@otmc/ui 0.1.2 → 0.1.3

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 CHANGED
@@ -29,6 +29,9 @@ __export(index_exports, {
29
29
  Footer: () => Footer,
30
30
  InformationContent: () => InformationContent,
31
31
  InformationModal: () => InformationModal,
32
+ NotFound: () => NotFound,
33
+ ThemeMenu: () => ThemeMenu,
34
+ ThemeProvider: () => ThemeProvider,
32
35
  UNKNOWN: () => UNKNOWN,
33
36
  calculateRemainingTime: () => calculateRemainingTime,
34
37
  copyToClipboard: () => copyToClipboard,
@@ -37,7 +40,9 @@ __export(index_exports, {
37
40
  formatHumanDate: () => formatHumanDate,
38
41
  formatRelativeTime: () => formatRelativeTime,
39
42
  normalizeDate: () => normalizeDate,
40
- pad: () => pad
43
+ pad: () => pad,
44
+ resolveColorScheme: () => resolveColorScheme,
45
+ useTheme: () => useTheme
41
46
  });
42
47
  module.exports = __toCommonJS(index_exports);
43
48
 
@@ -137,9 +142,169 @@ function Footer({
137
142
  ] });
138
143
  }
139
144
 
140
- // src/modals/Information.tsx
145
+ // src/components/ThemeMenu.tsx
146
+ var import_core3 = require("@mantine/core");
147
+ var import_lucide_react = require("lucide-react");
148
+
149
+ // src/contexts/ThemeProvider.tsx
141
150
  var import_react = require("react");
142
151
  var import_core2 = require("@mantine/core");
