@jant/core 0.2.17 → 0.2.18
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.
- package/dist/app.d.ts +1 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +319 -115
- package/dist/i18n/context.d.ts +2 -2
- package/dist/i18n/context.js +1 -1
- package/dist/i18n/i18n.d.ts +1 -1
- package/dist/i18n/i18n.js +1 -1
- package/dist/i18n/index.d.ts +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +1 -1
- package/dist/i18n/locales/zh-Hans.d.ts.map +1 -1
- package/dist/i18n/locales/zh-Hans.js +1 -1
- package/dist/i18n/locales/zh-Hant.d.ts.map +1 -1
- package/dist/i18n/locales/zh-Hant.js +1 -1
- package/dist/lib/config.d.ts +44 -10
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +69 -44
- package/dist/lib/constants.d.ts +2 -1
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +5 -2
- package/dist/lib/sse.d.ts +15 -0
- package/dist/lib/sse.d.ts.map +1 -1
- package/dist/lib/sse.js +13 -0
- package/dist/lib/theme.d.ts +44 -0
- package/dist/lib/theme.d.ts.map +1 -0
- package/dist/lib/theme.js +65 -0
- package/dist/routes/dash/appearance.d.ts +13 -0
- package/dist/routes/dash/appearance.d.ts.map +1 -0
- package/dist/routes/dash/appearance.js +164 -0
- package/dist/routes/dash/settings.d.ts.map +1 -1
- package/dist/routes/dash/settings.js +38 -37
- package/dist/services/settings.d.ts +1 -0
- package/dist/services/settings.d.ts.map +1 -1
- package/dist/services/settings.js +3 -0
- package/dist/theme/color-themes.d.ts +30 -0
- package/dist/theme/color-themes.d.ts.map +1 -0
- package/dist/theme/color-themes.js +268 -0
- package/dist/theme/layouts/BaseLayout.d.ts +5 -0
- package/dist/theme/layouts/BaseLayout.d.ts.map +1 -1
- package/dist/theme/layouts/BaseLayout.js +70 -3
- package/dist/theme/layouts/DashLayout.d.ts +2 -0
- package/dist/theme/layouts/DashLayout.d.ts.map +1 -1
- package/dist/theme/layouts/DashLayout.js +10 -1
- package/dist/theme/layouts/index.d.ts +1 -1
- package/dist/theme/layouts/index.d.ts.map +1 -1
- package/dist/types.d.ts +53 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +52 -0
- package/package.json +1 -1
- package/src/app.tsx +272 -55
- package/src/db/migrations/{0000_solid_moon_knight.sql → 0000_square_wallflower.sql} +3 -3
- package/src/db/migrations/meta/0000_snapshot.json +9 -9
- package/src/db/migrations/meta/_journal.json +2 -30
- package/src/i18n/context.tsx +2 -2
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/index.ts +1 -1
- package/src/i18n/locales/en.po +328 -252
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +315 -278
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +315 -278
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/lib/config.ts +73 -47
- package/src/lib/constants.ts +3 -0
- package/src/lib/sse.ts +38 -0
- package/src/lib/theme.ts +86 -0
- package/src/preset.css +9 -0
- package/src/routes/dash/appearance.tsx +180 -0
- package/src/routes/dash/settings.tsx +50 -52
- package/src/services/settings.ts +5 -0
- package/src/styles/components.css +93 -0
- package/src/theme/color-themes.ts +321 -0
- package/src/theme/layouts/BaseLayout.tsx +61 -1
- package/src/theme/layouts/DashLayout.tsx +13 -2
- package/src/theme/layouts/index.ts +5 -1
- package/src/types.ts +62 -1
- package/src/db/migrations/0001_add_search_fts.sql +0 -40
- package/src/db/migrations/0002_collection_path.sql +0 -2
- package/src/db/migrations/0003_collection_path_nullable.sql +0 -21
- package/src/db/migrations/0004_media_uuid.sql +0 -35
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Dashboard Appearance Routes
|
|
4
|
+
*/ import { Hono } from "hono";
|
|
5
|
+
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
6
|
+
import { DashLayout } from "../../theme/layouts/index.js";
|
|
7
|
+
import { sse } from "../../lib/sse.js";
|
|
8
|
+
import { getSiteName } from "../../lib/config.js";
|
|
9
|
+
import { SETTINGS_KEYS } from "../../lib/constants.js";
|
|
10
|
+
import { getAvailableThemes } from "../../lib/theme.js";
|
|
11
|
+
export const appearanceRoutes = new Hono();
|
|
12
|
+
function ThemeCard({ theme, selected }) {
|
|
13
|
+
const expr = `$theme === '${theme.id}'`;
|
|
14
|
+
const { preview } = theme;
|
|
15
|
+
return /*#__PURE__*/ _jsx("label", {
|
|
16
|
+
class: `block cursor-pointer rounded-lg border overflow-hidden transition-colors ${selected ? "border-primary" : "border-border"}`,
|
|
17
|
+
"data-class:border-primary": expr,
|
|
18
|
+
"data-class:border-border": `$theme !== '${theme.id}'`,
|
|
19
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
20
|
+
class: "grid grid-cols-2",
|
|
21
|
+
children: [
|
|
22
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
23
|
+
class: "p-5",
|
|
24
|
+
style: `background-color:${preview.lightBg};color:${preview.lightText}`,
|
|
25
|
+
children: [
|
|
26
|
+
/*#__PURE__*/ _jsx("input", {
|
|
27
|
+
type: "radio",
|
|
28
|
+
name: "theme",
|
|
29
|
+
value: theme.id,
|
|
30
|
+
"data-bind": "theme",
|
|
31
|
+
checked: selected || undefined,
|
|
32
|
+
class: "mb-1"
|
|
33
|
+
}),
|
|
34
|
+
/*#__PURE__*/ _jsx("h3", {
|
|
35
|
+
class: "font-bold text-lg",
|
|
36
|
+
children: theme.name
|
|
37
|
+
}),
|
|
38
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
39
|
+
class: "text-sm mt-2 leading-relaxed",
|
|
40
|
+
children: [
|
|
41
|
+
"This is the ",
|
|
42
|
+
theme.name,
|
|
43
|
+
" theme in light mode. Links",
|
|
44
|
+
" ",
|
|
45
|
+
/*#__PURE__*/ _jsx("a", {
|
|
46
|
+
tabIndex: -1,
|
|
47
|
+
class: "underline",
|
|
48
|
+
style: `color:${preview.lightLink}`,
|
|
49
|
+
children: "look like this"
|
|
50
|
+
}),
|
|
51
|
+
". We'll show the correct light or dark mode based on your visitor's settings."
|
|
52
|
+
]
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
}),
|
|
56
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
57
|
+
class: "p-5",
|
|
58
|
+
style: `background-color:${preview.darkBg};color:${preview.darkText}`,
|
|
59
|
+
children: [
|
|
60
|
+
/*#__PURE__*/ _jsx("h3", {
|
|
61
|
+
class: "font-bold text-lg",
|
|
62
|
+
children: theme.name
|
|
63
|
+
}),
|
|
64
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
65
|
+
class: "text-sm mt-2 leading-relaxed",
|
|
66
|
+
children: [
|
|
67
|
+
"This is the ",
|
|
68
|
+
theme.name,
|
|
69
|
+
" theme in dark mode. Links",
|
|
70
|
+
" ",
|
|
71
|
+
/*#__PURE__*/ _jsx("a", {
|
|
72
|
+
tabIndex: -1,
|
|
73
|
+
class: "underline",
|
|
74
|
+
style: `color:${preview.darkLink}`,
|
|
75
|
+
children: "look like this"
|
|
76
|
+
}),
|
|
77
|
+
". We'll show the correct light or dark mode based on your visitor's settings."
|
|
78
|
+
]
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function AppearanceContent({ themes, currentThemeId }) {
|
|
87
|
+
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
88
|
+
const signals = JSON.stringify({
|
|
89
|
+
theme: currentThemeId
|
|
90
|
+
}).replace(/</g, "\\u003c");
|
|
91
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
92
|
+
"data-signals": signals,
|
|
93
|
+
"data-on:change": "@post('/dash/appearance')",
|
|
94
|
+
class: "max-w-3xl",
|
|
95
|
+
children: /*#__PURE__*/ _jsxs("fieldset", {
|
|
96
|
+
children: [
|
|
97
|
+
/*#__PURE__*/ _jsx("legend", {
|
|
98
|
+
class: "text-lg font-semibold",
|
|
99
|
+
children: $__i18n._({
|
|
100
|
+
id: "rFmBG3",
|
|
101
|
+
message: "Color theme"
|
|
102
|
+
})
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ _jsx("p", {
|
|
105
|
+
class: "text-sm text-muted-foreground mb-4",
|
|
106
|
+
children: $__i18n._({
|
|
107
|
+
id: "07Epll",
|
|
108
|
+
message: "This will theme both your site and your dashboard. All color themes support dark mode."
|
|
109
|
+
})
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ _jsx("div", {
|
|
112
|
+
class: "flex flex-col gap-4",
|
|
113
|
+
children: themes.map((theme)=>/*#__PURE__*/ _jsx(ThemeCard, {
|
|
114
|
+
theme: theme,
|
|
115
|
+
selected: theme.id === currentThemeId
|
|
116
|
+
}, theme.id))
|
|
117
|
+
})
|
|
118
|
+
]
|
|
119
|
+
})
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Appearance page
|
|
123
|
+
appearanceRoutes.get("/", async (c)=>{
|
|
124
|
+
const { settings } = c.var.services;
|
|
125
|
+
const siteName = await getSiteName(c);
|
|
126
|
+
const currentThemeId = await settings.get(SETTINGS_KEYS.THEME) ?? "default";
|
|
127
|
+
const themes = getAvailableThemes(c.var.config);
|
|
128
|
+
const saved = c.req.query("saved") !== undefined;
|
|
129
|
+
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
130
|
+
c: c,
|
|
131
|
+
title: "Appearance",
|
|
132
|
+
siteName: siteName,
|
|
133
|
+
currentPath: "/dash/appearance",
|
|
134
|
+
toast: saved ? {
|
|
135
|
+
message: "Theme saved successfully."
|
|
136
|
+
} : undefined,
|
|
137
|
+
children: /*#__PURE__*/ _jsx(AppearanceContent, {
|
|
138
|
+
themes: themes,
|
|
139
|
+
currentThemeId: currentThemeId
|
|
140
|
+
})
|
|
141
|
+
}));
|
|
142
|
+
});
|
|
143
|
+
// Save theme
|
|
144
|
+
appearanceRoutes.post("/", async (c)=>{
|
|
145
|
+
const body = await c.req.json();
|
|
146
|
+
const { settings } = c.var.services;
|
|
147
|
+
const themes = getAvailableThemes(c.var.config);
|
|
148
|
+
// Validate theme ID
|
|
149
|
+
const validTheme = themes.find((t)=>t.id === body.theme);
|
|
150
|
+
if (!validTheme) {
|
|
151
|
+
return sse(c, async (stream)=>{
|
|
152
|
+
await stream.toast("Invalid theme selected.", "error");
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (validTheme.id === "default") {
|
|
156
|
+
await settings.remove(SETTINGS_KEYS.THEME);
|
|
157
|
+
} else {
|
|
158
|
+
await settings.set(SETTINGS_KEYS.THEME, validTheme.id);
|
|
159
|
+
}
|
|
160
|
+
// Full page reload to apply the new theme CSS
|
|
161
|
+
return sse(c, async (stream)=>{
|
|
162
|
+
await stream.redirect("/dash/appearance?saved");
|
|
163
|
+
});
|
|
164
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/settings.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/routes/dash/settings.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAKjD,KAAK,GAAG,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,cAAc,kDAAkB,CAAC"}
|
|
@@ -5,9 +5,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-
|
|
|
5
5
|
import { useLingui as $_useLingui } from "@jant/core/i18n";
|
|
6
6
|
import { DashLayout } from "../../theme/layouts/index.js";
|
|
7
7
|
import { sse } from "../../lib/sse.js";
|
|
8
|
-
import {
|
|
8
|
+
import { getSiteLanguage, getConfigFallback } from "../../lib/config.js";
|
|
9
9
|
export const settingsRoutes = new Hono();
|
|
10
|
-
function SettingsContent({ siteName, siteDescription, siteLanguage,
|
|
10
|
+
function SettingsContent({ siteName, siteDescription, siteLanguage, siteNameFallback, siteDescriptionFallback }) {
|
|
11
11
|
const { i18n: $__i18n, _: $__ } = $_useLingui();
|
|
12
12
|
const generalSignals = JSON.stringify({
|
|
13
13
|
siteName,
|
|
@@ -23,17 +23,6 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
23
23
|
message: "Settings"
|
|
24
24
|
})
|
|
25
25
|
}),
|
|
26
|
-
saved && /*#__PURE__*/ _jsx("div", {
|
|
27
|
-
id: "settings-saved-toast",
|
|
28
|
-
class: "alert mb-4 max-w-lg transition-opacity duration-300",
|
|
29
|
-
"data-init": `console.log('[toast] init fired at', Date.now()); history.replaceState({}, '', '/dash/settings'); setTimeout(() => { console.log('[toast] hiding at', Date.now()); const el = document.getElementById('settings-saved-toast'); if (el) { el.style.opacity = '0'; setTimeout(() => el.remove(), 300) } }, 3000)`,
|
|
30
|
-
children: /*#__PURE__*/ _jsx("h2", {
|
|
31
|
-
children: $__i18n._({
|
|
32
|
-
id: "T0bsor",
|
|
33
|
-
message: "Settings saved successfully."
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
}),
|
|
37
26
|
/*#__PURE__*/ _jsxs("div", {
|
|
38
27
|
class: "flex flex-col gap-6 max-w-lg",
|
|
39
28
|
children: [
|
|
@@ -41,9 +30,6 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
41
30
|
"data-signals": generalSignals,
|
|
42
31
|
"data-on:submit__prevent": "@post('/dash/settings')",
|
|
43
32
|
children: [
|
|
44
|
-
/*#__PURE__*/ _jsx("div", {
|
|
45
|
-
id: "settings-message"
|
|
46
|
-
}),
|
|
47
33
|
/*#__PURE__*/ _jsxs("div", {
|
|
48
34
|
class: "card",
|
|
49
35
|
children: [
|
|
@@ -72,7 +58,7 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
72
58
|
type: "text",
|
|
73
59
|
"data-bind": "siteName",
|
|
74
60
|
class: "input",
|
|
75
|
-
|
|
61
|
+
placeholder: siteNameFallback
|
|
76
62
|
})
|
|
77
63
|
]
|
|
78
64
|
}),
|
|
@@ -90,6 +76,7 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
90
76
|
"data-bind": "siteDescription",
|
|
91
77
|
class: "textarea",
|
|
92
78
|
rows: 3,
|
|
79
|
+
placeholder: siteDescriptionFallback,
|
|
93
80
|
children: siteDescription
|
|
94
81
|
})
|
|
95
82
|
]
|
|
@@ -145,9 +132,6 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
145
132
|
"data-signals": "{currentPassword: '', newPassword: '', confirmPassword: ''}",
|
|
146
133
|
"data-on:submit__prevent": "@post('/dash/settings/password')",
|
|
147
134
|
children: [
|
|
148
|
-
/*#__PURE__*/ _jsx("div", {
|
|
149
|
-
id: "password-message"
|
|
150
|
-
}),
|
|
151
135
|
/*#__PURE__*/ _jsxs("div", {
|
|
152
136
|
class: "card",
|
|
153
137
|
children: [
|
|
@@ -242,40 +226,57 @@ function SettingsContent({ siteName, siteDescription, siteLanguage, saved }) {
|
|
|
242
226
|
}
|
|
243
227
|
// Settings page
|
|
244
228
|
settingsRoutes.get("/", async (c)=>{
|
|
245
|
-
const
|
|
246
|
-
|
|
229
|
+
const { settings } = c.var.services;
|
|
230
|
+
// Fetch raw DB values (null if not set)
|
|
231
|
+
const dbSiteName = await settings.get("SITE_NAME");
|
|
232
|
+
const dbSiteDescription = await settings.get("SITE_DESCRIPTION");
|
|
247
233
|
const siteLanguage = await getSiteLanguage(c);
|
|
234
|
+
// Fallback values (ENV > Default) for placeholders
|
|
235
|
+
const siteNameFallback = getConfigFallback(c, "SITE_NAME");
|
|
236
|
+
const siteDescriptionFallback = getConfigFallback(c, "SITE_DESCRIPTION");
|
|
248
237
|
const saved = c.req.query("saved") !== undefined;
|
|
249
238
|
return c.html(/*#__PURE__*/ _jsx(DashLayout, {
|
|
250
239
|
c: c,
|
|
251
240
|
title: "Settings",
|
|
252
|
-
siteName:
|
|
241
|
+
siteName: dbSiteName || siteNameFallback,
|
|
253
242
|
currentPath: "/dash/settings",
|
|
243
|
+
toast: saved ? {
|
|
244
|
+
message: "Settings saved successfully."
|
|
245
|
+
} : undefined,
|
|
254
246
|
children: /*#__PURE__*/ _jsx(SettingsContent, {
|
|
255
|
-
siteName:
|
|
256
|
-
siteDescription:
|
|
247
|
+
siteName: dbSiteName || "",
|
|
248
|
+
siteDescription: dbSiteDescription || "",
|
|
257
249
|
siteLanguage: siteLanguage,
|
|
258
|
-
|
|
250
|
+
siteNameFallback: siteNameFallback,
|
|
251
|
+
siteDescriptionFallback: siteDescriptionFallback
|
|
259
252
|
})
|
|
260
253
|
}));
|
|
261
254
|
});
|
|
262
255
|
// Update settings
|
|
263
256
|
settingsRoutes.post("/", async (c)=>{
|
|
264
257
|
const body = await c.req.json();
|
|
265
|
-
const
|
|
266
|
-
await
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
258
|
+
const { settings } = c.var.services;
|
|
259
|
+
const oldLanguage = await settings.get("SITE_LANGUAGE") ?? "en";
|
|
260
|
+
// For text fields: empty = remove from DB (fall back to ENV > Default)
|
|
261
|
+
if (body.siteName.trim()) {
|
|
262
|
+
await settings.set("SITE_NAME", body.siteName.trim());
|
|
263
|
+
} else {
|
|
264
|
+
await settings.remove("SITE_NAME");
|
|
265
|
+
}
|
|
266
|
+
if (body.siteDescription.trim()) {
|
|
267
|
+
await settings.set("SITE_DESCRIPTION", body.siteDescription.trim());
|
|
268
|
+
} else {
|
|
269
|
+
await settings.remove("SITE_DESCRIPTION");
|
|
270
|
+
}
|
|
271
|
+
// Language always has a value from the select
|
|
272
|
+
await settings.set("SITE_LANGUAGE", body.siteLanguage);
|
|
271
273
|
const languageChanged = oldLanguage !== body.siteLanguage;
|
|
272
274
|
return sse(c, async (stream)=>{
|
|
273
275
|
if (languageChanged) {
|
|
274
276
|
// Language changed - full reload needed to update all UI text
|
|
275
277
|
await stream.redirect("/dash/settings?saved");
|
|
276
278
|
} else {
|
|
277
|
-
|
|
278
|
-
await stream.patchElements('<div id="settings-message"><div class="alert mb-4 transition-opacity duration-300" data-init="setTimeout(() => { el.style.opacity = \'0\'; setTimeout(() => el.remove(), 300) }, 3000)"><h2>Settings saved successfully.</h2></div></div>');
|
|
279
|
+
await stream.toast("Settings saved successfully.");
|
|
279
280
|
}
|
|
280
281
|
});
|
|
281
282
|
});
|
|
@@ -284,7 +285,7 @@ settingsRoutes.post("/password", async (c)=>{
|
|
|
284
285
|
const body = await c.req.json();
|
|
285
286
|
if (body.newPassword !== body.confirmPassword) {
|
|
286
287
|
return sse(c, async (stream)=>{
|
|
287
|
-
await stream.
|
|
288
|
+
await stream.toast("Passwords do not match.", "error");
|
|
288
289
|
});
|
|
289
290
|
}
|
|
290
291
|
try {
|
|
@@ -298,11 +299,11 @@ settingsRoutes.post("/password", async (c)=>{
|
|
|
298
299
|
});
|
|
299
300
|
} catch {
|
|
300
301
|
return sse(c, async (stream)=>{
|
|
301
|
-
await stream.
|
|
302
|
+
await stream.toast("Current password is incorrect.", "error");
|
|
302
303
|
});
|
|
303
304
|
}
|
|
304
305
|
return sse(c, async (stream)=>{
|
|
305
|
-
await stream.
|
|
306
|
+
await stream.toast("Password changed successfully.");
|
|
306
307
|
await stream.patchSignals({
|
|
307
308
|
currentPassword: "",
|
|
308
309
|
newPassword: "",
|
|
@@ -10,6 +10,7 @@ export interface SettingsService {
|
|
|
10
10
|
getAll(): Promise<Record<string, string>>;
|
|
11
11
|
set(key: SettingsKey, value: string): Promise<void>;
|
|
12
12
|
setMany(entries: Partial<Record<SettingsKey, string>>): Promise<void>;
|
|
13
|
+
remove(key: SettingsKey): Promise<void>;
|
|
13
14
|
isOnboardingComplete(): Promise<boolean>;
|
|
14
15
|
completeOnboarding(): Promise<void>;
|
|
15
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/services/settings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/services/settings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1C,GAAG,CAAC,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,eAAe,CAiEnE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Color Themes
|
|
3
|
+
*
|
|
4
|
+
* Each theme defines CSS variable overrides for light and dark modes,
|
|
5
|
+
* plus preview colors for the theme picker UI.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A color theme definition with light and dark mode CSS variable overrides.
|
|
9
|
+
*/
|
|
10
|
+
export interface ColorTheme {
|
|
11
|
+
/** Stored in DB settings, e.g. "beach" */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Display name, e.g. "Beach" */
|
|
14
|
+
name: string;
|
|
15
|
+
/** CSS variable overrides for :root (light mode) */
|
|
16
|
+
light: Record<string, string>;
|
|
17
|
+
/** CSS variable overrides for .dark (dark mode) */
|
|
18
|
+
dark: Record<string, string>;
|
|
19
|
+
/** Preview colors (hex) for theme picker cards */
|
|
20
|
+
preview: {
|
|
21
|
+
lightBg: string;
|
|
22
|
+
lightText: string;
|
|
23
|
+
lightLink: string;
|
|
24
|
+
darkBg: string;
|
|
25
|
+
darkText: string;
|
|
26
|
+
darkLink: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare const BUILTIN_COLOR_THEMES: ColorTheme[];
|
|
30
|
+
//# sourceMappingURL=color-themes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-themes.d.ts","sourceRoot":"","sources":["../../src/theme/color-themes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,kDAAkD;IAClD,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AA2FD,eAAO,MAAM,oBAAoB,EAAE,UAAU,EAyM5C,CAAC"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Color Themes
|
|
3
|
+
*
|
|
4
|
+
* Each theme defines CSS variable overrides for light and dark modes,
|
|
5
|
+
* plus preview colors for the theme picker UI.
|
|
6
|
+
*/ /**
|
|
7
|
+
* A color theme definition with light and dark mode CSS variable overrides.
|
|
8
|
+
*/ /**
|
|
9
|
+
* Create a comprehensive color theme from key colors.
|
|
10
|
+
* Derives card, popover, muted, secondary, accent, and sidebar variables.
|
|
11
|
+
*/ function defineTheme(opts) {
|
|
12
|
+
const { light, dark } = opts;
|
|
13
|
+
return {
|
|
14
|
+
id: opts.id,
|
|
15
|
+
name: opts.name,
|
|
16
|
+
preview: opts.preview,
|
|
17
|
+
light: {
|
|
18
|
+
"--background": light.bg,
|
|
19
|
+
"--foreground": light.fg,
|
|
20
|
+
"--card": light.bg,
|
|
21
|
+
"--card-foreground": light.fg,
|
|
22
|
+
"--popover": light.bg,
|
|
23
|
+
"--popover-foreground": light.fg,
|
|
24
|
+
"--primary": light.primary,
|
|
25
|
+
"--primary-foreground": light.primaryFg,
|
|
26
|
+
"--secondary": light.muted,
|
|
27
|
+
"--secondary-foreground": light.fg,
|
|
28
|
+
"--muted": light.muted,
|
|
29
|
+
"--muted-foreground": light.mutedFg,
|
|
30
|
+
"--accent": light.muted,
|
|
31
|
+
"--accent-foreground": light.fg,
|
|
32
|
+
"--border": light.border,
|
|
33
|
+
"--input": light.border,
|
|
34
|
+
"--ring": light.primary,
|
|
35
|
+
"--sidebar": light.bg,
|
|
36
|
+
"--sidebar-foreground": light.fg,
|
|
37
|
+
"--sidebar-primary": light.primary,
|
|
38
|
+
"--sidebar-primary-foreground": light.primaryFg,
|
|
39
|
+
"--sidebar-accent": light.muted,
|
|
40
|
+
"--sidebar-accent-foreground": light.fg,
|
|
41
|
+
"--sidebar-border": light.border,
|
|
42
|
+
"--sidebar-ring": light.primary
|
|
43
|
+
},
|
|
44
|
+
dark: {
|
|
45
|
+
"--background": dark.bg,
|
|
46
|
+
"--foreground": dark.fg,
|
|
47
|
+
"--card": dark.bg,
|
|
48
|
+
"--card-foreground": dark.fg,
|
|
49
|
+
"--popover": dark.bg,
|
|
50
|
+
"--popover-foreground": dark.fg,
|
|
51
|
+
"--primary": dark.primary,
|
|
52
|
+
"--primary-foreground": dark.primaryFg,
|
|
53
|
+
"--secondary": dark.muted,
|
|
54
|
+
"--secondary-foreground": dark.fg,
|
|
55
|
+
"--muted": dark.muted,
|
|
56
|
+
"--muted-foreground": dark.mutedFg,
|
|
57
|
+
"--accent": dark.muted,
|
|
58
|
+
"--accent-foreground": dark.fg,
|
|
59
|
+
"--border": dark.border,
|
|
60
|
+
"--input": dark.border,
|
|
61
|
+
"--ring": dark.primary,
|
|
62
|
+
"--sidebar": dark.bg,
|
|
63
|
+
"--sidebar-foreground": dark.fg,
|
|
64
|
+
"--sidebar-primary": dark.primary,
|
|
65
|
+
"--sidebar-primary-foreground": dark.primaryFg,
|
|
66
|
+
"--sidebar-accent": dark.muted,
|
|
67
|
+
"--sidebar-accent-foreground": dark.fg,
|
|
68
|
+
"--sidebar-border": dark.border,
|
|
69
|
+
"--sidebar-ring": dark.primary
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export const BUILTIN_COLOR_THEMES = [
|
|
74
|
+
{
|
|
75
|
+
id: "default",
|
|
76
|
+
name: "Default",
|
|
77
|
+
light: {},
|
|
78
|
+
dark: {},
|
|
79
|
+
preview: {
|
|
80
|
+
lightBg: "#ffffff",
|
|
81
|
+
lightText: "#1e1e1e",
|
|
82
|
+
lightLink: "#1e1e1e",
|
|
83
|
+
darkBg: "#262626",
|
|
84
|
+
darkText: "#fafafa",
|
|
85
|
+
darkLink: "#eaeaea"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
defineTheme({
|
|
89
|
+
id: "beach",
|
|
90
|
+
name: "Beach",
|
|
91
|
+
preview: {
|
|
92
|
+
lightBg: "#f9f3ea",
|
|
93
|
+
lightText: "#3d3527",
|
|
94
|
+
lightLink: "#2d6a59",
|
|
95
|
+
darkBg: "#2d4553",
|
|
96
|
+
darkText: "#e2d6c4",
|
|
97
|
+
darkLink: "#7cc5a2"
|
|
98
|
+
},
|
|
99
|
+
light: {
|
|
100
|
+
bg: "oklch(0.97 0.01 85)",
|
|
101
|
+
fg: "oklch(0.28 0.02 65)",
|
|
102
|
+
primary: "oklch(0.46 0.1 170)",
|
|
103
|
+
primaryFg: "oklch(0.98 0.005 85)",
|
|
104
|
+
muted: "oklch(0.93 0.015 85)",
|
|
105
|
+
mutedFg: "oklch(0.52 0.015 65)",
|
|
106
|
+
border: "oklch(0.88 0.018 85)"
|
|
107
|
+
},
|
|
108
|
+
dark: {
|
|
109
|
+
bg: "oklch(0.27 0.03 210)",
|
|
110
|
+
fg: "oklch(0.88 0.015 80)",
|
|
111
|
+
primary: "oklch(0.72 0.1 165)",
|
|
112
|
+
primaryFg: "oklch(0.22 0.03 210)",
|
|
113
|
+
muted: "oklch(0.33 0.025 210)",
|
|
114
|
+
mutedFg: "oklch(0.65 0.015 80)",
|
|
115
|
+
border: "oklch(0.38 0.02 210)"
|
|
116
|
+
}
|
|
117
|
+
}),
|
|
118
|
+
defineTheme({
|
|
119
|
+
id: "gameboy",
|
|
120
|
+
name: "Gameboy",
|
|
121
|
+
preview: {
|
|
122
|
+
lightBg: "#d3d7c0",
|
|
123
|
+
lightText: "#2b3326",
|
|
124
|
+
lightLink: "#466740",
|
|
125
|
+
darkBg: "#1b1f18",
|
|
126
|
+
darkText: "#a6b09a",
|
|
127
|
+
darkLink: "#6d9660"
|
|
128
|
+
},
|
|
129
|
+
light: {
|
|
130
|
+
bg: "oklch(0.87 0.03 130)",
|
|
131
|
+
fg: "oklch(0.25 0.04 140)",
|
|
132
|
+
primary: "oklch(0.4 0.08 145)",
|
|
133
|
+
primaryFg: "oklch(0.92 0.02 130)",
|
|
134
|
+
muted: "oklch(0.83 0.035 130)",
|
|
135
|
+
mutedFg: "oklch(0.48 0.03 140)",
|
|
136
|
+
border: "oklch(0.79 0.035 130)"
|
|
137
|
+
},
|
|
138
|
+
dark: {
|
|
139
|
+
bg: "oklch(0.18 0.02 140)",
|
|
140
|
+
fg: "oklch(0.78 0.025 130)",
|
|
141
|
+
primary: "oklch(0.6 0.08 145)",
|
|
142
|
+
primaryFg: "oklch(0.15 0.02 140)",
|
|
143
|
+
muted: "oklch(0.24 0.02 140)",
|
|
144
|
+
mutedFg: "oklch(0.58 0.02 130)",
|
|
145
|
+
border: "oklch(0.3 0.02 140)"
|
|
146
|
+
}
|
|
147
|
+
}),
|
|
148
|
+
defineTheme({
|
|
149
|
+
id: "grayscale",
|
|
150
|
+
name: "Grayscale",
|
|
151
|
+
preview: {
|
|
152
|
+
lightBg: "#efefef",
|
|
153
|
+
lightText: "#3a3a3a",
|
|
154
|
+
lightLink: "#555555",
|
|
155
|
+
darkBg: "#1e1e1e",
|
|
156
|
+
darkText: "#c8c8c8",
|
|
157
|
+
darkLink: "#999999"
|
|
158
|
+
},
|
|
159
|
+
light: {
|
|
160
|
+
bg: "oklch(0.96 0 0)",
|
|
161
|
+
fg: "oklch(0.3 0 0)",
|
|
162
|
+
primary: "oklch(0.4 0 0)",
|
|
163
|
+
primaryFg: "oklch(0.96 0 0)",
|
|
164
|
+
muted: "oklch(0.92 0 0)",
|
|
165
|
+
mutedFg: "oklch(0.55 0 0)",
|
|
166
|
+
border: "oklch(0.87 0 0)"
|
|
167
|
+
},
|
|
168
|
+
dark: {
|
|
169
|
+
bg: "oklch(0.18 0 0)",
|
|
170
|
+
fg: "oklch(0.82 0 0)",
|
|
171
|
+
primary: "oklch(0.7 0 0)",
|
|
172
|
+
primaryFg: "oklch(0.18 0 0)",
|
|
173
|
+
muted: "oklch(0.24 0 0)",
|
|
174
|
+
mutedFg: "oklch(0.6 0 0)",
|
|
175
|
+
border: "oklch(0.3 0 0)"
|
|
176
|
+
}
|
|
177
|
+
}),
|
|
178
|
+
defineTheme({
|
|
179
|
+
id: "halloween",
|
|
180
|
+
name: "Halloween",
|
|
181
|
+
preview: {
|
|
182
|
+
lightBg: "#f9f2e3",
|
|
183
|
+
lightText: "#352200",
|
|
184
|
+
lightLink: "#cc5500",
|
|
185
|
+
darkBg: "#1e1000",
|
|
186
|
+
darkText: "#dfc390",
|
|
187
|
+
darkLink: "#ff8c00"
|
|
188
|
+
},
|
|
189
|
+
light: {
|
|
190
|
+
bg: "oklch(0.97 0.015 75)",
|
|
191
|
+
fg: "oklch(0.25 0.04 55)",
|
|
192
|
+
primary: "oklch(0.6 0.2 50)",
|
|
193
|
+
primaryFg: "oklch(0.98 0.01 75)",
|
|
194
|
+
muted: "oklch(0.93 0.02 75)",
|
|
195
|
+
mutedFg: "oklch(0.5 0.025 55)",
|
|
196
|
+
border: "oklch(0.88 0.025 75)"
|
|
197
|
+
},
|
|
198
|
+
dark: {
|
|
199
|
+
bg: "oklch(0.16 0.03 50)",
|
|
200
|
+
fg: "oklch(0.85 0.025 75)",
|
|
201
|
+
primary: "oklch(0.72 0.19 55)",
|
|
202
|
+
primaryFg: "oklch(0.14 0.03 50)",
|
|
203
|
+
muted: "oklch(0.22 0.025 50)",
|
|
204
|
+
mutedFg: "oklch(0.62 0.02 75)",
|
|
205
|
+
border: "oklch(0.28 0.025 50)"
|
|
206
|
+
}
|
|
207
|
+
}),
|
|
208
|
+
defineTheme({
|
|
209
|
+
id: "notepad",
|
|
210
|
+
name: "Notepad",
|
|
211
|
+
preview: {
|
|
212
|
+
lightBg: "#fdfce8",
|
|
213
|
+
lightText: "#333333",
|
|
214
|
+
lightLink: "#2060b8",
|
|
215
|
+
darkBg: "#2a291a",
|
|
216
|
+
darkText: "#d2d2b8",
|
|
217
|
+
darkLink: "#6695cc"
|
|
218
|
+
},
|
|
219
|
+
light: {
|
|
220
|
+
bg: "oklch(0.985 0.018 95)",
|
|
221
|
+
fg: "oklch(0.27 0 0)",
|
|
222
|
+
primary: "oklch(0.5 0.17 260)",
|
|
223
|
+
primaryFg: "oklch(0.985 0.01 95)",
|
|
224
|
+
muted: "oklch(0.94 0.022 95)",
|
|
225
|
+
mutedFg: "oklch(0.52 0 0)",
|
|
226
|
+
border: "oklch(0.88 0.025 95)"
|
|
227
|
+
},
|
|
228
|
+
dark: {
|
|
229
|
+
bg: "oklch(0.2 0.02 90)",
|
|
230
|
+
fg: "oklch(0.87 0.015 95)",
|
|
231
|
+
primary: "oklch(0.65 0.14 260)",
|
|
232
|
+
primaryFg: "oklch(0.98 0.01 95)",
|
|
233
|
+
muted: "oklch(0.26 0.018 90)",
|
|
234
|
+
mutedFg: "oklch(0.62 0.012 95)",
|
|
235
|
+
border: "oklch(0.32 0.018 90)"
|
|
236
|
+
}
|
|
237
|
+
}),
|
|
238
|
+
defineTheme({
|
|
239
|
+
id: "sonnet",
|
|
240
|
+
name: "Sonnet",
|
|
241
|
+
preview: {
|
|
242
|
+
lightBg: "#f7eef5",
|
|
243
|
+
lightText: "#2e1e2c",
|
|
244
|
+
lightLink: "#9845c8",
|
|
245
|
+
darkBg: "#1d1428",
|
|
246
|
+
darkText: "#d4c2d0",
|
|
247
|
+
darkLink: "#c080fc"
|
|
248
|
+
},
|
|
249
|
+
light: {
|
|
250
|
+
bg: "oklch(0.97 0.012 325)",
|
|
251
|
+
fg: "oklch(0.25 0.02 310)",
|
|
252
|
+
primary: "oklch(0.55 0.2 300)",
|
|
253
|
+
primaryFg: "oklch(0.98 0.008 325)",
|
|
254
|
+
muted: "oklch(0.93 0.016 325)",
|
|
255
|
+
mutedFg: "oklch(0.52 0.015 310)",
|
|
256
|
+
border: "oklch(0.88 0.016 325)"
|
|
257
|
+
},
|
|
258
|
+
dark: {
|
|
259
|
+
bg: "oklch(0.18 0.025 300)",
|
|
260
|
+
fg: "oklch(0.87 0.012 325)",
|
|
261
|
+
primary: "oklch(0.72 0.18 300)",
|
|
262
|
+
primaryFg: "oklch(0.98 0.008 325)",
|
|
263
|
+
muted: "oklch(0.24 0.022 300)",
|
|
264
|
+
mutedFg: "oklch(0.62 0.012 325)",
|
|
265
|
+
border: "oklch(0.3 0.022 300)"
|
|
266
|
+
}
|
|
267
|
+
})
|
|
268
|
+
];
|