@otmc/ui 0.1.2 → 0.1.4
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/index.cjs +470 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -2
- package/dist/index.d.ts +80 -2
- package/dist/index.js +512 -64
- package/dist/index.js.map +1 -1
- package/package.json +65 -60
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/branding/Footer.tsx
|
|
2
2
|
import { Stack, Group, Text, Anchor, Tooltip, ActionIcon } from "@mantine/core";
|
|
3
|
+
import { Copyright } from "lucide-react";
|
|
3
4
|
import {
|
|
4
|
-
IconCopyright,
|
|
5
5
|
IconHeart,
|
|
6
6
|
IconBrandFacebook,
|
|
7
7
|
IconBrandGithub,
|
|
@@ -56,7 +56,7 @@ function Footer({
|
|
|
56
56
|
"Copyright",
|
|
57
57
|
" "
|
|
58
58
|
] }),
|
|
59
|
-
/* @__PURE__ */ jsx(
|
|
59
|
+
/* @__PURE__ */ jsx(Copyright, { size: 15, color: "var(--mantine-color-dimmed)" }),
|
|
60
60
|
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
61
61
|
(/* @__PURE__ */ new Date()).getFullYear(),
|
|
62
62
|
" ",
|
|
@@ -100,35 +100,376 @@ function Footer({
|
|
|
100
100
|
] });
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// src/
|
|
104
|
-
import { useState } from "react";
|
|
103
|
+
// src/components/ThemeMenu.tsx
|
|
105
104
|
import {
|
|
106
|
-
|
|
105
|
+
ActionIcon as ActionIcon2,
|
|
106
|
+
Menu,
|
|
107
|
+
Tooltip as Tooltip2
|
|
108
|
+
} from "@mantine/core";
|
|
109
|
+
import { Sun, Moon, Monitor, Clock } from "lucide-react";
|
|
110
|
+
|
|
111
|
+
// src/contexts/ThemeProvider.tsx
|
|
112
|
+
import { createContext, useContext, useEffect, useState } from "react";
|
|
113
|
+
import {
|
|
114
|
+
useMantineColorScheme
|
|
115
|
+
} from "@mantine/core";
|
|
116
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
117
|
+
var ThemeContext = createContext(null);
|
|
118
|
+
var useTheme = () => {
|
|
119
|
+
const ctx = useContext(ThemeContext);
|
|
120
|
+
if (!ctx) {
|
|
121
|
+
throw new Error("useTheme must be used inside ThemeProvider");
|
|
122
|
+
}
|
|
123
|
+
return ctx;
|
|
124
|
+
};
|
|
125
|
+
var resolveColorScheme = (colorScheme) => {
|
|
126
|
+
if (colorScheme === "auto") {
|
|
127
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
128
|
+
}
|
|
129
|
+
return colorScheme;
|
|
130
|
+
};
|
|
131
|
+
var resolveTimeBasedTheme = (settings) => {
|
|
132
|
+
const now = /* @__PURE__ */ new Date();
|
|
133
|
+
const minutes = now.getHours() * 60 + now.getMinutes();
|
|
134
|
+
const [lh, lm] = settings.lightStartTime.split(":").map(Number);
|
|
135
|
+
const [dh, dm] = settings.darkStartTime.split(":").map(Number);
|
|
136
|
+
const light = lh * 60 + lm;
|
|
137
|
+
const dark = dh * 60 + dm;
|
|
138
|
+
return light < dark ? minutes >= light && minutes < dark ? "light" : "dark" : minutes >= light || minutes < dark ? "light" : "dark";
|
|
139
|
+
};
|
|
140
|
+
var resolveAutoScheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
141
|
+
var ThemeProvider = ({
|
|
142
|
+
children,
|
|
143
|
+
defaultTheme = "auto",
|
|
144
|
+
defaultTimeBasedSettings = {
|
|
145
|
+
lightStartTime: "07:00",
|
|
146
|
+
darkStartTime: "19:00"
|
|
147
|
+
},
|
|
148
|
+
storagePrefix = ""
|
|
149
|
+
}) => {
|
|
150
|
+
const themeStorageKey = `${storagePrefix}theme`;
|
|
151
|
+
const timeStorageKey = `${storagePrefix}time-theme`;
|
|
152
|
+
const { colorScheme, setColorScheme } = useMantineColorScheme();
|
|
153
|
+
const [theme, setThemeState] = useState(
|
|
154
|
+
() => localStorage.getItem(themeStorageKey) ?? defaultTheme
|
|
155
|
+
);
|
|
156
|
+
const [timeBasedSettings, setTimeBasedSettings] = useState(
|
|
157
|
+
() => JSON.parse(localStorage.getItem(timeStorageKey) || "null") ?? defaultTimeBasedSettings
|
|
158
|
+
);
|
|
159
|
+
const handleSetTimeBasedSettings = (settings) => {
|
|
160
|
+
setTimeBasedSettings(settings);
|
|
161
|
+
localStorage.setItem(timeStorageKey, JSON.stringify(settings));
|
|
162
|
+
if (theme === "time-based") {
|
|
163
|
+
applyTheme("time-based");
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const applyTheme = (mode) => {
|
|
167
|
+
let scheme;
|
|
168
|
+
switch (mode) {
|
|
169
|
+
case "light":
|
|
170
|
+
case "dark":
|
|
171
|
+
case "auto":
|
|
172
|
+
scheme = mode;
|
|
173
|
+
break;
|
|
174
|
+
case "time-based":
|
|
175
|
+
scheme = resolveTimeBasedTheme(timeBasedSettings);
|
|
176
|
+
break;
|
|
177
|
+
default:
|
|
178
|
+
scheme = "auto";
|
|
179
|
+
}
|
|
180
|
+
setColorScheme(scheme);
|
|
181
|
+
};
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
applyTheme(theme);
|
|
184
|
+
}, [theme, timeBasedSettings]);
|
|
185
|
+
const setTheme = (mode) => {
|
|
186
|
+
setThemeState(mode);
|
|
187
|
+
localStorage.setItem(themeStorageKey, mode);
|
|
188
|
+
applyTheme(mode);
|
|
189
|
+
};
|
|
190
|
+
const toggleTheme = () => {
|
|
191
|
+
setTheme(colorScheme === "dark" ? "light" : "dark");
|
|
192
|
+
};
|
|
193
|
+
const currentTheme = theme === "time-based" ? resolveTimeBasedTheme(timeBasedSettings) : colorScheme === "auto" ? resolveAutoScheme() : colorScheme;
|
|
194
|
+
return /* @__PURE__ */ jsx2(
|
|
195
|
+
ThemeContext.Provider,
|
|
196
|
+
{
|
|
197
|
+
value: {
|
|
198
|
+
theme,
|
|
199
|
+
currentTheme,
|
|
200
|
+
setTheme,
|
|
201
|
+
toggleTheme,
|
|
202
|
+
timeBasedSettings,
|
|
203
|
+
setTimeBasedSettings: handleSetTimeBasedSettings
|
|
204
|
+
},
|
|
205
|
+
children
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// src/components/ThemeMenu.tsx
|
|
211
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
212
|
+
var DEFAULT_LABELS = {
|
|
213
|
+
tooltip: "Ch\u1EBF \u0111\u1ED9 giao di\u1EC7n",
|
|
214
|
+
title: "Ch\u1EBF \u0111\u1ED9 giao di\u1EC7n",
|
|
215
|
+
light: "S\xE1ng",
|
|
216
|
+
dark: "T\u1ED1i",
|
|
217
|
+
auto: "Theo h\u1EC7 th\u1ED1ng",
|
|
218
|
+
timeBased: "Theo th\u1EDDi gian"
|
|
219
|
+
};
|
|
220
|
+
var MODE_ICONS = {
|
|
221
|
+
light: /* @__PURE__ */ jsx3(Sun, { size: 16 }),
|
|
222
|
+
dark: /* @__PURE__ */ jsx3(Moon, { size: 16 }),
|
|
223
|
+
auto: /* @__PURE__ */ jsx3(Monitor, { size: 16 }),
|
|
224
|
+
"time-based": /* @__PURE__ */ jsx3(Clock, { size: 16 })
|
|
225
|
+
};
|
|
226
|
+
function ThemeMenu({
|
|
227
|
+
modes = ["light", "dark", "auto", "time-based"],
|
|
228
|
+
labels = {},
|
|
229
|
+
iconSize = 20,
|
|
230
|
+
size = "lg",
|
|
231
|
+
menuProps = {}
|
|
232
|
+
}) {
|
|
233
|
+
const { theme, currentTheme, setTheme } = useTheme();
|
|
234
|
+
const text = { ...DEFAULT_LABELS, ...labels };
|
|
235
|
+
const isDark = currentTheme === "dark";
|
|
236
|
+
const activeColor = isDark ? "yellow.8" : "blue.8";
|
|
237
|
+
const triggerIcon = theme === "light" ? /* @__PURE__ */ jsx3(Sun, { size: iconSize, strokeWidth: 2 }) : theme === "dark" ? /* @__PURE__ */ jsx3(Moon, { size: iconSize, strokeWidth: 2 }) : theme === "auto" ? /* @__PURE__ */ jsx3(Monitor, { size: iconSize, strokeWidth: 2 }) : /* @__PURE__ */ jsx3(Clock, { size: iconSize, strokeWidth: 2 });
|
|
238
|
+
return /* @__PURE__ */ jsxs2(Menu, { shadow: "md", width: 200, position: "bottom-end", ...menuProps, children: [
|
|
239
|
+
/* @__PURE__ */ jsx3(Menu.Target, { children: /* @__PURE__ */ jsx3(Tooltip2, { label: text.tooltip, position: "bottom", withArrow: true, children: /* @__PURE__ */ jsx3(
|
|
240
|
+
ActionIcon2,
|
|
241
|
+
{
|
|
242
|
+
variant: "subtle",
|
|
243
|
+
color: activeColor,
|
|
244
|
+
size,
|
|
245
|
+
radius: "lg",
|
|
246
|
+
style: {
|
|
247
|
+
boxShadow: isDark ? "0 0 15px rgba(250, 176, 5, 0.2)" : "0 0 15px rgba(34, 139, 230, 0.2)"
|
|
248
|
+
},
|
|
249
|
+
children: triggerIcon
|
|
250
|
+
}
|
|
251
|
+
) }) }),
|
|
252
|
+
/* @__PURE__ */ jsxs2(Menu.Dropdown, { style: { borderRadius: "11px" }, children: [
|
|
253
|
+
/* @__PURE__ */ jsx3(Menu.Label, { children: text.title }),
|
|
254
|
+
modes.map((mode) => /* @__PURE__ */ jsx3(
|
|
255
|
+
Menu.Item,
|
|
256
|
+
{
|
|
257
|
+
leftSection: MODE_ICONS[mode],
|
|
258
|
+
onClick: () => setTheme(mode),
|
|
259
|
+
color: theme === mode ? activeColor : void 0,
|
|
260
|
+
fw: theme === mode ? 700 : 400,
|
|
261
|
+
children: text[mode === "time-based" ? "timeBased" : mode]
|
|
262
|
+
},
|
|
263
|
+
mode
|
|
264
|
+
))
|
|
265
|
+
] })
|
|
266
|
+
] });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/components/ThemeSetting.tsx
|
|
270
|
+
import {
|
|
271
|
+
Box,
|
|
272
|
+
Card,
|
|
273
|
+
Divider,
|
|
274
|
+
Group as Group2,
|
|
275
|
+
SegmentedControl,
|
|
107
276
|
Stack as Stack2,
|
|
108
|
-
Title,
|
|
109
277
|
Text as Text2,
|
|
110
|
-
Group as Group2,
|
|
111
|
-
Divider,
|
|
112
|
-
Badge,
|
|
113
278
|
ThemeIcon,
|
|
279
|
+
Title
|
|
280
|
+
} from "@mantine/core";
|
|
281
|
+
import { TimeInput } from "@mantine/dates";
|
|
282
|
+
import {
|
|
283
|
+
IconClock,
|
|
284
|
+
IconDeviceLaptop,
|
|
285
|
+
IconMoon,
|
|
286
|
+
IconPalette,
|
|
287
|
+
IconSun
|
|
288
|
+
} from "@tabler/icons-react";
|
|
289
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
290
|
+
var DEFAULT_LABELS2 = {
|
|
291
|
+
title: "Appearance",
|
|
292
|
+
subtitle: "Control how the application looks and feels",
|
|
293
|
+
themeMode: "Theme mode",
|
|
294
|
+
themeModeHint: "Auto will switch between light and dark based on time of day",
|
|
295
|
+
currentlyActive: "Currently active:",
|
|
296
|
+
timeBasedSettings: "Time-based settings",
|
|
297
|
+
lightStartTime: "Light theme start time",
|
|
298
|
+
darkStartTime: "Dark theme start time",
|
|
299
|
+
light: "Light",
|
|
300
|
+
dark: "Dark",
|
|
301
|
+
system: "System",
|
|
302
|
+
timeBased: "Time-based"
|
|
303
|
+
};
|
|
304
|
+
var MODE_ICONS2 = {
|
|
305
|
+
light: /* @__PURE__ */ jsx4(IconSun, { size: 16 }),
|
|
306
|
+
dark: /* @__PURE__ */ jsx4(IconMoon, { size: 16 }),
|
|
307
|
+
auto: /* @__PURE__ */ jsx4(IconDeviceLaptop, { size: 16 }),
|
|
308
|
+
"time-based": /* @__PURE__ */ jsx4(IconClock, { size: 16 })
|
|
309
|
+
};
|
|
310
|
+
var MODE_ORDER = ["light", "dark", "auto", "time-based"];
|
|
311
|
+
function ThemeSetting({
|
|
312
|
+
modes = MODE_ORDER,
|
|
313
|
+
labels = {},
|
|
314
|
+
cardProps = {}
|
|
315
|
+
}) {
|
|
316
|
+
const {
|
|
317
|
+
theme,
|
|
318
|
+
timeBasedSettings,
|
|
319
|
+
setTheme,
|
|
320
|
+
setTimeBasedSettings,
|
|
321
|
+
currentTheme
|
|
322
|
+
} = useTheme();
|
|
323
|
+
const text = { ...DEFAULT_LABELS2, ...labels };
|
|
324
|
+
const isTimeBased = theme === "time-based";
|
|
325
|
+
const isDark = currentTheme === "dark";
|
|
326
|
+
const showTimeBased = modes.includes("time-based");
|
|
327
|
+
return /* @__PURE__ */ jsx4(
|
|
328
|
+
Card,
|
|
329
|
+
{
|
|
330
|
+
withBorder: true,
|
|
331
|
+
radius: "lg",
|
|
332
|
+
p: "25px",
|
|
333
|
+
bg: isDark ? "dark.8" : "gray.0",
|
|
334
|
+
style: { flex: 1, overflow: "auto", display: "flex", flexDirection: "column" },
|
|
335
|
+
...cardProps,
|
|
336
|
+
children: /* @__PURE__ */ jsxs3(Stack2, { gap: "lg", style: { flex: 1 }, children: [
|
|
337
|
+
/* @__PURE__ */ jsxs3(Box, { children: [
|
|
338
|
+
/* @__PURE__ */ jsxs3(Group2, { gap: "xs", children: [
|
|
339
|
+
/* @__PURE__ */ jsx4(ThemeIcon, { variant: "subtle", color: "blue.8", size: "md", radius: "md", children: /* @__PURE__ */ jsx4(IconPalette, { size: 25 }) }),
|
|
340
|
+
/* @__PURE__ */ jsx4(Title, { order: 4, children: text.title })
|
|
341
|
+
] }),
|
|
342
|
+
/* @__PURE__ */ jsx4(Text2, { size: "sm", c: "dimmed", children: text.subtitle })
|
|
343
|
+
] }),
|
|
344
|
+
/* @__PURE__ */ jsx4(Divider, {}),
|
|
345
|
+
/* @__PURE__ */ jsxs3(Box, { children: [
|
|
346
|
+
/* @__PURE__ */ jsx4(Text2, { fw: 500, mb: 6, children: text.themeMode }),
|
|
347
|
+
/* @__PURE__ */ jsx4(
|
|
348
|
+
SegmentedControl,
|
|
349
|
+
{
|
|
350
|
+
fullWidth: true,
|
|
351
|
+
value: theme,
|
|
352
|
+
radius: "lg",
|
|
353
|
+
color: "teal.8",
|
|
354
|
+
bg: isDark ? "dark.6" : "gray.3",
|
|
355
|
+
onChange: (value) => setTheme(value),
|
|
356
|
+
data: MODE_ORDER.filter((mode) => modes.includes(mode)).map(
|
|
357
|
+
(mode) => ({
|
|
358
|
+
value: mode,
|
|
359
|
+
label: /* @__PURE__ */ jsxs3(Group2, { gap: 6, children: [
|
|
360
|
+
MODE_ICONS2[mode],
|
|
361
|
+
/* @__PURE__ */ jsx4("span", { children: mode === "light" ? text.light : mode === "dark" ? text.dark : mode === "auto" ? text.system : text.timeBased })
|
|
362
|
+
] })
|
|
363
|
+
})
|
|
364
|
+
)
|
|
365
|
+
}
|
|
366
|
+
),
|
|
367
|
+
/* @__PURE__ */ jsx4(Text2, { size: "xs", c: "dimmed", mt: "xs", children: text.themeModeHint }),
|
|
368
|
+
/* @__PURE__ */ jsxs3(Text2, { size: "xs", mt: 4, children: [
|
|
369
|
+
text.currentlyActive,
|
|
370
|
+
" ",
|
|
371
|
+
/* @__PURE__ */ jsx4("b", { children: isDark ? text.dark : text.light })
|
|
372
|
+
] })
|
|
373
|
+
] }),
|
|
374
|
+
showTimeBased && /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
375
|
+
/* @__PURE__ */ jsx4(Divider, {}),
|
|
376
|
+
/* @__PURE__ */ jsxs3(
|
|
377
|
+
Box,
|
|
378
|
+
{
|
|
379
|
+
style: {
|
|
380
|
+
opacity: isTimeBased ? 1 : 0.45,
|
|
381
|
+
pointerEvents: isTimeBased ? "auto" : "none",
|
|
382
|
+
transition: "opacity 150ms ease"
|
|
383
|
+
},
|
|
384
|
+
children: [
|
|
385
|
+
/* @__PURE__ */ jsxs3(Group2, { gap: 6, mb: 6, children: [
|
|
386
|
+
/* @__PURE__ */ jsx4(IconClock, { size: 16 }),
|
|
387
|
+
/* @__PURE__ */ jsx4(Text2, { fw: 500, children: text.timeBasedSettings })
|
|
388
|
+
] }),
|
|
389
|
+
/* @__PURE__ */ jsxs3(Group2, { grow: true, children: [
|
|
390
|
+
/* @__PURE__ */ jsxs3(Box, { children: [
|
|
391
|
+
/* @__PURE__ */ jsx4(Text2, { size: "sm", mb: 4, children: text.lightStartTime }),
|
|
392
|
+
/* @__PURE__ */ jsx4(
|
|
393
|
+
TimeInput,
|
|
394
|
+
{
|
|
395
|
+
withSeconds: false,
|
|
396
|
+
radius: "13px",
|
|
397
|
+
value: timeBasedSettings.lightStartTime,
|
|
398
|
+
onChange: (event) => setTimeBasedSettings({
|
|
399
|
+
...timeBasedSettings,
|
|
400
|
+
lightStartTime: event.currentTarget.value
|
|
401
|
+
})
|
|
402
|
+
}
|
|
403
|
+
)
|
|
404
|
+
] }),
|
|
405
|
+
/* @__PURE__ */ jsxs3(Box, { children: [
|
|
406
|
+
/* @__PURE__ */ jsx4(Text2, { size: "sm", mb: 4, children: text.darkStartTime }),
|
|
407
|
+
/* @__PURE__ */ jsx4(
|
|
408
|
+
TimeInput,
|
|
409
|
+
{
|
|
410
|
+
withSeconds: false,
|
|
411
|
+
radius: "13px",
|
|
412
|
+
value: timeBasedSettings.darkStartTime,
|
|
413
|
+
onChange: (event) => setTimeBasedSettings({
|
|
414
|
+
...timeBasedSettings,
|
|
415
|
+
darkStartTime: event.currentTarget.value
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
)
|
|
419
|
+
] })
|
|
420
|
+
] }),
|
|
421
|
+
/* @__PURE__ */ jsxs3(Text2, { size: "xs", c: "dimmed", mt: "xs", children: [
|
|
422
|
+
text.light,
|
|
423
|
+
": ",
|
|
424
|
+
timeBasedSettings.lightStartTime,
|
|
425
|
+
" \u2192",
|
|
426
|
+
" ",
|
|
427
|
+
timeBasedSettings.darkStartTime,
|
|
428
|
+
/* @__PURE__ */ jsx4("br", {}),
|
|
429
|
+
text.dark,
|
|
430
|
+
": ",
|
|
431
|
+
timeBasedSettings.darkStartTime,
|
|
432
|
+
" \u2192",
|
|
433
|
+
" ",
|
|
434
|
+
timeBasedSettings.lightStartTime
|
|
435
|
+
] })
|
|
436
|
+
]
|
|
437
|
+
}
|
|
438
|
+
)
|
|
439
|
+
] })
|
|
440
|
+
] })
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// src/modals/Information.tsx
|
|
446
|
+
import { useState as useState2 } from "react";
|
|
447
|
+
import {
|
|
448
|
+
Modal,
|
|
449
|
+
Stack as Stack3,
|
|
450
|
+
Title as Title2,
|
|
451
|
+
Text as Text3,
|
|
452
|
+
Group as Group3,
|
|
453
|
+
Divider as Divider2,
|
|
454
|
+
Badge,
|
|
455
|
+
ThemeIcon as ThemeIcon2,
|
|
114
456
|
SimpleGrid,
|
|
115
457
|
Paper,
|
|
116
|
-
ActionIcon as
|
|
117
|
-
Tooltip as
|
|
458
|
+
ActionIcon as ActionIcon3,
|
|
459
|
+
Tooltip as Tooltip3,
|
|
118
460
|
useComputedColorScheme
|
|
119
461
|
} from "@mantine/core";
|
|
120
462
|
import {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
} from "@tabler/icons-react";
|
|
463
|
+
Award,
|
|
464
|
+
Calendar,
|
|
465
|
+
Check,
|
|
466
|
+
Copy,
|
|
467
|
+
Cpu,
|
|
468
|
+
Hash,
|
|
469
|
+
MapPin,
|
|
470
|
+
Tag,
|
|
471
|
+
User
|
|
472
|
+
} from "lucide-react";
|
|
132
473
|
|
|
133
474
|
// src/utils/commonUtils.ts
|
|
134
475
|
var copyToClipboard = async (text) => {
|
|
@@ -268,10 +609,10 @@ function formatHumanDate(date, options) {
|
|
|
268
609
|
}
|
|
269
610
|
|
|
270
611
|
// src/modals/Information.tsx
|
|
271
|
-
import { jsx as
|
|
272
|
-
var DEFAULT_TITLE = /* @__PURE__ */
|
|
273
|
-
/* @__PURE__ */
|
|
274
|
-
/* @__PURE__ */
|
|
612
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
613
|
+
var DEFAULT_TITLE = /* @__PURE__ */ jsxs4(Group3, { gap: "xs", wrap: "nowrap", children: [
|
|
614
|
+
/* @__PURE__ */ jsx5(Cpu, { size: 20 }),
|
|
615
|
+
/* @__PURE__ */ jsx5("span", { children: "System Information" })
|
|
275
616
|
] });
|
|
276
617
|
function InformationContent({ info }) {
|
|
277
618
|
const colorScheme = useComputedColorScheme();
|
|
@@ -279,46 +620,46 @@ function InformationContent({ info }) {
|
|
|
279
620
|
const versionType = info.versionType ?? DEFAULT_VERSION_TYPE;
|
|
280
621
|
const cards = [
|
|
281
622
|
{
|
|
282
|
-
icon: /* @__PURE__ */
|
|
623
|
+
icon: /* @__PURE__ */ jsx5(User, { size: 18 }),
|
|
283
624
|
label: "Author",
|
|
284
625
|
value: author,
|
|
285
626
|
color: "blue"
|
|
286
627
|
},
|
|
287
628
|
{
|
|
288
|
-
icon: /* @__PURE__ */
|
|
629
|
+
icon: /* @__PURE__ */ jsx5(Award, { size: 18 }),
|
|
289
630
|
label: "License",
|
|
290
631
|
value: info.license ?? DEFAULT_LICENSE,
|
|
291
632
|
color: "orange"
|
|
292
633
|
},
|
|
293
634
|
{
|
|
294
|
-
icon: /* @__PURE__ */
|
|
635
|
+
icon: /* @__PURE__ */ jsx5(MapPin, { size: 18 }),
|
|
295
636
|
label: "Location",
|
|
296
637
|
value: info.location ?? DEFAULT_LOCATION,
|
|
297
638
|
color: "teal"
|
|
298
639
|
},
|
|
299
640
|
{
|
|
300
|
-
icon: /* @__PURE__ */
|
|
641
|
+
icon: /* @__PURE__ */ jsx5(Tag, { size: 18 }),
|
|
301
642
|
label: "Version Type",
|
|
302
643
|
value: versionType,
|
|
303
644
|
color: "red"
|
|
304
645
|
},
|
|
305
646
|
{
|
|
306
|
-
icon: /* @__PURE__ */
|
|
647
|
+
icon: /* @__PURE__ */ jsx5(Calendar, { size: 18 }),
|
|
307
648
|
label: "Build Time",
|
|
308
649
|
value: info.buildTime !== void 0 ? formatAbsoluteAndRelativeTime(info.buildTime) : UNKNOWN,
|
|
309
650
|
color: "green"
|
|
310
651
|
},
|
|
311
652
|
...info.metadata ?? []
|
|
312
653
|
];
|
|
313
|
-
return /* @__PURE__ */
|
|
314
|
-
/* @__PURE__ */
|
|
654
|
+
return /* @__PURE__ */ jsxs4(Stack3, { gap: "lg", children: [
|
|
655
|
+
/* @__PURE__ */ jsxs4(Stack3, { gap: "xs", align: "center", children: [
|
|
315
656
|
info.logo,
|
|
316
|
-
/* @__PURE__ */
|
|
317
|
-
/* @__PURE__ */
|
|
318
|
-
info.tagline && /* @__PURE__ */
|
|
657
|
+
/* @__PURE__ */ jsxs4(Stack3, { gap: 2, align: "center", children: [
|
|
658
|
+
/* @__PURE__ */ jsx5(Title2, { order: 2, children: info.name }),
|
|
659
|
+
info.tagline && /* @__PURE__ */ jsx5(Text3, { size: "sm", c: "dimmed", w: 600, ta: "center", children: info.tagline })
|
|
319
660
|
] }),
|
|
320
|
-
/* @__PURE__ */
|
|
321
|
-
info.version && /* @__PURE__ */
|
|
661
|
+
/* @__PURE__ */ jsxs4(Group3, { gap: "xs", children: [
|
|
662
|
+
info.version && /* @__PURE__ */ jsxs4(
|
|
322
663
|
Badge,
|
|
323
664
|
{
|
|
324
665
|
size: "lg",
|
|
@@ -333,7 +674,7 @@ function InformationContent({ info }) {
|
|
|
333
674
|
]
|
|
334
675
|
}
|
|
335
676
|
),
|
|
336
|
-
/* @__PURE__ */
|
|
677
|
+
/* @__PURE__ */ jsxs4(
|
|
337
678
|
Badge,
|
|
338
679
|
{
|
|
339
680
|
size: "lg",
|
|
@@ -350,39 +691,39 @@ function InformationContent({ info }) {
|
|
|
350
691
|
)
|
|
351
692
|
] })
|
|
352
693
|
] }),
|
|
353
|
-
/* @__PURE__ */
|
|
354
|
-
/* @__PURE__ */
|
|
355
|
-
cards.map((card) => /* @__PURE__ */
|
|
694
|
+
/* @__PURE__ */ jsx5(Divider2, { label: "System Information", labelPosition: "center" }),
|
|
695
|
+
/* @__PURE__ */ jsxs4(SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
|
|
696
|
+
cards.map((card) => /* @__PURE__ */ jsx5(
|
|
356
697
|
InfoCard,
|
|
357
698
|
{
|
|
358
|
-
icon: card.icon ?? /* @__PURE__ */
|
|
699
|
+
icon: card.icon ?? /* @__PURE__ */ jsx5(Award, { size: 18 }),
|
|
359
700
|
label: card.label,
|
|
360
701
|
value: card.value,
|
|
361
702
|
color: card.color ?? "gray"
|
|
362
703
|
},
|
|
363
704
|
card.label
|
|
364
705
|
)),
|
|
365
|
-
/* @__PURE__ */
|
|
706
|
+
/* @__PURE__ */ jsx5(
|
|
366
707
|
Paper,
|
|
367
708
|
{
|
|
368
709
|
withBorder: true,
|
|
369
710
|
p: "sm",
|
|
370
711
|
radius: "18px",
|
|
371
712
|
bg: colorScheme === "dark" ? "gray.9" : "gray.0",
|
|
372
|
-
children: /* @__PURE__ */
|
|
373
|
-
/* @__PURE__ */
|
|
374
|
-
/* @__PURE__ */
|
|
375
|
-
/* @__PURE__ */
|
|
376
|
-
/* @__PURE__ */
|
|
377
|
-
/* @__PURE__ */
|
|
713
|
+
children: /* @__PURE__ */ jsxs4(Group3, { justify: "space-between", wrap: "nowrap", children: [
|
|
714
|
+
/* @__PURE__ */ jsxs4(Group3, { gap: "sm", flex: 1, children: [
|
|
715
|
+
/* @__PURE__ */ jsx5(ThemeIcon2, { variant: "light", color: "yellow", size: "lg", radius: "14px", children: /* @__PURE__ */ jsx5(Hash, { size: 18 }) }),
|
|
716
|
+
/* @__PURE__ */ jsxs4(Stack3, { gap: 2, children: [
|
|
717
|
+
/* @__PURE__ */ jsx5(Text3, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Build ID" }),
|
|
718
|
+
/* @__PURE__ */ jsx5(Text3, { size: "sm", fw: 500, truncate: true, children: info.buildId ?? UNKNOWN })
|
|
378
719
|
] })
|
|
379
720
|
] }),
|
|
380
|
-
info.buildId && /* @__PURE__ */
|
|
721
|
+
info.buildId && /* @__PURE__ */ jsx5(CopyBuildIdButton, { buildId: info.buildId })
|
|
381
722
|
] })
|
|
382
723
|
}
|
|
383
724
|
)
|
|
384
725
|
] }),
|
|
385
|
-
/* @__PURE__ */
|
|
726
|
+
/* @__PURE__ */ jsx5(
|
|
386
727
|
Footer,
|
|
387
728
|
{
|
|
388
729
|
copyright: info.copyright,
|
|
@@ -399,7 +740,7 @@ function InformationModal({
|
|
|
399
740
|
info,
|
|
400
741
|
title = DEFAULT_TITLE
|
|
401
742
|
}) {
|
|
402
|
-
return /* @__PURE__ */
|
|
743
|
+
return /* @__PURE__ */ jsx5(
|
|
403
744
|
Modal,
|
|
404
745
|
{
|
|
405
746
|
opened,
|
|
@@ -419,12 +760,12 @@ function InformationModal({
|
|
|
419
760
|
}
|
|
420
761
|
},
|
|
421
762
|
title,
|
|
422
|
-
children: /* @__PURE__ */
|
|
763
|
+
children: /* @__PURE__ */ jsx5(InformationContent, { info })
|
|
423
764
|
}
|
|
424
765
|
);
|
|
425
766
|
}
|
|
426
767
|
function CopyBuildIdButton({ buildId }) {
|
|
427
|
-
const [copied, setCopied] =
|
|
768
|
+
const [copied, setCopied] = useState2(false);
|
|
428
769
|
const handleCopy = async () => {
|
|
429
770
|
const success = await copyToClipboard(buildId);
|
|
430
771
|
if (success) {
|
|
@@ -432,13 +773,13 @@ function CopyBuildIdButton({ buildId }) {
|
|
|
432
773
|
setTimeout(() => setCopied(false), 2e3);
|
|
433
774
|
}
|
|
434
775
|
};
|
|
435
|
-
return /* @__PURE__ */
|
|
436
|
-
|
|
776
|
+
return /* @__PURE__ */ jsx5(Tooltip3, { label: copied ? "Copied!" : "Copy ID", withArrow: true, children: /* @__PURE__ */ jsx5(
|
|
777
|
+
ActionIcon3,
|
|
437
778
|
{
|
|
438
779
|
variant: "subtle",
|
|
439
780
|
color: copied ? "teal" : "gray",
|
|
440
781
|
onClick: handleCopy,
|
|
441
|
-
children: copied ? /* @__PURE__ */
|
|
782
|
+
children: copied ? /* @__PURE__ */ jsx5(Check, { size: 16 }) : /* @__PURE__ */ jsx5(Copy, { size: 16 })
|
|
442
783
|
}
|
|
443
784
|
) });
|
|
444
785
|
}
|
|
@@ -449,14 +790,115 @@ function InfoCard({
|
|
|
449
790
|
color
|
|
450
791
|
}) {
|
|
451
792
|
const colorScheme = useComputedColorScheme();
|
|
452
|
-
return /* @__PURE__ */
|
|
453
|
-
/* @__PURE__ */
|
|
454
|
-
/* @__PURE__ */
|
|
455
|
-
/* @__PURE__ */
|
|
456
|
-
/* @__PURE__ */
|
|
793
|
+
return /* @__PURE__ */ jsx5(Paper, { withBorder: true, p: "md", radius: "18px", h: "100%", bg: colorScheme === "dark" ? "gray.9" : "gray.0", children: /* @__PURE__ */ jsxs4(Group3, { gap: "sm", align: "flex-start", children: [
|
|
794
|
+
/* @__PURE__ */ jsx5(ThemeIcon2, { color, variant: "light", size: "lg", radius: "14px", children: icon }),
|
|
795
|
+
/* @__PURE__ */ jsxs4(Stack3, { gap: 2, flex: 1, children: [
|
|
796
|
+
/* @__PURE__ */ jsx5(Text3, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: label }),
|
|
797
|
+
/* @__PURE__ */ jsx5(Text3, { size: "sm", fw: 500, lineClamp: 1, children: value })
|
|
457
798
|
] })
|
|
458
799
|
] }) });
|
|
459
800
|
}
|
|
801
|
+
|
|
802
|
+
// src/pages/NotFound.tsx
|
|
803
|
+
import {
|
|
804
|
+
Box as Box2,
|
|
805
|
+
Button,
|
|
806
|
+
Container,
|
|
807
|
+
Group as Group4,
|
|
808
|
+
Paper as Paper2,
|
|
809
|
+
Text as Text4,
|
|
810
|
+
Title as Title3,
|
|
811
|
+
Code,
|
|
812
|
+
Badge as Badge2
|
|
813
|
+
} from "@mantine/core";
|
|
814
|
+
import {
|
|
815
|
+
IconArrowLeft,
|
|
816
|
+
IconHome,
|
|
817
|
+
IconSearch,
|
|
818
|
+
IconFileOff
|
|
819
|
+
} from "@tabler/icons-react";
|
|
820
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
821
|
+
function NotFound({
|
|
822
|
+
path,
|
|
823
|
+
onSearchClick,
|
|
824
|
+
onHomeClick
|
|
825
|
+
}) {
|
|
826
|
+
const currentPath = path || (typeof window !== "undefined" ? window.location.pathname : "/404");
|
|
827
|
+
return /* @__PURE__ */ jsx6(
|
|
828
|
+
Box2,
|
|
829
|
+
{
|
|
830
|
+
style: {
|
|
831
|
+
minHeight: "100vh",
|
|
832
|
+
display: "flex",
|
|
833
|
+
alignItems: "center",
|
|
834
|
+
background: "radial-gradient(circle at top left, rgba(34, 139, 230, 0.15), transparent 45%), radial-gradient(circle at bottom right, rgba(34, 211, 238, 0.12), transparent 45%), var(--mantine-color-body)"
|
|
835
|
+
},
|
|
836
|
+
children: /* @__PURE__ */ jsx6(Container, { size: "xl", py: 80, children: /* @__PURE__ */ jsxs5(Paper2, { radius: "xl", p: 48, withBorder: true, style: { borderColor: "var(--mantine-color-default-border)", textAlign: "center" }, children: [
|
|
837
|
+
/* @__PURE__ */ jsx6(
|
|
838
|
+
Box2,
|
|
839
|
+
{
|
|
840
|
+
mx: "auto",
|
|
841
|
+
mb: "xl",
|
|
842
|
+
w: 96,
|
|
843
|
+
h: 96,
|
|
844
|
+
style: {
|
|
845
|
+
borderRadius: "50%",
|
|
846
|
+
display: "flex",
|
|
847
|
+
alignItems: "center",
|
|
848
|
+
justifyContent: "center",
|
|
849
|
+
background: "linear-gradient(135deg, var(--mantine-color-blue-6), var(--mantine-color-cyan-6))",
|
|
850
|
+
boxShadow: "0 12px 32px rgba(34, 139, 230, 0.35)"
|
|
851
|
+
},
|
|
852
|
+
children: /* @__PURE__ */ jsx6(IconFileOff, { size: 44, stroke: 1.5, color: "white" })
|
|
853
|
+
}
|
|
854
|
+
),
|
|
855
|
+
/* @__PURE__ */ jsx6(
|
|
856
|
+
Text4,
|
|
857
|
+
{
|
|
858
|
+
fz: { base: 72, sm: 100 },
|
|
859
|
+
fw: 900,
|
|
860
|
+
lh: 1,
|
|
861
|
+
variant: "gradient",
|
|
862
|
+
gradient: { from: "blue.7", to: "cyan.5", deg: 45 },
|
|
863
|
+
children: "404"
|
|
864
|
+
}
|
|
865
|
+
),
|
|
866
|
+
/* @__PURE__ */ jsx6(Badge2, { variant: "light", color: "blue", size: "lg", mb: "xs", children: "NOT FOUND" }),
|
|
867
|
+
/* @__PURE__ */ jsx6(Title3, { order: 2, mt: "sm", mb: "xs", children: "Trang kh\xF4ng t\u1ED3n t\u1EA1i" }),
|
|
868
|
+
/* @__PURE__ */ jsx6(Text4, { c: "dimmed", size: "sm", maw: 440, mx: "auto", children: "Trang ho\u1EB7c \u0111\u01B0\u1EDDng d\u1EABn b\u1EA1n truy c\u1EADp kh\xF4ng t\u1ED3n t\u1EA1i ho\u1EB7c \u0111\xE3 \u0111\u01B0\u1EE3c di chuy\u1EC3n. Vui l\xF2ng ki\u1EC3m tra l\u1EA1i \u0111\u01B0\u1EDDng d\u1EABn ho\u1EB7c quay v\u1EC1 trang ch\u1EE7." }),
|
|
869
|
+
/* @__PURE__ */ jsx6(Box2, { mt: "lg", children: /* @__PURE__ */ jsx6(Code, { color: "blue", variant: "light", px: "md", py: 6, children: currentPath }) }),
|
|
870
|
+
/* @__PURE__ */ jsxs5(Group4, { gap: "sm", mt: "xl", justify: "center", children: [
|
|
871
|
+
/* @__PURE__ */ jsx6(
|
|
872
|
+
Button,
|
|
873
|
+
{
|
|
874
|
+
variant: "light",
|
|
875
|
+
leftSection: /* @__PURE__ */ jsx6(IconArrowLeft, { size: 16 }),
|
|
876
|
+
onClick: () => window.history.back(),
|
|
877
|
+
children: "Quay l\u1EA1i"
|
|
878
|
+
}
|
|
879
|
+
),
|
|
880
|
+
onSearchClick && /* @__PURE__ */ jsx6(
|
|
881
|
+
Button,
|
|
882
|
+
{
|
|
883
|
+
variant: "outline",
|
|
884
|
+
leftSection: /* @__PURE__ */ jsx6(IconSearch, { size: 16 }),
|
|
885
|
+
onClick: onSearchClick,
|
|
886
|
+
children: "T\xECm Docs"
|
|
887
|
+
}
|
|
888
|
+
),
|
|
889
|
+
/* @__PURE__ */ jsx6(
|
|
890
|
+
Button,
|
|
891
|
+
{
|
|
892
|
+
leftSection: /* @__PURE__ */ jsx6(IconHome, { size: 16 }),
|
|
893
|
+
onClick: onHomeClick || (() => window.location.href = "/"),
|
|
894
|
+
children: "Trang ch\u1EE7"
|
|
895
|
+
}
|
|
896
|
+
)
|
|
897
|
+
] })
|
|
898
|
+
] }) })
|
|
899
|
+
}
|
|
900
|
+
);
|
|
901
|
+
}
|
|
460
902
|
export {
|
|
461
903
|
DEFAULT_AUTHOR,
|
|
462
904
|
DEFAULT_AUTHOR_HREF,
|
|
@@ -467,6 +909,10 @@ export {
|
|
|
467
909
|
Footer,
|
|
468
910
|
InformationContent,
|
|
469
911
|
InformationModal,
|
|
912
|
+
NotFound,
|
|
913
|
+
ThemeMenu,
|
|
914
|
+
ThemeProvider,
|
|
915
|
+
ThemeSetting,
|
|
470
916
|
UNKNOWN,
|
|
471
917
|
calculateRemainingTime,
|
|
472
918
|
copyToClipboard,
|
|
@@ -475,6 +921,8 @@ export {
|
|
|
475
921
|
formatHumanDate,
|
|
476
922
|
formatRelativeTime,
|
|
477
923
|
normalizeDate,
|
|
478
|
-
pad
|
|
924
|
+
pad,
|
|
925
|
+
resolveColorScheme,
|
|
926
|
+
useTheme
|
|
479
927
|
};
|
|
480
928
|
//# sourceMappingURL=index.js.map
|