152
+ var import_jsx_runtime2 = require("react/jsx-runtime");
153
+ var ThemeContext = (0, import_react.createContext)(null);
154
+ var useTheme = () => {
155
+ const ctx = (0, import_react.useContext)(ThemeContext);
156
+ if (!ctx) {
157
+ throw new Error("useTheme must be used inside ThemeProvider");
158
+ }
159
+ return ctx;
160
+ };
161
+ var resolveColorScheme = (colorScheme) => {
162
+ if (colorScheme === "auto") {
163
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
164
+ }
165
+ return colorScheme;
166
+ };
167
+ var resolveTimeBasedTheme = (settings) => {
168
+ const now = /* @__PURE__ */ new Date();
169
+ const minutes = now.getHours() * 60 + now.getMinutes();
170
+ const [lh, lm] = settings.lightStartTime.split(":").map(Number);
171
+ const [dh, dm] = settings.darkStartTime.split(":").map(Number);
172
+ const light = lh * 60 + lm;
173
+ const dark = dh * 60 + dm;
174
+ return light < dark ? minutes >= light && minutes < dark ? "light" : "dark" : minutes >= light || minutes < dark ? "light" : "dark";
175
+ };
176
+ var resolveAutoScheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
177
+ var ThemeProvider = ({
178
+ children,
179
+ defaultTheme = "auto",
180
+ defaultTimeBasedSettings = {
181
+ lightStartTime: "07:00",
182
+ darkStartTime: "19:00"
183
+ },
184
+ storagePrefix = ""
185
+ }) => {
186
+ const themeStorageKey = `${storagePrefix}theme`;
187
+ const timeStorageKey = `${storagePrefix}time-theme`;
188
+ const { colorScheme, setColorScheme } = (0, import_core2.useMantineColorScheme)();
189
+ const [theme, setThemeState] = (0, import_react.useState)(
190
+ () => localStorage.getItem(themeStorageKey) ?? defaultTheme
191
+ );
192
+ const [timeBasedSettings, setTimeBasedSettings] = (0, import_react.useState)(
193
+ () => JSON.parse(localStorage.getItem(timeStorageKey) || "null") ?? defaultTimeBasedSettings
194
+ );
195
+ const handleSetTimeBasedSettings = (settings) => {
196
+ setTimeBasedSettings(settings);
197
+ localStorage.setItem(timeStorageKey, JSON.stringify(settings));
198
+ if (theme === "time-based") {
199
+ applyTheme("time-based");
200
+ }
201
+ };
202
+ const applyTheme = (mode) => {
203
+ let scheme;
204
+ switch (mode) {
205
+ case "light":
206
+ case "dark":
207
+ case "auto":
208
+ scheme = mode;
209
+ break;
210
+ case "time-based":
211
+ scheme = resolveTimeBasedTheme(timeBasedSettings);
212
+ break;
213
+ default:
214
+ scheme = "auto";
215
+ }
216
+ setColorScheme(scheme);
217
+ };
218
+ (0, import_react.useEffect)(() => {
219
+ applyTheme(theme);
220
+ }, [theme, timeBasedSettings]);
221
+ const setTheme = (mode) => {
222
+ setThemeState(mode);
223
+ localStorage.setItem(themeStorageKey, mode);
224
+ applyTheme(mode);
225
+ };
226
+ const toggleTheme = () => {
227
+ setTheme(colorScheme === "dark" ? "light" : "dark");
228
+ };
229
+ const currentTheme = theme === "time-based" ? resolveTimeBasedTheme(timeBasedSettings) : colorScheme === "auto" ? resolveAutoScheme() : colorScheme;
230
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
231
+ ThemeContext.Provider,
232
+ {
233
+ value: {
234
+ theme,
235
+ currentTheme,
236
+ setTheme,
237
+ toggleTheme,
238
+ timeBasedSettings,
239
+ setTimeBasedSettings: handleSetTimeBasedSettings
240
+ },
241
+ children
242
+ }
243
+ );
244
+ };
245
+
246
+ // src/components/ThemeMenu.tsx
247
+ var import_jsx_runtime3 = require("react/jsx-runtime");
248
+ var DEFAULT_LABELS = {
249
+ tooltip: "Ch\u1EBF \u0111\u1ED9 giao di\u1EC7n",
250
+ title: "Ch\u1EBF \u0111\u1ED9 giao di\u1EC7n",
251
+ light: "S\xE1ng",
252
+ dark: "T\u1ED1i",
253
+ auto: "Theo h\u1EC7 th\u1ED1ng",
254
+ timeBased: "Theo th\u1EDDi gian"
255
+ };
256
+ var MODE_ICONS = {
257
+ light: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Sun, { size: 16 }),
258
+ dark: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Moon, { size: 16 }),
259
+ auto: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Monitor, { size: 16 }),
260
+ "time-based": /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Clock, { size: 16 })
261
+ };
262
+ function ThemeMenu({
263
+ modes = ["light", "dark", "auto", "time-based"],
264
+ labels = {},
265
+ iconSize = 20,
266
+ size = "lg",
267
+ menuProps = {}
268
+ }) {
269
+ const { theme, currentTheme, setTheme } = useTheme();
270
+ const text = { ...DEFAULT_LABELS, ...labels };
271
+ const isDark = currentTheme === "dark";
272
+ const activeColor = isDark ? "yellow.8" : "blue.8";
273
+ const triggerIcon = theme === "light" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Sun, { size: iconSize, strokeWidth: 2 }) : theme === "dark" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Moon, { size: iconSize, strokeWidth: 2 }) : theme === "auto" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Monitor, { size: iconSize, strokeWidth: 2 }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Clock, { size: iconSize, strokeWidth: 2 });
274
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Menu, { shadow: "md", width: 200, position: "bottom-end", ...menuProps, children: [
275
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Menu.Target, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Tooltip, { label: text.tooltip, position: "bottom", withArrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
276
+ import_core3.ActionIcon,
277
+ {
278
+ variant: "subtle",
279
+ color: activeColor,
280
+ size,
281
+ radius: "lg",
282
+ style: {
283
+ boxShadow: isDark ? "0 0 15px rgba(250, 176, 5, 0.2)" : "0 0 15px rgba(34, 139, 230, 0.2)"
284
+ },
285
+ children: triggerIcon
286
+ }
287
+ ) }) }),
288
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_core3.Menu.Dropdown, { style: { borderRadius: "11px" }, children: [
289
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_core3.Menu.Label, { children: text.title }),
290
+ modes.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
291
+ import_core3.Menu.Item,
292
+ {
293
+ leftSection: MODE_ICONS[mode],
294
+ onClick: () => setTheme(mode),
295
+ color: theme === mode ? activeColor : void 0,
296
+ fw: theme === mode ? 700 : 400,
297
+ children: text[mode === "time-based" ? "timeBased" : mode]
298
+ },
299
+ mode
300
+ ))
301
+ ] })
302
+ ] });
303
+ }
304
+
305
+ // src/modals/Information.tsx
306
+ var import_react2 = require("react");
307
+ var import_core4 = require("@mantine/core");
143
308
  var import_icons_react2 = require("@tabler/icons-react");
144
309
 
145
310
  // src/utils/commonUtils.ts
