@docubook/create 2.4.0 → 2.5.1
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/package.json +1 -1
- package/src/dist/app/docs/[[...slug]]/page.tsx +55 -59
- package/src/dist/app/docs/layout.tsx +11 -4
- package/src/dist/app/layout.tsx +10 -7
- package/src/dist/app/page.tsx +1 -1
- package/src/dist/components/{context-popover.tsx → ContextPopover.tsx} +3 -2
- package/src/dist/components/DocSearch.tsx +16 -15
- package/src/dist/components/{docs-breadcrumb.tsx → DocsBreadcrumb.tsx} +1 -1
- package/src/dist/components/DocsNavbar.tsx +46 -0
- package/src/dist/components/DocsSidebar.tsx +207 -0
- package/src/dist/components/Github.tsx +26 -0
- package/src/dist/components/{scroll-to-top.tsx → ScrollToTop.tsx} +16 -9
- package/src/dist/components/SearchBox.tsx +39 -0
- package/src/dist/components/SearchContext.tsx +47 -0
- package/src/dist/components/SearchModal.tsx +77 -79
- package/src/dist/components/SearchTrigger.tsx +20 -15
- package/src/dist/components/Sponsor.tsx +2 -2
- package/src/dist/components/{theme-toggle.tsx → ThemeToggle.tsx} +10 -10
- package/src/dist/components/TocObserver.tsx +197 -0
- package/src/dist/components/footer.tsx +16 -12
- package/src/dist/components/leftbar.tsx +45 -73
- package/src/dist/components/markdown/AccordionContext.tsx +21 -0
- package/src/dist/components/markdown/AccordionGroupMdx.tsx +11 -22
- package/src/dist/components/markdown/AccordionMdx.tsx +58 -59
- package/src/dist/components/markdown/PreMdx.tsx +2 -2
- package/src/dist/components/navbar.tsx +130 -53
- package/src/dist/components/toc.tsx +16 -14
- package/src/dist/components/typography.tsx +1 -1
- package/src/dist/components/ui/icon-cloud.tsx +353 -0
- package/src/dist/components/ui/scroll-area.tsx +2 -2
- package/src/dist/components/ui/sheet.tsx +4 -4
- package/src/dist/components/ui/toggle.tsx +3 -3
- package/src/dist/docs/components/accordion-group.mdx +13 -12
- package/src/dist/docs/components/accordion.mdx +11 -14
- package/src/dist/docu.json +3 -0
- package/src/dist/hooks/useActiveSection.ts +45 -33
- package/src/dist/hooks/useScrollPosition.ts +16 -14
- package/src/dist/lib/search/algolia.ts +5 -0
- package/src/dist/lib/search/built-in.ts +43 -0
- package/src/dist/lib/search/config.ts +7 -0
- package/src/dist/lib/toc.ts +1 -0
- package/src/dist/lib/utils.ts +13 -54
- package/src/dist/package.json +1 -1
- package/src/dist/styles/algolia.css +12 -35
- package/src/dist/styles/{syntax.css → override.css} +82 -39
- package/src/dist/tailwind.config.ts +11 -110
- package/src/dist/components/AccordionContext.ts +0 -4
- package/src/dist/components/GithubStart.tsx +0 -44
- package/src/dist/components/mob-toc.tsx +0 -134
- package/src/dist/components/search.tsx +0 -55
- package/src/dist/components/toc-observer.tsx +0 -254
- /package/src/dist/components/{docs-menu.tsx → DocsMenu.tsx} +0 -0
- /package/src/dist/components/{edit-on-github.tsx → EditWithGithub.tsx} +0 -0
- /package/src/dist/components/{theme-provider.tsx → ThemeProvider.tsx} +0 -0
|
@@ -7,7 +7,7 @@ import { cva, type VariantProps } from "class-variance-authority"
|
|
|
7
7
|
import { cn } from "@/lib/utils"
|
|
8
8
|
|
|
9
9
|
const toggleVariants = cva(
|
|
10
|
-
"inline-flex items-center justify-center gap-1 rounded-md text-
|
|
10
|
+
"inline-flex items-center justify-center gap-1 rounded-md text-xs font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-3 [&_svg]:shrink-0",
|
|
11
11
|
{
|
|
12
12
|
variants: {
|
|
13
13
|
variant: {
|
|
@@ -18,7 +18,7 @@ const toggleVariants = cva(
|
|
|
18
18
|
size: {
|
|
19
19
|
default: "h-9 px-2 min-w-9",
|
|
20
20
|
sm: "h-8 px-1.5 min-w-8",
|
|
21
|
-
xs: "h-
|
|
21
|
+
xs: "h-6 px-1.5 min-w-6",
|
|
22
22
|
lg: "h-10 px-2.5 min-w-10",
|
|
23
23
|
},
|
|
24
24
|
},
|
|
@@ -32,7 +32,7 @@ const toggleVariants = cva(
|
|
|
32
32
|
const Toggle = React.forwardRef<
|
|
33
33
|
React.ElementRef<typeof TogglePrimitive.Root>,
|
|
34
34
|
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
|
35
|
-
|
|
35
|
+
VariantProps<typeof toggleVariants>
|
|
36
36
|
>(({ className, variant, size, ...props }, ref) => (
|
|
37
37
|
<TogglePrimitive.Root
|
|
38
38
|
ref={ref}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
title
|
|
2
|
+
title: Accordion Group
|
|
3
3
|
description: for writing multiple accordions and grouping them together
|
|
4
|
-
date
|
|
4
|
+
date: 10-08-2025
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
An accordion is like a button that opens and closes information. To avoid clutter, long information
|
|
7
|
+
An accordion is like a button that opens and closes information. To avoid clutter, long information
|
|
8
|
+
can be hidden first and then revealed when clicked.
|
|
8
9
|
|
|
9
10
|
<Note type="note" title="Note">
|
|
10
11
|
Group related accordions together using `<AccordionGroup>`. This creates a cohesive section of accordions that can be individually expanded or collapsed.
|
|
@@ -18,10 +19,11 @@ An accordion is like a button that opens and closes information. To avoid clutte
|
|
|
18
19
|
</Accordion>
|
|
19
20
|
|
|
20
21
|
<Accordion title="With icon props" icon="MousePointerClick">
|
|
21
|
-
|
|
22
|
+
This accordion includes a [Lucide Icon](https://lucide.dev/icons/) because the `icon` prop is
|
|
23
|
+
provided.
|
|
22
24
|
</Accordion>
|
|
23
25
|
|
|
24
|
-
<Accordion title="
|
|
26
|
+
<Accordion title="With Code Block">
|
|
25
27
|
You can put other components inside Accordions.
|
|
26
28
|
```jsx:helloword.jsx
|
|
27
29
|
class HelloWorld {
|
|
@@ -45,7 +47,7 @@ public static void main(String[] args) {
|
|
|
45
47
|
This accordion includes a Lucide icon because the `icon` prop is provided.
|
|
46
48
|
</Accordion>
|
|
47
49
|
|
|
48
|
-
<Accordion title="
|
|
50
|
+
<Accordion title="With Code Block">
|
|
49
51
|
You can put other components inside Accordions.
|
|
50
52
|
```jsx:helloword.jsx
|
|
51
53
|
class HelloWorld {
|
|
@@ -60,9 +62,8 @@ public static void main(String[] args) {
|
|
|
60
62
|
|
|
61
63
|
## Props
|
|
62
64
|
|
|
63
|
-
| Prop
|
|
64
|
-
|
|
65
|
-
| `title`
|
|
66
|
-
| `children` | ReactNode | null
|
|
67
|
-
| `
|
|
68
|
-
| `icon` | string | undefined | Optional. Adds a Lucide icon before the title in the accordion header. |
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
| ---------- | --------- | --------- | ------------------------------------------------------------------------------------------------------------- |
|
|
67
|
+
| `title` | string | - | **Required**. The text displayed in the accordion header. |
|
|
68
|
+
| `children` | ReactNode | null | The content to be displayed when the accordion is expanded. Can be plain text, markdown, or React components. |
|
|
69
|
+
| `icon` | string | undefined | Optional. Adds a Lucide icon before the title in the accordion header. |
|
|
@@ -4,9 +4,7 @@ description: A component used to create collapsible content that can be hidden a
|
|
|
4
4
|
date: 22-12-2024
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
### Basic Usage
|
|
7
|
+
## Basic Usage
|
|
10
8
|
|
|
11
9
|
```plaintext
|
|
12
10
|
<Accordion title="Click to expand">
|
|
@@ -17,13 +15,14 @@ date: 22-12-2024
|
|
|
17
15
|
Render as :
|
|
18
16
|
|
|
19
17
|
<Accordion title="Click to expand">
|
|
20
|
-
|
|
18
|
+
This is a simple accordion component that can be toggled by clicking the header. The content can
|
|
19
|
+
include any valid React nodes, including text, components, and markdown.
|
|
21
20
|
</Accordion>
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
## With Icon
|
|
24
23
|
|
|
25
24
|
````plaintext
|
|
26
|
-
<Accordion title="Code Block"
|
|
25
|
+
<Accordion title="Code Block" icon="Code">
|
|
27
26
|
```javascript:main.js showLineNumbers {3-4}
|
|
28
27
|
function isRocketAboutToCrash() {
|
|
29
28
|
// Check if the rocket is stable
|
|
@@ -37,7 +36,7 @@ Render as :
|
|
|
37
36
|
|
|
38
37
|
Render as :
|
|
39
38
|
|
|
40
|
-
<Accordion title="Code Block"
|
|
39
|
+
<Accordion title="Code Block" icon="Code">
|
|
41
40
|
```javascript:main.js showLineNumbers {3-4}
|
|
42
41
|
function isRocketAboutToCrash() {
|
|
43
42
|
// Check if the rocket is stable
|
|
@@ -50,10 +49,8 @@ Render as :
|
|
|
50
49
|
|
|
51
50
|
## Props
|
|
52
51
|
|
|
53
|
-
| Prop
|
|
54
|
-
|
|
55
|
-
| `title`
|
|
56
|
-
| `children` | ReactNode | null
|
|
57
|
-
| `
|
|
58
|
-
| `icon` | string | undefined | Optional. Adds a Lucide icon before the title in the accordion header. |
|
|
59
|
-
|
|
52
|
+
| Prop | Type | Default | Description |
|
|
53
|
+
| ---------- | --------- | --------- | ------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| `title` | string | - | **Required**. The text displayed in the accordion header. |
|
|
55
|
+
| `children` | ReactNode | null | The content to be displayed when the accordion is expanded. Can be plain text, markdown, or React components. |
|
|
56
|
+
| `icon` | string | undefined | Optional. Adds a Lucide icon before the title in the accordion header. |
|
package/src/dist/docu.json
CHANGED
|
@@ -1,68 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback, useEffect, useRef } from "react"
|
|
4
|
+
import { TocItem } from "@/lib/toc"
|
|
3
5
|
|
|
4
6
|
export function useActiveSection(tocs: TocItem[]) {
|
|
5
|
-
const [activeId, setActiveId] = useState<string | null>(null)
|
|
6
|
-
const observerRef = useRef<IntersectionObserver | null>(null)
|
|
7
|
-
const clickedIdRef = useRef<string | null>(null)
|
|
7
|
+
const [activeId, setActiveId] = useState<string | null>(null)
|
|
8
|
+
const observerRef = useRef<IntersectionObserver | null>(null)
|
|
9
|
+
const clickedIdRef = useRef<string | null>(null)
|
|
10
|
+
|
|
11
|
+
const activeIdRef = useRef<string | null>(null)
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
activeIdRef.current = activeId
|
|
15
|
+
}, [activeId])
|
|
8
16
|
|
|
9
17
|
// Handle intersection observer for active section
|
|
10
18
|
useEffect(() => {
|
|
11
|
-
if (typeof document ===
|
|
19
|
+
if (typeof document === "undefined" || !tocs.length) return
|
|
12
20
|
|
|
13
21
|
const handleIntersect = (entries: IntersectionObserverEntry[]) => {
|
|
14
|
-
if (clickedIdRef.current) return
|
|
22
|
+
if (clickedIdRef.current) return
|
|
15
23
|
|
|
16
|
-
const visibleEntries = entries.filter(entry => entry.isIntersecting)
|
|
17
|
-
if (!visibleEntries.length) return
|
|
24
|
+
const visibleEntries = entries.filter((entry) => entry.isIntersecting)
|
|
25
|
+
if (!visibleEntries.length) return
|
|
18
26
|
|
|
19
27
|
// Find the most visible entry
|
|
20
28
|
const mostVisibleEntry = visibleEntries.reduce((prev, current) => {
|
|
21
|
-
return current.intersectionRatio > prev.intersectionRatio ? current : prev
|
|
22
|
-
}, visibleEntries[0])
|
|
29
|
+
return current.intersectionRatio > prev.intersectionRatio ? current : prev
|
|
30
|
+
}, visibleEntries[0])
|
|
23
31
|
|
|
24
|
-
const newActiveId = mostVisibleEntry.target.id
|
|
25
|
-
if (newActiveId !==
|
|
26
|
-
setActiveId(newActiveId)
|
|
32
|
+
const newActiveId = mostVisibleEntry.target.id
|
|
33
|
+
if (newActiveId !== activeIdRef.current) {
|
|
34
|
+
setActiveId(newActiveId)
|
|
27
35
|
}
|
|
28
|
-
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Determine the scroll root: #scroll-container is only used on desktop (lg)
|
|
39
|
+
const isDesktop = window.innerWidth >= 1024
|
|
40
|
+
const container = isDesktop ? document.getElementById("scroll-container") : null
|
|
29
41
|
|
|
30
42
|
// Initialize intersection observer
|
|
31
43
|
observerRef.current = new IntersectionObserver(handleIntersect, {
|
|
32
|
-
root:
|
|
33
|
-
rootMargin:
|
|
34
|
-
threshold: 0
|
|
35
|
-
})
|
|
44
|
+
root: container,
|
|
45
|
+
rootMargin: isDesktop ? "0px 0px -60% 0px" : "-160px 0px -60% 0px",
|
|
46
|
+
threshold: 0,
|
|
47
|
+
})
|
|
36
48
|
|
|
37
49
|
// Observe all headings
|
|
38
|
-
tocs.forEach(toc => {
|
|
39
|
-
const element = document.getElementById(toc.href.slice(1))
|
|
50
|
+
tocs.forEach((toc) => {
|
|
51
|
+
const element = document.getElementById(toc.href.slice(1))
|
|
40
52
|
if (element) {
|
|
41
|
-
observerRef.current?.observe(element)
|
|
53
|
+
observerRef.current?.observe(element)
|
|
42
54
|
}
|
|
43
|
-
})
|
|
55
|
+
})
|
|
44
56
|
|
|
45
57
|
// Cleanup
|
|
46
58
|
return () => {
|
|
47
|
-
observerRef.current?.disconnect()
|
|
48
|
-
}
|
|
49
|
-
}, [tocs, activeId
|
|
59
|
+
observerRef.current?.disconnect()
|
|
60
|
+
}
|
|
61
|
+
}, [tocs]) // Only depend on tocs, handle activeId via ref
|
|
50
62
|
|
|
51
63
|
const handleLinkClick = useCallback((id: string) => {
|
|
52
|
-
clickedIdRef.current = id
|
|
53
|
-
setActiveId(id)
|
|
64
|
+
clickedIdRef.current = id
|
|
65
|
+
setActiveId(id)
|
|
54
66
|
|
|
55
67
|
// Reset clicked state after scroll completes
|
|
56
68
|
const timer = setTimeout(() => {
|
|
57
|
-
clickedIdRef.current = null
|
|
58
|
-
}, 1000)
|
|
69
|
+
clickedIdRef.current = null
|
|
70
|
+
}, 1000)
|
|
59
71
|
|
|
60
|
-
return () => clearTimeout(timer)
|
|
61
|
-
}, [])
|
|
72
|
+
return () => clearTimeout(timer)
|
|
73
|
+
}, [])
|
|
62
74
|
|
|
63
75
|
return {
|
|
64
76
|
activeId,
|
|
65
77
|
setActiveId,
|
|
66
78
|
handleLinkClick,
|
|
67
|
-
}
|
|
79
|
+
}
|
|
68
80
|
}
|
|
@@ -1,29 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useState, useCallback, useEffect } from "react"
|
|
2
4
|
|
|
3
5
|
export function useScrollPosition(threshold = 0.5) {
|
|
4
|
-
const [isScrolled, setIsScrolled] = useState(false)
|
|
6
|
+
const [isScrolled, setIsScrolled] = useState(false)
|
|
5
7
|
|
|
6
8
|
const handleScroll = useCallback(() => {
|
|
7
|
-
if (typeof window ===
|
|
9
|
+
if (typeof window === "undefined") return
|
|
8
10
|
|
|
9
|
-
const scrollPosition = window.scrollY
|
|
10
|
-
const viewportHeight = window.innerHeight
|
|
11
|
-
const shouldBeSticky = scrollPosition > viewportHeight * threshold
|
|
11
|
+
const scrollPosition = window.scrollY
|
|
12
|
+
const viewportHeight = window.innerHeight
|
|
13
|
+
const shouldBeSticky = scrollPosition > viewportHeight * threshold
|
|
12
14
|
|
|
13
|
-
setIsScrolled(prev => shouldBeSticky !== prev ? shouldBeSticky : prev)
|
|
14
|
-
}, [threshold])
|
|
15
|
+
setIsScrolled((prev) => (shouldBeSticky !== prev ? shouldBeSticky : prev))
|
|
16
|
+
}, [threshold])
|
|
15
17
|
|
|
16
18
|
// Add scroll event listener
|
|
17
19
|
useEffect(() => {
|
|
18
20
|
// Initial check
|
|
19
21
|
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
20
|
-
handleScroll()
|
|
22
|
+
handleScroll()
|
|
21
23
|
|
|
22
|
-
window.addEventListener(
|
|
24
|
+
window.addEventListener("scroll", handleScroll, { passive: true })
|
|
23
25
|
return () => {
|
|
24
|
-
window.removeEventListener(
|
|
25
|
-
}
|
|
26
|
-
}, [handleScroll])
|
|
26
|
+
window.removeEventListener("scroll", handleScroll)
|
|
27
|
+
}
|
|
28
|
+
}, [handleScroll])
|
|
27
29
|
|
|
28
|
-
return isScrolled
|
|
30
|
+
return isScrolled
|
|
29
31
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ROUTES, type EachRoute } from "../routes"
|
|
2
|
+
|
|
3
|
+
export type SearchResult = {
|
|
4
|
+
title: string
|
|
5
|
+
href: string
|
|
6
|
+
noLink?: boolean
|
|
7
|
+
items?: undefined
|
|
8
|
+
score?: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function helperSearch(
|
|
12
|
+
query: string,
|
|
13
|
+
node: EachRoute,
|
|
14
|
+
prefix: string,
|
|
15
|
+
currenLevel: number,
|
|
16
|
+
maxLevel?: number
|
|
17
|
+
) {
|
|
18
|
+
const res: EachRoute[] = []
|
|
19
|
+
let parentHas = false
|
|
20
|
+
|
|
21
|
+
const nextLink = `${prefix}${node.href}`
|
|
22
|
+
if (!node.noLink && node.title.toLowerCase().includes(query.toLowerCase())) {
|
|
23
|
+
res.push({ ...node, items: undefined, href: nextLink })
|
|
24
|
+
parentHas = true
|
|
25
|
+
}
|
|
26
|
+
const goNext = maxLevel ? currenLevel < maxLevel : true
|
|
27
|
+
if (goNext)
|
|
28
|
+
node.items?.forEach((item) => {
|
|
29
|
+
const innerRes = helperSearch(query, item, nextLink, currenLevel + 1, maxLevel)
|
|
30
|
+
if (!!innerRes.length && !parentHas && !node.noLink) {
|
|
31
|
+
res.push({ ...node, items: undefined, href: nextLink })
|
|
32
|
+
parentHas = true
|
|
33
|
+
}
|
|
34
|
+
res.push(...innerRes)
|
|
35
|
+
})
|
|
36
|
+
return res
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function advanceSearch(query: string) {
|
|
40
|
+
return ROUTES.map((node) =>
|
|
41
|
+
helperSearch(query, node, "", 1, query.length == 0 ? 2 : undefined)
|
|
42
|
+
).flat()
|
|
43
|
+
}
|
package/src/dist/lib/toc.ts
CHANGED
package/src/dist/lib/utils.ts
CHANGED
|
@@ -1,80 +1,39 @@
|
|
|
1
|
-
import { type ClassValue, clsx } from "clsx"
|
|
2
|
-
import { twMerge } from "tailwind-merge"
|
|
3
|
-
import { EachRoute, ROUTES } from "./routes";
|
|
1
|
+
import { type ClassValue, clsx } from "clsx"
|
|
2
|
+
import { twMerge } from "tailwind-merge"
|
|
4
3
|
|
|
5
4
|
export function cn(...inputs: ClassValue[]) {
|
|
6
|
-
return twMerge(clsx(inputs))
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function helperSearch(
|
|
10
|
-
query: string,
|
|
11
|
-
node: EachRoute,
|
|
12
|
-
prefix: string,
|
|
13
|
-
currenLevel: number,
|
|
14
|
-
maxLevel?: number
|
|
15
|
-
) {
|
|
16
|
-
const res: EachRoute[] = [];
|
|
17
|
-
let parentHas = false;
|
|
18
|
-
|
|
19
|
-
const nextLink = `${prefix}${node.href}`;
|
|
20
|
-
if (!node.noLink && node.title.toLowerCase().includes(query.toLowerCase())) {
|
|
21
|
-
res.push({ ...node, items: undefined, href: nextLink });
|
|
22
|
-
parentHas = true;
|
|
23
|
-
}
|
|
24
|
-
const goNext = maxLevel ? currenLevel < maxLevel : true;
|
|
25
|
-
if (goNext)
|
|
26
|
-
node.items?.forEach((item) => {
|
|
27
|
-
const innerRes = helperSearch(
|
|
28
|
-
query,
|
|
29
|
-
item,
|
|
30
|
-
nextLink,
|
|
31
|
-
currenLevel + 1,
|
|
32
|
-
maxLevel
|
|
33
|
-
);
|
|
34
|
-
if (!!innerRes.length && !parentHas && !node.noLink) {
|
|
35
|
-
res.push({ ...node, items: undefined, href: nextLink });
|
|
36
|
-
parentHas = true;
|
|
37
|
-
}
|
|
38
|
-
res.push(...innerRes);
|
|
39
|
-
});
|
|
40
|
-
return res;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function advanceSearch(query: string) {
|
|
44
|
-
return ROUTES.map((node) =>
|
|
45
|
-
helperSearch(query, node, "", 1, query.length == 0 ? 2 : undefined)
|
|
46
|
-
).flat();
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
47
6
|
}
|
|
48
7
|
|
|
49
8
|
// Thursday, May 23, 2024
|
|
50
9
|
export function formatDate(dateStr: string): string {
|
|
51
|
-
const [day, month, year] = dateStr.split("-").map(Number)
|
|
52
|
-
const date = new Date(year, month - 1, day)
|
|
10
|
+
const [day, month, year] = dateStr.split("-").map(Number)
|
|
11
|
+
const date = new Date(year, month - 1, day)
|
|
53
12
|
|
|
54
13
|
const options: Intl.DateTimeFormatOptions = {
|
|
55
14
|
weekday: "long",
|
|
56
15
|
year: "numeric",
|
|
57
16
|
month: "long",
|
|
58
17
|
day: "numeric",
|
|
59
|
-
}
|
|
18
|
+
}
|
|
60
19
|
|
|
61
|
-
return date.toLocaleDateString("en-US", options)
|
|
20
|
+
return date.toLocaleDateString("en-US", options)
|
|
62
21
|
}
|
|
63
22
|
|
|
64
23
|
// May 23, 2024
|
|
65
24
|
export function formatDate2(dateStr: string): string {
|
|
66
|
-
const [day, month, year] = dateStr.split("-").map(Number)
|
|
67
|
-
const date = new Date(year, month - 1, day)
|
|
25
|
+
const [day, month, year] = dateStr.split("-").map(Number)
|
|
26
|
+
const date = new Date(year, month - 1, day)
|
|
68
27
|
|
|
69
28
|
const options: Intl.DateTimeFormatOptions = {
|
|
70
29
|
month: "short",
|
|
71
30
|
day: "numeric",
|
|
72
31
|
year: "numeric",
|
|
73
|
-
}
|
|
74
|
-
return date.toLocaleDateString("en-US", options)
|
|
32
|
+
}
|
|
33
|
+
return date.toLocaleDateString("en-US", options)
|
|
75
34
|
}
|
|
76
35
|
|
|
77
36
|
export function stringToDate(date: string) {
|
|
78
|
-
const [day, month, year] = date.split("-").map(Number)
|
|
79
|
-
return new Date(year, month - 1, day)
|
|
37
|
+
const [day, month, year] = date.split("-").map(Number)
|
|
38
|
+
return new Date(year, month - 1, day)
|
|
80
39
|
}
|
package/src/dist/package.json
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
================================================================================
|
|
3
|
-
DocSearch Component Styling (Refactored Version)
|
|
4
|
-
================================================================================
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/* -- LANGKAH 1: Definisi Variabel Global --
|
|
8
|
-
Variabel tema DocSearch sekarang didefinisikan secara global di :root.
|
|
9
|
-
Ini menyederhanakan pewarisan tema dan memastikan konsistensi.
|
|
10
|
-
Mode gelap secara otomatis menimpa variabel ini karena .dark di globals.css.
|
|
11
|
-
*/
|
|
12
1
|
:root {
|
|
13
2
|
--docsearch-primary-color: hsl(var(--primary));
|
|
14
3
|
--docsearch-text-color: hsl(var(--muted-foreground));
|
|
@@ -18,47 +7,43 @@
|
|
|
18
7
|
--docsearch-muted-color: hsl(var(--muted-foreground));
|
|
19
8
|
--docsearch-container-background: rgba(0, 0, 0, 0.7);
|
|
20
9
|
--docsearch-logo-color: hsl(var(--primary-foreground));
|
|
21
|
-
|
|
10
|
+
|
|
22
11
|
/* Modal */
|
|
23
12
|
--docsearch-modal-width: 560px;
|
|
24
13
|
--docsearch-modal-height: 600px;
|
|
25
14
|
--docsearch-modal-background: hsl(var(--background));
|
|
26
15
|
--docsearch-modal-shadow: 0 0 0 1px hsl(var(--border)), 0 8px 20px rgba(0, 0, 0, 0.2);
|
|
27
|
-
|
|
16
|
+
|
|
28
17
|
/* SearchBox */
|
|
29
18
|
--docsearch-searchbox-height: 56px;
|
|
30
19
|
--docsearch-searchbox-background: hsl(var(--input));
|
|
31
20
|
--docsearch-searchbox-focus-background: hsl(var(--card));
|
|
32
21
|
--docsearch-searchbox-shadow: none;
|
|
33
|
-
|
|
34
|
-
/* Hit (
|
|
22
|
+
|
|
23
|
+
/* Hit (Search Result) */
|
|
35
24
|
--docsearch-hit-height: 56px;
|
|
36
25
|
--docsearch-hit-color: hsl(var(--foreground));
|
|
37
26
|
--docsearch-hit-active-color: hsl(var(--primary-foreground));
|
|
38
27
|
--docsearch-hit-background: hsl(var(--card));
|
|
39
28
|
--docsearch-hit-shadow: none;
|
|
40
|
-
|
|
29
|
+
|
|
41
30
|
/* Keys */
|
|
42
31
|
--docsearch-key-gradient: none;
|
|
43
32
|
--docsearch-key-shadow: none;
|
|
44
33
|
--docsearch-key-pressed-shadow: none;
|
|
45
|
-
|
|
34
|
+
|
|
46
35
|
/* Footer */
|
|
47
36
|
--docsearch-footer-height: 44px;
|
|
48
37
|
--docsearch-footer-background: hsl(var(--background));
|
|
49
38
|
--docsearch-footer-shadow: none;
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
/* -- LANGKAH 2: Gaya untuk Tombol Awal --
|
|
53
|
-
Gaya ini spesifik untuk tombol yang ada di Navbar,
|
|
54
|
-
yang dibungkus oleh <div class="docsearch">.
|
|
55
|
-
*/
|
|
56
41
|
.docsearch .DocSearch-Button {
|
|
57
42
|
background-color: hsl(var(--secondary));
|
|
58
43
|
border: 1px solid hsl(var(--border));
|
|
59
44
|
border-radius: 9999px;
|
|
60
|
-
width:
|
|
61
|
-
height:
|
|
45
|
+
width: 250px;
|
|
46
|
+
height: 35px;
|
|
62
47
|
color: hsl(var(--muted-foreground));
|
|
63
48
|
transition: width 0.3s ease;
|
|
64
49
|
margin: 0;
|
|
@@ -71,8 +56,8 @@
|
|
|
71
56
|
|
|
72
57
|
.docsearch .DocSearch-Search-Icon {
|
|
73
58
|
color: var(--docsearch-muted-color);
|
|
74
|
-
width:
|
|
75
|
-
height:
|
|
59
|
+
width: 1.2rem;
|
|
60
|
+
height: 1.2rem;
|
|
76
61
|
}
|
|
77
62
|
|
|
78
63
|
.docsearch .DocSearch-Button-Placeholder {
|
|
@@ -85,7 +70,7 @@
|
|
|
85
70
|
|
|
86
71
|
.docsearch .DocSearch-Button-Key {
|
|
87
72
|
background: var(--docsearch-primary-color);
|
|
88
|
-
color: var(--docsearch-logo-color);
|
|
73
|
+
color: var(--docsearch-logo-color);
|
|
89
74
|
border-radius: 6px;
|
|
90
75
|
font-size: 14px;
|
|
91
76
|
font-weight: 500;
|
|
@@ -96,10 +81,6 @@
|
|
|
96
81
|
top: 0;
|
|
97
82
|
}
|
|
98
83
|
|
|
99
|
-
/* -- LANGKAH 3: Gaya untuk Modal dan Isinya --
|
|
100
|
-
Gaya ini menargetkan elemen-elemen modal yang dirender terpisah.
|
|
101
|
-
Karena variabel sudah global, kita hanya perlu menata elemennya.
|
|
102
|
-
*/
|
|
103
84
|
.DocSearch-Container .DocSearch-Modal {
|
|
104
85
|
backdrop-filter: blur(8px);
|
|
105
86
|
}
|
|
@@ -117,7 +98,6 @@
|
|
|
117
98
|
border-top: 1px solid hsl(var(--border));
|
|
118
99
|
}
|
|
119
100
|
|
|
120
|
-
/* Gaya untuk tombol keyboard di footer */
|
|
121
101
|
.DocSearch-Footer--commands kbd {
|
|
122
102
|
background-color: hsl(var(--secondary));
|
|
123
103
|
border: 1px solid hsl(var(--border));
|
|
@@ -130,7 +110,6 @@
|
|
|
130
110
|
justify-content: center;
|
|
131
111
|
}
|
|
132
112
|
|
|
133
|
-
/* Menghilangkan gaya default dari ikon di dalam tombol footer */
|
|
134
113
|
.DocSearch-Commands-Key {
|
|
135
114
|
background: none;
|
|
136
115
|
color: hsl(var(--muted-foreground));
|
|
@@ -143,9 +122,6 @@
|
|
|
143
122
|
border-radius: 6px;
|
|
144
123
|
}
|
|
145
124
|
|
|
146
|
-
/* -- LANGKAH 4: Gaya Responsif --
|
|
147
|
-
Tidak ada perubahan, hanya mempertahankan fungsionalitas mobile.
|
|
148
|
-
*/
|
|
149
125
|
@media (max-width: 768px) {
|
|
150
126
|
.docsearch .DocSearch-Button {
|
|
151
127
|
width: 40px;
|
|
@@ -155,6 +131,7 @@
|
|
|
155
131
|
background: none;
|
|
156
132
|
border: none;
|
|
157
133
|
}
|
|
134
|
+
|
|
158
135
|
.docsearch .DocSearch-Button-Placeholder,
|
|
159
136
|
.docsearch .DocSearch-Button-Key {
|
|
160
137
|
display: none;
|