@docubook/create 1.16.1 → 2.0.0-beta.2

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.
@@ -44,6 +44,7 @@ export default function SubLink({
44
44
  // Auto-expand if current path is a child of this item
45
45
  useEffect(() => {
46
46
  if (items && (path.startsWith(fullHref) && path !== fullHref)) {
47
+ // eslint-disable-next-line react-hooks/set-state-in-effect
47
48
  setIsOpen(true);
48
49
  }
49
50
  }, [path, fullHref, items]);
@@ -85,7 +86,7 @@ export default function SubLink({
85
86
  <div className={cn("flex flex-col gap-1 w-full")}>
86
87
  <Collapsible open={isOpen} onOpenChange={setIsOpen}>
87
88
  <CollapsibleTrigger
88
- className="w-full pr-5 text-left"
89
+ className="w-full pr-5 text-left cursor-pointer"
89
90
  aria-expanded={isOpen}
90
91
  aria-controls={`collapsible-${fullHref.replace(/[^a-zA-Z0-9]/g, '-')}`}
91
92
  >
@@ -1,68 +1,69 @@
1
1
  "use client";
2
2
 
3
3
  import * as React from "react";
4
- import { Moon, Sun, Monitor } from "lucide-react";
4
+ import { Moon, Sun } from "lucide-react";
5
5
  import { useTheme } from "next-themes";
6
6
  import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
7
7
 
8
8
  export function ModeToggle() {
9
- const { theme, setTheme } = useTheme();
10
- const [selectedTheme, setSelectedTheme] = React.useState<string>("system");
9
+ const { theme, setTheme, resolvedTheme } = useTheme();
10
+ const [mounted, setMounted] = React.useState(false);
11
11
 
12
- // Pastikan toggle tetap di posisi yang benar setelah reload
12
+ // Untuk menghindari hydration mismatch
13
13
  React.useEffect(() => {
14
- if (theme) {
15
- setSelectedTheme(theme);
14
+ setMounted(true);
15
+ }, []);
16
+
17
+ // Jika belum mounted, jangan render apapun untuk menghindari mismatch
18
+ if (!mounted) {
19
+ return (
20
+ <div className="flex items-center gap-1 rounded-full border border-border bg-background/50 p-1">
21
+ <div className="rounded-full p-1 w-8 h-8" />
22
+ <div className="rounded-full p-1 w-8 h-8" />
23
+ </div>
24
+ );
25
+ }
26
+
27
+ // Tentukan theme yang aktif: gunakan resolvedTheme untuk menampilkan ikon yang sesuai
28
+ // jika theme === "system", resolvedTheme akan menjadi "light" atau "dark" sesuai device
29
+ const activeTheme = theme === "system" || !theme ? resolvedTheme : theme;
30
+
31
+ const handleToggle = () => {
32
+ // Toggle antara light dan dark
33
+ // Jika sekarang light, ganti ke dark, dan sebaliknya
34
+ if (activeTheme === "light") {
35
+ setTheme("dark");
16
36
  } else {
17
- setSelectedTheme("system"); // Default ke system jika undefined
37
+ setTheme("light");
18
38
  }
19
- }, [theme]);
39
+ };
20
40
 
21
41
  return (
22
42
  <ToggleGroup
23
43
  type="single"
24
- value={selectedTheme}
25
- onValueChange={(value) => {
26
- if (value) {
27
- setTheme(value);
28
- setSelectedTheme(value);
29
- }
30
- }}
44
+ value={activeTheme}
45
+ onValueChange={handleToggle}
31
46
  className="flex items-center gap-1 rounded-full border border-border bg-background/50 p-1 transition-all"
32
47
  >
33
48
  <ToggleGroupItem
34
49
  value="light"
35
50
  size="sm"
36
51
  aria-label="Light Mode"
37
- className={`rounded-full p-1 transition-all ${
38
- selectedTheme === "light"
39
- ? "bg-primary text-primary-foreground"
40
- : "bg-transparent hover:bg-muted/50"
41
- }`}
52
+ className={`rounded-full cursor-pointer p-1 transition-all ${activeTheme === "light"
53
+ ? "bg-primary text-primary-foreground"
54
+ : "bg-transparent hover:bg-muted/50"
55
+ }`}
42
56
  >
43
57
  <Sun className="h-4 w-4" />
44
58
  </ToggleGroupItem>
45
- <ToggleGroupItem
46
- value="system"
47
- size="sm"
48
- aria-label="System Mode"
49
- className={`rounded-full p-1 transition-all ${
50
- selectedTheme === "system"
51
- ? "bg-primary text-primary-foreground"
52
- : "bg-transparent hover:bg-muted/50"
53
- }`}
54
- >
55
- <Monitor className="h-4 w-4" />
56
- </ToggleGroupItem>
57
59
  <ToggleGroupItem
58
60
  value="dark"
59
61
  size="sm"
60
62
  aria-label="Dark Mode"
61
- className={`rounded-full p-1 transition-all ${
62
- selectedTheme === "dark"
63
- ? "bg-primary text-primary-foreground"
64
- : "bg-transparent hover:bg-muted/50"
65
- }`}
63
+ className={`rounded-full cursor-pointer p-1 transition-all ${activeTheme === "dark"
64
+ ? "bg-primary text-primary-foreground"
65
+ : "bg-transparent hover:bg-muted/50"
66
+ }`}
66
67
  >
67
68
  <Moon className="h-4 w-4" />
68
69
  </ToggleGroupItem>
@@ -29,7 +29,7 @@ const TabsTrigger = React.forwardRef<
29
29
  <TabsPrimitive.Trigger
30
30
  ref={ref}
31
31
  className={cn(
32
- "inline-flex items-center justify-center whitespace-nowrap px-1.5 py-[0.58rem] text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-primary border-b-2 border-transparent data-[state=active]:text-foreground font-code",
32
+ "inline-flex items-center justify-center whitespace-nowrap px-1.5 py-[0.58rem] text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-primary border-b-2 border-transparent data-[state=active]:text-foreground font-code cursor-pointer",
33
33
  className
34
34
  )}
35
35
  {...props}
@@ -0,0 +1,35 @@
1
+ import { defineConfig } from "eslint/config";
2
+ import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
3
+ import nextTypescript from "eslint-config-next/typescript";
4
+ import path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import js from "@eslint/js";
7
+ import { FlatCompat } from "@eslint/eslintrc";
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
11
+ const compat = new FlatCompat({
12
+ baseDirectory: __dirname,
13
+ recommendedConfig: js.configs.recommended,
14
+ allConfig: js.configs.all
15
+ });
16
+
17
+ export default defineConfig([{
18
+ extends: [
19
+ ...nextCoreWebVitals,
20
+ ...nextTypescript,
21
+ ...compat.extends("plugin:@typescript-eslint/recommended")
22
+ ],
23
+
24
+ rules: {
25
+ "@typescript-eslint/no-explicit-any": "warn",
26
+
27
+ "@typescript-eslint/no-unused-vars": ["warn", {
28
+ argsIgnorePattern: "^_",
29
+ varsIgnorePattern: "^_",
30
+ caughtErrorsIgnorePattern: "^_",
31
+ }],
32
+
33
+ "@typescript-eslint/no-empty-object-type": "off",
34
+ },
35
+ }]);
@@ -2,27 +2,28 @@ import { useState, useCallback, useEffect } from 'react';
2
2
 
3
3
  export function useScrollPosition(threshold = 0.5) {
4
4
  const [isScrolled, setIsScrolled] = useState(false);
5
-
5
+
6
6
  const handleScroll = useCallback(() => {
7
7
  if (typeof window === 'undefined') return;
8
-
8
+
9
9
  const scrollPosition = window.scrollY;
10
10
  const viewportHeight = window.innerHeight;
11
11
  const shouldBeSticky = scrollPosition > viewportHeight * threshold;
12
-
12
+
13
13
  setIsScrolled(prev => shouldBeSticky !== prev ? shouldBeSticky : prev);
14
14
  }, [threshold]);
15
15
 
16
16
  // Add scroll event listener
17
17
  useEffect(() => {
18
18
  // Initial check
19
+ // eslint-disable-next-line react-hooks/set-state-in-effect
19
20
  handleScroll();
20
-
21
+
21
22
  window.addEventListener('scroll', handleScroll, { passive: true });
22
23
  return () => {
23
24
  window.removeEventListener('scroll', handleScroll);
24
25
  };
25
26
  }, [handleScroll]);
26
-
27
+
27
28
  return isScrolled;
28
29
  }
@@ -1,62 +1,67 @@
1
1
  {
2
2
  "name": "docubook",
3
- "version": "1.16.1",
3
+ "version": "2.0.0-beta.2",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "next dev",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "next lint"
9
+ "lint": "eslint ."
10
10
  },
11
11
  "dependencies": {
12
- "@docsearch/css": "3",
12
+ "@docsearch/css": "^3.9.0",
13
13
  "@docsearch/react": "^3.9.0",
14
- "@radix-ui/react-accordion": "^1.2.0",
15
- "@radix-ui/react-avatar": "^1.1.0",
16
- "@radix-ui/react-collapsible": "^1.1.0",
17
- "@radix-ui/react-dialog": "^1.1.6",
18
- "@radix-ui/react-dropdown-menu": "^2.1.1",
19
- "@radix-ui/react-popover": "^1.1.6",
20
- "@radix-ui/react-scroll-area": "^1.2.0",
21
- "@radix-ui/react-separator": "^1.0.3",
22
- "@radix-ui/react-slot": "^1.1.0",
23
- "@radix-ui/react-tabs": "^1.1.0",
24
- "@radix-ui/react-toggle": "^1.1.2",
25
- "@radix-ui/react-toggle-group": "^1.1.2",
26
- "algoliasearch": "^5.35.0",
27
- "class-variance-authority": "^0.7.0",
14
+ "@radix-ui/react-accordion": "^1.2.12",
15
+ "@radix-ui/react-avatar": "^1.1.11",
16
+ "@radix-ui/react-collapsible": "^1.1.12",
17
+ "@radix-ui/react-dialog": "^1.1.15",
18
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
19
+ "@radix-ui/react-popover": "^1.1.15",
20
+ "@radix-ui/react-scroll-area": "^1.2.10",
21
+ "@radix-ui/react-separator": "^1.1.8",
22
+ "@radix-ui/react-slot": "^1.2.4",
23
+ "@radix-ui/react-tabs": "^1.1.13",
24
+ "@radix-ui/react-toggle": "^1.1.10",
25
+ "@radix-ui/react-toggle-group": "^1.1.11",
26
+ "algoliasearch": "^5.46.3",
27
+ "class-variance-authority": "^0.7.1",
28
28
  "clsx": "^2.1.1",
29
- "cmdk": "1.0.0",
30
- "framer-motion": "^12.4.1",
31
- "geist": "^1.3.1",
29
+ "cmdk": "^1.1.1",
30
+ "framer-motion": "^12.26.2",
31
+ "geist": "^1.5.1",
32
32
  "gray-matter": "^4.0.3",
33
33
  "lucide-react": "^0.511.0",
34
- "next": "^14.2.6",
34
+ "next": "^16.1.6",
35
35
  "next-mdx-remote": "^5.0.0",
36
- "next-themes": "^0.3.0",
37
- "react": "^18.3.1",
38
- "react-dom": "^18.3.1",
36
+ "next-themes": "^0.4.4",
37
+ "react": "19.2.3",
38
+ "react-dom": "19.2.3",
39
39
  "react-icons": "^5.5.0",
40
40
  "rehype-autolink-headings": "^7.1.0",
41
- "rehype-code-titles": "^1.2.0",
42
- "rehype-prism-plus": "^2.0.0",
41
+ "rehype-code-titles": "^1.2.1",
42
+ "rehype-prism-plus": "^2.0.1",
43
43
  "rehype-slug": "^6.0.0",
44
- "remark-gfm": "^4.0.0",
45
- "sonner": "^1.4.3",
46
- "tailwind-merge": "^2.5.2",
44
+ "remark-gfm": "^4.0.1",
45
+ "sonner": "^1.7.4",
46
+ "tailwind-merge": "^2.6.0",
47
47
  "tailwindcss-animate": "^1.0.7",
48
48
  "unist-util-visit": "^5.0.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@tailwindcss/typography": "^0.5.14",
52
- "@types/node": "^20",
53
- "@types/react": "^18",
54
- "@types/react-dom": "^18",
55
- "autoprefixer": "^10.4.20",
56
- "eslint": "^8",
57
- "eslint-config-next": "^14.2.6",
58
- "postcss": "^8",
59
- "tailwindcss": "^3.4.10",
60
- "typescript": "^5"
51
+ "@tailwindcss/postcss": "^4.1.18",
52
+ "@tailwindcss/typography": "^0.5.19",
53
+ "@types/node": "^20.19.30",
54
+ "@types/react": "19.2.8",
55
+ "@types/react-dom": "19.2.3",
56
+ "autoprefixer": "^10.4.23",
57
+ "eslint": "^9.39.2",
58
+ "eslint-config-next": "16.1.3",
59
+ "postcss": "^8.5.6",
60
+ "tailwindcss": "^4.1.18",
61
+ "typescript": "^5.9.3"
62
+ },
63
+ "overrides": {
64
+ "@types/react": "19.2.8",
65
+ "@types/react-dom": "19.2.3"
61
66
  }
62
67
  }
@@ -1,6 +1,6 @@
1
1
  module.exports = {
2
2
  plugins: {
3
- tailwindcss: {},
3
+ '@tailwindcss/postcss': {},
4
4
  autoprefixer: {},
5
5
  },
6
6
  };