@@ -280,58 +445,58 @@ function formatHumanDate(date, options) {
280
445
  }
281
446
 
282
447
  // src/modals/Information.tsx
283
- var import_jsx_runtime2 = require("react/jsx-runtime");
284
- var DEFAULT_TITLE = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Group, { gap: "xs", wrap: "nowrap", children: [
285
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconCpu, { size: 20 }),
286
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "System Information" })
448
+ var import_jsx_runtime4 = require("react/jsx-runtime");
449
+ var DEFAULT_TITLE = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Group, { gap: "xs", wrap: "nowrap", children: [
450
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconCpu, { size: 20 }),
451
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "System Information" })
287
452
  ] });
288
453
  function InformationContent({ info }) {
289
- const colorScheme = (0, import_core2.useComputedColorScheme)();
454
+ const colorScheme = (0, import_core4.useComputedColorScheme)();
290
455
  const author = info.author ?? DEFAULT_AUTHOR;
291
456
  const versionType = info.versionType ?? DEFAULT_VERSION_TYPE;
292
457
  const cards = [
293
458
  {
294
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconUser, { size: 18 }),
459
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconUser, { size: 18 }),
295
460
  label: "Author",
296
461
  value: author,
297
462
  color: "blue"
298
463
  },
299
464
  {
300
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconLicense, { size: 18 }),
465
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconLicense, { size: 18 }),
301
466
  label: "License",
302
467
  value: info.license ?? DEFAULT_LICENSE,
303
468
  color: "orange"
304
469
  },
305
470
  {
306
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconMapPin, { size: 18 }),
471
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconMapPin, { size: 18 }),
307
472
  label: "Location",
308
473
  value: info.location ?? DEFAULT_LOCATION,
309
474
  color: "teal"
310
475
  },
311
476
  {
312
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconTag, { size: 18 }),
477
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconTag, { size: 18 }),
313
478
  label: "Version Type",
314
479
  value: versionType,
315
480
  color: "red"
316
481
  },
317
482
  {
318
- icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconCalendar, { size: 18 }),
483
+ icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconCalendar, { size: 18 }),
319
484
  label: "Build Time",
320
485
  value: info.buildTime !== void 0 ? formatAbsoluteAndRelativeTime(info.buildTime) : UNKNOWN,
321
486
  color: "green"
322
487
  },
323
488
  ...info.metadata ?? []
324
489
  ];
325
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Stack, { gap: "lg", children: [
326
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Stack, { gap: "xs", align: "center", children: [
490
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Stack, { gap: "lg", children: [
491
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Stack, { gap: "xs", align: "center", children: [
327
492
  info.logo,
328
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Stack, { gap: 2, align: "center", children: [
329
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Title, { order: 2, children: info.name }),
330
- info.tagline && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Text, { size: "sm", c: "dimmed", w: 600, ta: "center", children: info.tagline })
493
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Stack, { gap: 2, align: "center", children: [
494
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Title, { order: 2, children: info.name }),
495
+ info.tagline && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Text, { size: "sm", c: "dimmed", w: 600, ta: "center", children: info.tagline })
331
496
  ] }),
332
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Group, { gap: "xs", children: [
333
- info.version && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
334
- import_core2.Badge,
497
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Group, { gap: "xs", children: [
498
+ info.version && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
499
+ import_core4.Badge,
335
500
  {
336
501
  size: "lg",
337
502
  color: "blue",
@@ -345,8 +510,8 @@ function InformationContent({ info }) {
345
510
  ]
346
511
  }
347
512
  ),
348
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
349
- import_core2.Badge,
513
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
514
+ import_core4.Badge,
350
515
  {
351
516
  size: "lg",
352
517
  color: "teal",
@@ -362,39 +527,39 @@ function InformationContent({ info }) {
362
527
  )
363
528
  ] })
364
529
  ] }),
365
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Divider, { label: "System Information", labelPosition: "center" }),
366
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
367
- cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
530
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Divider, { label: "System Information", labelPosition: "center" }),
531
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
532
+ cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
368
533
  InfoCard,
369
534
  {
370
- icon: card.icon ?? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconAward, { size: 18 }),
535
+ icon: card.icon ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconAward, { size: 18 }),
371
536
  label: card.label,
372
537
  value: card.value,
373
538
  color: card.color ?? "gray"
374
539
  },
375
540
  card.label
376
541
  )),
377
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
378
- import_core2.Paper,
542
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
543
+ import_core4.Paper,
379
544
  {
380
545
  withBorder: true,
381
546
  p: "sm",
382
547
  radius: "18px",
383
548
  bg: colorScheme === "dark" ? "gray.9" : "gray.0",
384
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Group, { justify: "space-between", wrap: "nowrap", children: [
385
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Group, { gap: "sm", flex: 1, children: [
386
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.ThemeIcon, { variant: "light", color: "yellow", size: "lg", radius: "14px", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconHash, { size: 18 }) }),
387
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Stack, { gap: 2, children: [
388
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Build ID" }),
389
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Text, { size: "sm", fw: 500, truncate: true, children: info.buildId ?? UNKNOWN })
549
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Group, { justify: "space-between", wrap: "nowrap", children: [
550
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Group, { gap: "sm", flex: 1, children: [
551
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.ThemeIcon, { variant: "light", color: "yellow", size: "lg", radius: "14px", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconHash, { size: 18 }) }),
552
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Stack, { gap: 2, children: [
553
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: "Build ID" }),
554
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Text, { size: "sm", fw: 500, truncate: true, children: info.buildId ?? UNKNOWN })
390
555
  ] })
391
556
  ] }),
392
- info.buildId && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CopyBuildIdButton, { buildId: info.buildId })
557
+ info.buildId && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CopyBuildIdButton, { buildId: info.buildId })
393
558
  ] })
394
559
  }
395
560
  )
396
561
  ] }),
397
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
562
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
398
563
  Footer,
399
564
  {
400
565
  copyright: info.copyright,
@@ -411,8 +576,8 @@ function InformationModal({
411
576
  info,
412
577
  title = DEFAULT_TITLE
413
578
  }) {
414
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
415
- import_core2.Modal,
579
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
580
+ import_core4.Modal,
416
581
  {
417
582
  opened,
418
583
  onClose,
@@ -431,12 +596,12 @@ function InformationModal({
431
596
  }
432
597
  },
433
598
  title,
434
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(InformationContent, { info })
599
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InformationContent, { info })
435
600
  }
436
601
  );
437
602
  }
438
603
  function CopyBuildIdButton({ buildId }) {
439
- const [copied, setCopied] = (0, import_react.useState)(false);
604
+ const [copied, setCopied] = (0, import_react2.useState)(false);
440
605
  const handleCopy = async () => {
441
606
  const success = await copyToClipboard(buildId);
442
607
  if (success) {
@@ -444,13 +609,13 @@ function CopyBuildIdButton({ buildId }) {
444
609
  setTimeout(() => setCopied(false), 2e3);
445
610
  }
446
611
  };
447
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Tooltip, { label: copied ? "Copied!" : "Copy ID", withArrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
448
- import_core2.ActionIcon,
612
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Tooltip, { label: copied ? "Copied!" : "Copy ID", withArrow: true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
613
+ import_core4.ActionIcon,
449
614
  {
450
615
  variant: "subtle",
451
616
  color: copied ? "teal" : "gray",
452
617
  onClick: handleCopy,
453
- children: copied ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconCheck, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons_react2.IconCopy, { size: 16 })
618
+ children: copied ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconCheck, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons_react2.IconCopy, { size: 16 })
454
619
  }
455
620
  ) });
456
621
  }
@@ -460,15 +625,101 @@ function InfoCard({
460
625
  value,
461
626
  color
462
627
  }) {
463
- const colorScheme = (0, import_core2.useComputedColorScheme)();
464
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Paper, { withBorder: true, p: "md", radius: "18px", h: "100%", bg: colorScheme === "dark" ? "gray.9" : "gray.0", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Group, { gap: "sm", align: "flex-start", children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.ThemeIcon, { color, variant: "light", size: "lg", radius: "14px", children: icon }),
466
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_core2.Stack, { gap: 2, flex: 1, children: [
467
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: label }),
468
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core2.Text, { size: "sm", fw: 500, lineClamp: 1, children: value })
628
+ const colorScheme = (0, import_core4.useComputedColorScheme)();
629
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Paper, { withBorder: true, p: "md", radius: "18px", h: "100%", bg: colorScheme === "dark" ? "gray.9" : "gray.0", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Group, { gap: "sm", align: "flex-start", children: [
630
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.ThemeIcon, { color, variant: "light", size: "lg", radius: "14px", children: icon }),
631
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_core4.Stack, { gap: 2, flex: 1, children: [
632
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Text, { size: "xs", c: "dimmed", fw: 700, tt: "uppercase", children: label }),
633
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_core4.Text, { size: "sm", fw: 500, lineClamp: 1, children: value })
469
634
  ] })
470
635
  ] }) });
471
636
  }
637
+
638
+ // src/pages/NotFound.tsx
639
+ var import_core5 = require("@mantine/core");
640
+ var import_icons_react3 = require("@tabler/icons-react");
641
+ var import_jsx_runtime5 = require("react/jsx-runtime");
642
+ function NotFound({
643
+ path,
644
+ onSearchClick,
645
+ onHomeClick
646
+ }) {
647
+ const currentPath = path || (typeof window !== "undefined" ? window.location.pathname : "/404");
648
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
649
+ import_core5.Box,
650
+ {
651
+ style: {
652
+ minHeight: "100vh",
653
+ display: "flex",
654
+ alignItems: "center",
655
+ 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)"
656
+ },
657
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Container, { size: "xl", py: 80, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_core5.Paper, { radius: "xl", p: 48, withBorder: true, style: { borderColor: "var(--mantine-color-default-border)", textAlign: "center" }, children: [
658
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
659
+ import_core5.Box,
660
+ {
661
+ mx: "auto",
662
+ mb: "xl",
663
+ w: 96,
664
+ h: 96,
665
+ style: {
666
+ borderRadius: "50%",
667
+ display: "flex",
668
+ alignItems: "center",
669
+ justifyContent: "center",
670
+ background: "linear-gradient(135deg, var(--mantine-color-blue-6), var(--mantine-color-cyan-6))",
671
+ boxShadow: "0 12px 32px rgba(34, 139, 230, 0.35)"
672
+ },
673
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons_react3.IconFileOff, { size: 44, stroke: 1.5, color: "white" })
674
+ }
675
+ ),
676
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
677
+ import_core5.Text,
678
+ {
679
+ fz: { base: 72, sm: 100 },
680
+ fw: 900,
681
+ lh: 1,
682
+ variant: "gradient",
683
+ gradient: { from: "blue.7", to: "cyan.5", deg: 45 },
684
+ children: "404"
685
+ }
686
+ ),
687
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Badge, { variant: "light", color: "blue", size: "lg", mb: "xs", children: "NOT FOUND" }),
688
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Title, { order: 2, mt: "sm", mb: "xs", children: "Trang kh\xF4ng t\u1ED3n t\u1EA1i" }),
689
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Text, { 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." }),
690
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Box, { mt: "lg", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_core5.Code, { color: "blue", variant: "light", px: "md", py: 6, children: currentPath }) }),
691
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_core5.Group, { gap: "sm", mt: "xl", justify: "center", children: [
692
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
693
+ import_core5.Button,
694
+ {
695
+ variant: "light",
696
+ leftSection: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons_react3.IconArrowLeft, { size: 16 }),
697
+ onClick: () => window.history.back(),
698
+ children: "Quay l\u1EA1i"
699
+ }
700
+ ),
701
+ onSearchClick && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
702
+ import_core5.Button,
703
+ {
704
+ variant: "outline",
705
+ leftSection: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons_react3.IconSearch, { size: 16 }),
706
+ onClick: onSearchClick,
707
+ children: "T\xECm Docs"
708
+ }
709
+ ),
710
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
711
+ import_core5.Button,
712
+ {
713
+ leftSection: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons_react3.IconHome, { size: 16 }),
714
+ onClick: onHomeClick || (() => window.location.href = "/"),
715
+ children: "Trang ch\u1EE7"
716
+ }
717
+ )
718
+ ] })
719
+ ] }) })
720
+ }
721
+ );
722
+ }
472
723
  // Annotate the CommonJS export names for ESM import in node:
473
724
  0 && (module.exports = {
474
725
  DEFAULT_AUTHOR,
@@ -480,6 +731,9 @@ function InfoCard({
480
731
  Footer,
481
732
  InformationContent,
482
733
  InformationModal,
734
+ NotFound,
735
+ ThemeMenu,
736
+ ThemeProvider,
483
737
  UNKNOWN,
484
738
  calculateRemainingTime,
485
739
  copyToClipboard,
@@ -488,6 +742,8 @@ function InfoCard({
488
742
  formatHumanDate,
489
743
  formatRelativeTime,
490
744
  normalizeDate,
491
- pad
745
+ pad,
746
+ resolveColorScheme,
747
+ useTheme
492
748
  });
493
749
  //# sourceMappingURL=index.cjs.map