@acmekit/docs-ui 2.13.41
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/Items-YPPZD6C6.mjs +312 -0
- package/dist/chunk-JD7BP7O5.mjs +13144 -0
- package/dist/index.d.mts +1550 -0
- package/dist/index.d.ts +1550 -0
- package/dist/index.js +15218 -0
- package/dist/index.mjs +366 -0
- package/package.json +58 -0
- package/src/components/Badge/index.tsx +74 -0
- package/src/components/BadgesList/index.tsx +18 -0
- package/src/components/BetaBadge/index.tsx +24 -0
- package/src/components/Bordered/index.tsx +21 -0
- package/src/components/BorderedIcon/index.tsx +60 -0
- package/src/components/Breadcrumbs/index.tsx +83 -0
- package/src/components/Button/index.tsx +100 -0
- package/src/components/Card/Layout/Default/index.tsx +124 -0
- package/src/components/Card/Layout/Filler/index.tsx +30 -0
- package/src/components/Card/Layout/Large/index.tsx +88 -0
- package/src/components/Card/Layout/Mini/index.tsx +142 -0
- package/src/components/Card/index.tsx +50 -0
- package/src/components/CardList/index.tsx +40 -0
- package/src/components/ChildDocs/index.tsx +9 -0
- package/src/components/CodeBlock/Actions/AskAi/index.tsx +10 -0
- package/src/components/CodeBlock/Actions/Copy/index.tsx +59 -0
- package/src/components/CodeBlock/Actions/index.tsx +137 -0
- package/src/components/CodeBlock/Collapsible/Button/index.tsx +58 -0
- package/src/components/CodeBlock/Collapsible/Fade/index.tsx +55 -0
- package/src/components/CodeBlock/Collapsible/Lines/index.tsx +22 -0
- package/src/components/CodeBlock/Header/Wrapper/index.tsx +46 -0
- package/src/components/CodeBlock/Header/index.tsx +67 -0
- package/src/components/CodeBlock/Inline/index.tsx +20 -0
- package/src/components/CodeBlock/Line/index.tsx +331 -0
- package/src/components/CodeBlock/index.tsx +510 -0
- package/src/components/CodeMdx/index.tsx +45 -0
- package/src/components/CodeTabs/Item/index.tsx +67 -0
- package/src/components/CodeTabs/index.tsx +319 -0
- package/src/components/ContentMenu/Actions/index.tsx +7 -0
- package/src/components/ContentMenu/Products/index.tsx +64 -0
- package/src/components/ContentMenu/Toc/index.tsx +148 -0
- package/src/components/ContentMenu/Version/index.tsx +77 -0
- package/src/components/ContentMenu/index.tsx +31 -0
- package/src/components/CopyButton/index.tsx +76 -0
- package/src/components/Details/Summary/index.tsx +75 -0
- package/src/components/Details/index.tsx +98 -0
- package/src/components/DetailsList/index.tsx +32 -0
- package/src/components/DottedSeparator/index.tsx +30 -0
- package/src/components/EditButton/index.tsx +32 -0
- package/src/components/EditDate/index.tsx +33 -0
- package/src/components/ErrorPage/Icon/index.tsx +428 -0
- package/src/components/ErrorPage/index.tsx +32 -0
- package/src/components/Feedback/Solutions/index.tsx +105 -0
- package/src/components/Feedback/index.tsx +304 -0
- package/src/components/Footer/index.tsx +23 -0
- package/src/components/Heading/H1/index.tsx +21 -0
- package/src/components/Heading/H2/index.tsx +47 -0
- package/src/components/Heading/H3/index.tsx +42 -0
- package/src/components/Heading/H4/index.tsx +14 -0
- package/src/components/Heading/index.tsx +4 -0
- package/src/components/IconHeadline/index.tsx +15 -0
- package/src/components/Icons/AiAssistant/index.tsx +462 -0
- package/src/components/Icons/ArrowRightDown/index.tsx +30 -0
- package/src/components/Icons/BundledProduct/index.tsx +72 -0
- package/src/components/Icons/CalendarRefresh/index.tsx +70 -0
- package/src/components/Icons/ChefHat/index.tsx +65 -0
- package/src/components/Icons/CircleDottedLine/index.tsx +60 -0
- package/src/components/Icons/CloudSolid/index.tsx +47 -0
- package/src/components/Icons/ColoredAcmeKit/index.tsx +13 -0
- package/src/components/Icons/DecisionProcess/index.tsx +58 -0
- package/src/components/Icons/Erp/index.tsx +92 -0
- package/src/components/Icons/Github/index.tsx +22 -0
- package/src/components/Icons/House/index.tsx +23 -0
- package/src/components/Icons/ImageBinary/index.tsx +69 -0
- package/src/components/Icons/Kapa/index.tsx +22 -0
- package/src/components/Icons/Markdown/index.tsx +25 -0
- package/src/components/Icons/NavigationDropdown/Admin/index.tsx +33 -0
- package/src/components/Icons/NavigationDropdown/Doc/index.tsx +41 -0
- package/src/components/Icons/NavigationDropdown/DocV1/index.tsx +37 -0
- package/src/components/Icons/NavigationDropdown/Modules/index.tsx +33 -0
- package/src/components/Icons/NavigationDropdown/Resources/index.tsx +37 -0
- package/src/components/Icons/NavigationDropdown/Store/index.tsx +37 -0
- package/src/components/Icons/NavigationDropdown/Ui/index.tsx +37 -0
- package/src/components/Icons/NavigationDropdown/User/index.tsx +37 -0
- package/src/components/Icons/PuzzleColored/index.tsx +35 -0
- package/src/components/Icons/QuestionMark/index.tsx +23 -0
- package/src/components/Icons/Restock/index.tsx +55 -0
- package/src/components/Icons/ScrollText/index.tsx +68 -0
- package/src/components/Icons/ShadedBg/index.tsx +334 -0
- package/src/components/Icons/Shop/index.tsx +68 -0
- package/src/components/Icons/SidebarLeft/index.tsx +42 -0
- package/src/components/Icons/StripeColored/index.tsx +60 -0
- package/src/components/Icons/ThumbDown/index.tsx +23 -0
- package/src/components/Icons/ThumbUp/index.tsx +23 -0
- package/src/components/Icons/WindowPaintbrush/index.tsx +57 -0
- package/src/components/Icons/index.tsx +20 -0
- package/src/components/InlineCode/index.tsx +42 -0
- package/src/components/InlineIcon/index.tsx +21 -0
- package/src/components/InlineThemeImage/index.tsx +14 -0
- package/src/components/Input/Search/index.tsx +64 -0
- package/src/components/Input/Text/index.tsx +39 -0
- package/src/components/Kbd/index.tsx +33 -0
- package/src/components/Label/index.tsx +19 -0
- package/src/components/Link/index.tsx +67 -0
- package/src/components/LinkButton/index.tsx +43 -0
- package/src/components/Loading/Dots/index.tsx +16 -0
- package/src/components/Loading/Spinner/index.tsx +19 -0
- package/src/components/Loading/index.tsx +43 -0
- package/src/components/MDXComponents/index.tsx +209 -0
- package/src/components/MainNav/DesktopMenu/ThemeMenu/index.tsx +76 -0
- package/src/components/MainNav/DesktopMenu/index.tsx +100 -0
- package/src/components/MainNav/Items/Dropdown/index.tsx +88 -0
- package/src/components/MainNav/Items/Link/index.tsx +34 -0
- package/src/components/MainNav/Items/index.tsx +61 -0
- package/src/components/MainNav/MobileMenu/Main/index.tsx +67 -0
- package/src/components/MainNav/MobileMenu/SubMenu/index.tsx +77 -0
- package/src/components/MainNav/MobileMenu/index.tsx +103 -0
- package/src/components/MainNav/Version/index.tsx +33 -0
- package/src/components/MainNav/index.tsx +153 -0
- package/src/components/MarkdownContent/index.tsx +41 -0
- package/src/components/Menu/Action/index.tsx +43 -0
- package/src/components/Menu/Divider/index.tsx +35 -0
- package/src/components/Menu/Dropdown/index.tsx +78 -0
- package/src/components/Menu/Item/index.tsx +36 -0
- package/src/components/Menu/SubMenu/index.tsx +47 -0
- package/src/components/Menu/index.tsx +44 -0
- package/src/components/Modal/Footer/index.tsx +29 -0
- package/src/components/Modal/Header/index.tsx +33 -0
- package/src/components/Modal/index.tsx +124 -0
- package/src/components/Note/Layout/index.tsx +139 -0
- package/src/components/Note/Types/checks.tsx +7 -0
- package/src/components/Note/Types/default.tsx +7 -0
- package/src/components/Note/Types/error.tsx +7 -0
- package/src/components/Note/Types/soon.tsx +7 -0
- package/src/components/Note/Types/sucess.tsx +7 -0
- package/src/components/Note/Types/warning.tsx +7 -0
- package/src/components/Note/index.tsx +32 -0
- package/src/components/Notices/DeprecatedNotice/index.tsx +33 -0
- package/src/components/Notices/ExpandableNotice/index.tsx +36 -0
- package/src/components/Notices/FeatureFlagNotice/index.tsx +36 -0
- package/src/components/Notices/VersionNotice/index.tsx +37 -0
- package/src/components/Notification/Item/Layout/Default/index.tsx +89 -0
- package/src/components/Notification/Item/index.tsx +88 -0
- package/src/components/Notification/index.tsx +65 -0
- package/src/components/Pagination/Card/index.tsx +80 -0
- package/src/components/Pagination/index.tsx +35 -0
- package/src/components/Prerequisites/Item/index.tsx +43 -0
- package/src/components/Prerequisites/index.tsx +94 -0
- package/src/components/RadioItem/index.tsx +38 -0
- package/src/components/Rating/index.tsx +133 -0
- package/src/components/RootProviders/index.tsx +31 -0
- package/src/components/Select/Badge/index.tsx +122 -0
- package/src/components/Select/Dropdown/index.tsx +188 -0
- package/src/components/Select/Input/index.tsx +123 -0
- package/src/components/Select/index.ts +13 -0
- package/src/components/Sidebar/Child/index.tsx +43 -0
- package/src/components/Sidebar/Item/Category/index.tsx +151 -0
- package/src/components/Sidebar/Item/Link/index.tsx +174 -0
- package/src/components/Sidebar/Item/Sidebar/index.tsx +67 -0
- package/src/components/Sidebar/Item/SubCategory/index.tsx +83 -0
- package/src/components/Sidebar/Item/index.tsx +41 -0
- package/src/components/Sidebar/Top/MobileClose/index.tsx +21 -0
- package/src/components/Sidebar/Top/index.tsx +33 -0
- package/src/components/Sidebar/index.tsx +153 -0
- package/src/components/SourceCodeLink/index.tsx +37 -0
- package/src/components/SplitLists/index.tsx +58 -0
- package/src/components/Table/index.tsx +87 -0
- package/src/components/Tabs/index.tsx +106 -0
- package/src/components/TextArea/index.tsx +30 -0
- package/src/components/ThemeImage/index.tsx +26 -0
- package/src/components/Toggle/index.tsx +28 -0
- package/src/components/Tooltip/index.tsx +65 -0
- package/src/components/TypeList/Items/index.tsx +337 -0
- package/src/components/TypeList/index.tsx +63 -0
- package/src/components/WideSection/index.tsx +25 -0
- package/src/components/ZoomImg/index.tsx +17 -0
- package/src/components/index.ts +75 -0
- package/src/constants.tsx +261 -0
- package/src/global-config.ts +11 -0
- package/src/hooks/index.ts +14 -0
- package/src/hooks/use-active-on-scroll/index.tsx +223 -0
- package/src/hooks/use-click-outside/index.tsx +37 -0
- package/src/hooks/use-collapsible/index.tsx +128 -0
- package/src/hooks/use-collapsible-code-lines/index.tsx +149 -0
- package/src/hooks/use-copy/index.tsx +28 -0
- package/src/hooks/use-heading-url/index.tsx +32 -0
- package/src/hooks/use-is-external-link/index.tsx +19 -0
- package/src/hooks/use-keyboard-shortcut/index.tsx +71 -0
- package/src/hooks/use-mutation-observer/index.ts +32 -0
- package/src/hooks/use-page-scroll-manager/index.tsx +82 -0
- package/src/hooks/use-resize-observer/index.ts +20 -0
- package/src/hooks/use-scroll-utils/index.tsx +372 -0
- package/src/hooks/use-select/index.tsx +99 -0
- package/src/hooks/use-tabs/index.tsx +94 -0
- package/src/index.ts +8 -0
- package/src/layouts/barebone.tsx +18 -0
- package/src/layouts/index.ts +4 -0
- package/src/layouts/main-content.tsx +86 -0
- package/src/layouts/root.tsx +43 -0
- package/src/layouts/tight.tsx +29 -0
- package/src/layouts/wide.tsx +25 -0
- package/src/providers/AiAssistant/index.tsx +65 -0
- package/src/providers/BrowserProvider/index.tsx +40 -0
- package/src/providers/ColorMode/index.tsx +73 -0
- package/src/providers/Layout/index.tsx +52 -0
- package/src/providers/MainNav/index.tsx +134 -0
- package/src/providers/Mobile/index.tsx +62 -0
- package/src/providers/Modal/index.tsx +52 -0
- package/src/providers/Notification/index.tsx +149 -0
- package/src/providers/Pagination/index.tsx +230 -0
- package/src/providers/Search/index.tsx +91 -0
- package/src/providers/Sidebar/index.tsx +745 -0
- package/src/providers/SiteConfig/index.tsx +70 -0
- package/src/providers/index.ts +13 -0
- package/src/types/config.ts +34 -0
- package/src/types/frontmatter.ts +23 -0
- package/src/types/general.ts +1 -0
- package/src/types/index.ts +9 -0
- package/src/types/menu.ts +40 -0
- package/src/types/navigation-dropdown.ts +16 -0
- package/src/types/navigation.ts +21 -0
- package/src/types/sidebar.ts +109 -0
- package/src/types/toc.ts +19 -0
- package/src/types/ui.ts +9 -0
- package/src/utils/array-same-elms.ts +10 -0
- package/src/utils/capitalize.ts +3 -0
- package/src/utils/check-sidebar-item-visibility.ts +47 -0
- package/src/utils/decode-str.ts +8 -0
- package/src/utils/dom-utils.ts +29 -0
- package/src/utils/event-parser.ts +54 -0
- package/src/utils/get-link-with-base-path.ts +3 -0
- package/src/utils/get-navbar-items.ts +55 -0
- package/src/utils/get-scrolled-top.ts +8 -0
- package/src/utils/index.ts +13 -0
- package/src/utils/is-elm-window.ts +3 -0
- package/src/utils/is-in-view.ts +10 -0
- package/src/utils/os-browser-utils.ts +39 -0
- package/src/utils/set-obj-value.ts +38 -0
- package/src/utils/sidebar-utils.ts +129 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
|
|
2
|
+
/* Copied from Docusaurus to maintain scroll position on re-renders. Useful when content of the page is updated dynamically */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import React, {
|
|
12
|
+
useCallback,
|
|
13
|
+
useContext,
|
|
14
|
+
useEffect,
|
|
15
|
+
useLayoutEffect,
|
|
16
|
+
useMemo,
|
|
17
|
+
useRef,
|
|
18
|
+
type ReactNode,
|
|
19
|
+
useState,
|
|
20
|
+
} from "react"
|
|
21
|
+
import { getScrolledTop as getScrolledTopUtil, isElmWindow } from "../../utils"
|
|
22
|
+
import { useKeyboardShortcut } from "../use-keyboard-shortcut"
|
|
23
|
+
import { useLayout } from "../../providers/Layout"
|
|
24
|
+
|
|
25
|
+
type EventFunc = (...args: never[]) => unknown
|
|
26
|
+
|
|
27
|
+
export function useEvent<T extends EventFunc>(callback: T): T {
|
|
28
|
+
const ref = useRef<T>(callback)
|
|
29
|
+
|
|
30
|
+
useLayoutEffect(() => {
|
|
31
|
+
ref.current = callback
|
|
32
|
+
}, [callback])
|
|
33
|
+
|
|
34
|
+
// @ts-expect-error: TS is right that this callback may be a supertype of T,
|
|
35
|
+
// but good enough for our use
|
|
36
|
+
return useCallback<T>((...args) => ref.current(...args), [])
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Gets `value` from the last render.
|
|
41
|
+
*/
|
|
42
|
+
export function usePrevious<T>(value: T): T | undefined {
|
|
43
|
+
const ref = useRef<T>(undefined)
|
|
44
|
+
|
|
45
|
+
useLayoutEffect(() => {
|
|
46
|
+
ref.current = value
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
return ref.current
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ScrollController = {
|
|
53
|
+
/** A boolean ref tracking whether scroll events are enabled. */
|
|
54
|
+
scrollEventsEnabledRef: React.MutableRefObject<boolean>
|
|
55
|
+
/** Enable scroll events in `useScrollPosition`. */
|
|
56
|
+
enableScrollEvents: () => void
|
|
57
|
+
/** Disable scroll events in `useScrollPosition`. */
|
|
58
|
+
disableScrollEvents: () => void
|
|
59
|
+
/** Retrieves the scrollable element. By default, it's window. */
|
|
60
|
+
scrollableElement: Element | Window | undefined
|
|
61
|
+
/** Retrieves the scroll top if the scrollable element */
|
|
62
|
+
getScrolledTop: () => number
|
|
63
|
+
/** Scrolls to an element */
|
|
64
|
+
scrollToElement: (elm: HTMLElement) => void
|
|
65
|
+
/** Scrolls to a top value */
|
|
66
|
+
scrollToTop: (top: number, parentTop?: number) => void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function useScrollControllerContextValue({
|
|
70
|
+
scrollableSelector,
|
|
71
|
+
}: {
|
|
72
|
+
scrollableSelector: string
|
|
73
|
+
restoreScrollOnReload?: boolean
|
|
74
|
+
}): ScrollController {
|
|
75
|
+
const scrollEventsEnabledRef = useRef(true)
|
|
76
|
+
const { showCollapsedNavbar } = useLayout()
|
|
77
|
+
|
|
78
|
+
const [scrollableElement, setScrollableElement] = useState<
|
|
79
|
+
Element | Window | undefined
|
|
80
|
+
>()
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
setScrollableElement(
|
|
84
|
+
(document.querySelector(scrollableSelector) as Element) || window
|
|
85
|
+
)
|
|
86
|
+
}, [])
|
|
87
|
+
|
|
88
|
+
const getScrolledTop = () => {
|
|
89
|
+
return scrollableElement ? getScrolledTopUtil(scrollableElement) : 0
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const scrollToElement = (elm: HTMLElement) => {
|
|
93
|
+
scrollToTop(elm.offsetTop)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const topMargin = useMemo(() => {
|
|
97
|
+
// might need a better way to set these static values
|
|
98
|
+
return showCollapsedNavbar ? 112 : 56
|
|
99
|
+
}, [showCollapsedNavbar])
|
|
100
|
+
|
|
101
|
+
const scrollToTop = (top: number, parentTop?: number) => {
|
|
102
|
+
const parentOffsetTop =
|
|
103
|
+
parentTop !== undefined
|
|
104
|
+
? parentTop
|
|
105
|
+
: isElmWindow(scrollableElement)
|
|
106
|
+
? 0
|
|
107
|
+
: scrollableElement instanceof HTMLElement
|
|
108
|
+
? scrollableElement.offsetTop
|
|
109
|
+
: 0
|
|
110
|
+
|
|
111
|
+
scrollableElement?.scrollTo({
|
|
112
|
+
top: top - parentOffsetTop - topMargin,
|
|
113
|
+
behavior: "instant",
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return useMemo(
|
|
118
|
+
() => ({
|
|
119
|
+
scrollEventsEnabledRef,
|
|
120
|
+
enableScrollEvents: () => {
|
|
121
|
+
scrollEventsEnabledRef.current = true
|
|
122
|
+
},
|
|
123
|
+
disableScrollEvents: () => {
|
|
124
|
+
scrollEventsEnabledRef.current = false
|
|
125
|
+
},
|
|
126
|
+
scrollableElement,
|
|
127
|
+
getScrolledTop,
|
|
128
|
+
scrollToElement,
|
|
129
|
+
scrollToTop,
|
|
130
|
+
}),
|
|
131
|
+
[scrollableElement]
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const ScrollMonitorContext = React.createContext<ScrollController | undefined>(
|
|
136
|
+
undefined
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
export function ScrollControllerProvider({
|
|
140
|
+
children,
|
|
141
|
+
scrollableSelector = "",
|
|
142
|
+
}: {
|
|
143
|
+
children: ReactNode
|
|
144
|
+
scrollableSelector?: string
|
|
145
|
+
restoreScrollOnReload?: boolean
|
|
146
|
+
}) {
|
|
147
|
+
const value = useScrollControllerContextValue({
|
|
148
|
+
scrollableSelector,
|
|
149
|
+
})
|
|
150
|
+
useKeyboardShortcut({
|
|
151
|
+
metakey: false,
|
|
152
|
+
shortcutKeys: ["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End"],
|
|
153
|
+
action: (e) => {
|
|
154
|
+
// check that document or body are focused
|
|
155
|
+
const activeElement = document.activeElement
|
|
156
|
+
if (
|
|
157
|
+
isElmWindow(value.scrollableElement) ||
|
|
158
|
+
!value.scrollableElement ||
|
|
159
|
+
(activeElement !== document.body &&
|
|
160
|
+
activeElement !== document.documentElement)
|
|
161
|
+
) {
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let newScroll = value.scrollableElement.scrollTop
|
|
166
|
+
const scrollThreshold = 50
|
|
167
|
+
const pageScrollAmount =
|
|
168
|
+
value.scrollableElement.clientHeight - scrollThreshold
|
|
169
|
+
|
|
170
|
+
switch (e.key) {
|
|
171
|
+
case "ArrowUp":
|
|
172
|
+
newScroll = -scrollThreshold
|
|
173
|
+
break
|
|
174
|
+
case "ArrowDown":
|
|
175
|
+
newScroll = scrollThreshold
|
|
176
|
+
break
|
|
177
|
+
case "PageUp":
|
|
178
|
+
newScroll = -pageScrollAmount
|
|
179
|
+
break
|
|
180
|
+
case "PageDown":
|
|
181
|
+
newScroll = pageScrollAmount
|
|
182
|
+
break
|
|
183
|
+
case "Home":
|
|
184
|
+
newScroll = -newScroll
|
|
185
|
+
break
|
|
186
|
+
case "End":
|
|
187
|
+
newScroll = value.scrollableElement.scrollHeight
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
value.scrollableElement?.scrollBy({
|
|
191
|
+
top: newScroll,
|
|
192
|
+
behavior: "smooth",
|
|
193
|
+
})
|
|
194
|
+
},
|
|
195
|
+
})
|
|
196
|
+
return (
|
|
197
|
+
<ScrollMonitorContext.Provider value={value}>
|
|
198
|
+
{children}
|
|
199
|
+
</ScrollMonitorContext.Provider>
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* We need a way to update the scroll position while ignoring scroll events
|
|
205
|
+
* so as not to toggle Navbar/BackToTop visibility.
|
|
206
|
+
*
|
|
207
|
+
* This API permits to temporarily disable/ignore scroll events. Motivated by
|
|
208
|
+
* https://github.com/facebook/docusaurus/pull/5618
|
|
209
|
+
*/
|
|
210
|
+
export function useScrollController(): ScrollController {
|
|
211
|
+
const context = useContext(ScrollMonitorContext)
|
|
212
|
+
if (context == null) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`useScrollController must be used by elements in ScrollControllerProvider`
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
return context
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
type ScrollPosition = { scrollX: number; scrollY: number }
|
|
221
|
+
|
|
222
|
+
const getScrollPosition = (): ScrollPosition | null => ({
|
|
223
|
+
scrollX: window.pageXOffset,
|
|
224
|
+
scrollY: window.pageYOffset,
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* This hook fires an effect when the scroll position changes. The effect will
|
|
229
|
+
* be provided with the before/after scroll positions. Note that the effect may
|
|
230
|
+
* not be always run: if scrolling is disabled through `useScrollController`, it
|
|
231
|
+
* will be a no-op.
|
|
232
|
+
*
|
|
233
|
+
* @see {@link useScrollController}
|
|
234
|
+
*/
|
|
235
|
+
export function useScrollPosition(
|
|
236
|
+
effect: (
|
|
237
|
+
position: ScrollPosition,
|
|
238
|
+
lastPosition: ScrollPosition | null
|
|
239
|
+
) => void,
|
|
240
|
+
deps: unknown[] = []
|
|
241
|
+
): void {
|
|
242
|
+
const { scrollEventsEnabledRef } = useScrollController()
|
|
243
|
+
const lastPositionRef = useRef<ScrollPosition | null>(getScrollPosition())
|
|
244
|
+
|
|
245
|
+
const dynamicEffect = useEvent(effect)
|
|
246
|
+
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
const handleScroll = () => {
|
|
249
|
+
if (!scrollEventsEnabledRef.current) {
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
const currentPosition = getScrollPosition()!
|
|
253
|
+
dynamicEffect(currentPosition, lastPositionRef.current)
|
|
254
|
+
lastPositionRef.current = currentPosition
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const opts: AddEventListenerOptions & EventListenerOptions = {
|
|
258
|
+
passive: true,
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
handleScroll()
|
|
262
|
+
window.addEventListener("scroll", handleScroll, opts)
|
|
263
|
+
|
|
264
|
+
return () => window.removeEventListener("scroll", handleScroll, opts)
|
|
265
|
+
}, [dynamicEffect, scrollEventsEnabledRef, ...deps])
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
type UseScrollPositionSaver = {
|
|
269
|
+
/** Measure the top of an element, and store the details. */
|
|
270
|
+
save: (elem: HTMLElement) => void
|
|
271
|
+
/**
|
|
272
|
+
* Restore the page position to keep the stored element's position from
|
|
273
|
+
* the top of the viewport, and remove the stored details.
|
|
274
|
+
*/
|
|
275
|
+
restore: () => { restored: boolean }
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function useScrollPositionSaver(): UseScrollPositionSaver {
|
|
279
|
+
const { scrollableElement } = useScrollController()
|
|
280
|
+
const lastElementRef = useRef<{ elem: HTMLElement | null; top: number }>({
|
|
281
|
+
elem: null,
|
|
282
|
+
top: 0,
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
const save = useCallback((elem: HTMLElement) => {
|
|
286
|
+
lastElementRef.current = {
|
|
287
|
+
elem,
|
|
288
|
+
top: elem.getBoundingClientRect().top,
|
|
289
|
+
}
|
|
290
|
+
}, [])
|
|
291
|
+
|
|
292
|
+
const restore = useCallback(() => {
|
|
293
|
+
const {
|
|
294
|
+
current: { elem, top },
|
|
295
|
+
} = lastElementRef
|
|
296
|
+
if (!elem) {
|
|
297
|
+
return { restored: false }
|
|
298
|
+
}
|
|
299
|
+
const newTop = elem.getBoundingClientRect().top
|
|
300
|
+
const heightDiff = newTop - top
|
|
301
|
+
if (heightDiff) {
|
|
302
|
+
scrollableElement?.scrollBy({ left: 0, top: heightDiff })
|
|
303
|
+
}
|
|
304
|
+
lastElementRef.current = { elem: null, top: 0 }
|
|
305
|
+
|
|
306
|
+
return { restored: heightDiff !== 0 }
|
|
307
|
+
}, [])
|
|
308
|
+
|
|
309
|
+
return useMemo(() => ({ save, restore }), [restore, save])
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* This hook permits to "block" the scroll position of a DOM element.
|
|
314
|
+
* The idea is that we should be able to update DOM content above this element
|
|
315
|
+
* but the screen position of this element should not change.
|
|
316
|
+
*
|
|
317
|
+
* Feature motivated by the Tabs groups: clicking on a tab may affect tabs of
|
|
318
|
+
* the same group upper in the tree, yet to avoid a bad UX, the clicked tab must
|
|
319
|
+
* remain under the user mouse.
|
|
320
|
+
*
|
|
321
|
+
* @see https://github.com/facebook/docusaurus/pull/5618
|
|
322
|
+
*/
|
|
323
|
+
export function useScrollPositionBlocker(): {
|
|
324
|
+
/**
|
|
325
|
+
* Takes an element, and keeps its screen position no matter what's getting
|
|
326
|
+
* rendered above it, until the next render.
|
|
327
|
+
*/
|
|
328
|
+
blockElementScrollPositionUntilNextRender: (el: HTMLElement) => void
|
|
329
|
+
} {
|
|
330
|
+
const scrollController = useScrollController()
|
|
331
|
+
const scrollPositionSaver = useScrollPositionSaver()
|
|
332
|
+
|
|
333
|
+
const nextLayoutEffectCallbackRef = useRef<(() => void) | undefined>(
|
|
334
|
+
undefined
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
const blockElementScrollPositionUntilNextRender = useCallback(
|
|
338
|
+
(el: HTMLElement) => {
|
|
339
|
+
scrollPositionSaver.save(el)
|
|
340
|
+
scrollController.disableScrollEvents()
|
|
341
|
+
nextLayoutEffectCallbackRef.current = () => {
|
|
342
|
+
const { restored } = scrollPositionSaver.restore()
|
|
343
|
+
nextLayoutEffectCallbackRef.current = undefined
|
|
344
|
+
|
|
345
|
+
// Restoring the former scroll position will trigger a scroll event. We
|
|
346
|
+
// need to wait for next scroll event to happen before enabling the
|
|
347
|
+
// scrollController events again.
|
|
348
|
+
if (restored) {
|
|
349
|
+
const handleScrollRestoreEvent = () => {
|
|
350
|
+
scrollController.enableScrollEvents()
|
|
351
|
+
window.removeEventListener("scroll", handleScrollRestoreEvent)
|
|
352
|
+
}
|
|
353
|
+
window.addEventListener("scroll", handleScrollRestoreEvent)
|
|
354
|
+
} else {
|
|
355
|
+
scrollController.enableScrollEvents()
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
[scrollController, scrollPositionSaver]
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
useLayoutEffect(() => {
|
|
363
|
+
// Queuing permits to restore scroll position after all useLayoutEffect
|
|
364
|
+
// have run, and yet preserve the sync nature of the scroll restoration
|
|
365
|
+
// See https://github.com/facebook/docusaurus/issues/8625
|
|
366
|
+
queueMicrotask(() => nextLayoutEffectCallbackRef.current?.())
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
blockElementScrollPositionUntilNextRender,
|
|
371
|
+
}
|
|
372
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react"
|
|
2
|
+
|
|
3
|
+
export type OptionType = {
|
|
4
|
+
value: string
|
|
5
|
+
label: string
|
|
6
|
+
index?: string
|
|
7
|
+
isAllOption?: boolean
|
|
8
|
+
hitsPerPage?: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type SelectOptions = {
|
|
12
|
+
value: string | string[]
|
|
13
|
+
multiple?: boolean
|
|
14
|
+
options: OptionType[]
|
|
15
|
+
setSelected?: (value: string | string[]) => void
|
|
16
|
+
addSelected?: (value: string) => void
|
|
17
|
+
removeSelected?: (value: string) => void
|
|
18
|
+
handleAddAll?: (isAllSelected: boolean) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const useSelect = ({
|
|
22
|
+
value,
|
|
23
|
+
options,
|
|
24
|
+
multiple = false,
|
|
25
|
+
setSelected,
|
|
26
|
+
addSelected,
|
|
27
|
+
removeSelected,
|
|
28
|
+
handleAddAll,
|
|
29
|
+
}: SelectOptions) => {
|
|
30
|
+
const isValueSelected = useCallback(
|
|
31
|
+
(val: string) => {
|
|
32
|
+
return (
|
|
33
|
+
(typeof value === "string" && val === value) ||
|
|
34
|
+
(Array.isArray(value) && value.includes(val))
|
|
35
|
+
)
|
|
36
|
+
},
|
|
37
|
+
[value]
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
// checks if there are multiple selected values
|
|
41
|
+
const hasSelectedValues = useMemo(() => {
|
|
42
|
+
return multiple && Array.isArray(value) && value.length > 0
|
|
43
|
+
}, [value, multiple])
|
|
44
|
+
|
|
45
|
+
// checks if there are any selected values,
|
|
46
|
+
// whether multiple or one
|
|
47
|
+
const hasSelectedValue = useMemo(() => {
|
|
48
|
+
return hasSelectedValues || (typeof value === "string" && value.length)
|
|
49
|
+
}, [hasSelectedValues, value])
|
|
50
|
+
|
|
51
|
+
const selectedValues: OptionType[] = useMemo(() => {
|
|
52
|
+
if (typeof value === "string") {
|
|
53
|
+
const selectedValue = options.find((option) => option.value === value)
|
|
54
|
+
return selectedValue ? [selectedValue] : []
|
|
55
|
+
} else if (Array.isArray(value)) {
|
|
56
|
+
return options.filter((option) => value.includes(option.value))
|
|
57
|
+
}
|
|
58
|
+
return []
|
|
59
|
+
}, [options, value])
|
|
60
|
+
|
|
61
|
+
const isAllSelected = useMemo(() => {
|
|
62
|
+
return Array.isArray(value) && value.length === options.length
|
|
63
|
+
}, [options, value])
|
|
64
|
+
|
|
65
|
+
const handleChange = (selectedValue: string, wasSelected: boolean) => {
|
|
66
|
+
if (multiple) {
|
|
67
|
+
if (wasSelected) {
|
|
68
|
+
removeSelected?.(selectedValue)
|
|
69
|
+
} else {
|
|
70
|
+
addSelected?.(selectedValue)
|
|
71
|
+
}
|
|
72
|
+
} else {
|
|
73
|
+
setSelected?.(selectedValue)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const handleSelectAll = () => {
|
|
78
|
+
if (handleAddAll) {
|
|
79
|
+
handleAddAll(isAllSelected)
|
|
80
|
+
} else {
|
|
81
|
+
setSelected?.(options.map((option) => option.value))
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const setSelectedValues = (values: string[]) => {
|
|
86
|
+
setSelected?.(values)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
isValueSelected,
|
|
91
|
+
hasSelectedValue,
|
|
92
|
+
hasSelectedValues,
|
|
93
|
+
selectedValues,
|
|
94
|
+
isAllSelected,
|
|
95
|
+
handleChange,
|
|
96
|
+
handleSelectAll,
|
|
97
|
+
setSelectedValues,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useLayoutEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react"
|
|
10
|
+
|
|
11
|
+
export type BaseTabType = {
|
|
12
|
+
label: string
|
|
13
|
+
value: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type EventData = {
|
|
17
|
+
storageValue: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type TabProps<T> = {
|
|
21
|
+
tabs: T[]
|
|
22
|
+
group?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useTabs<T extends BaseTabType>({ tabs, group }: TabProps<T>) {
|
|
26
|
+
const [selectedTab, setSelectedTab] = useState<T | null>(null)
|
|
27
|
+
const storageKey = useMemo(() => `tab_${group}`, [group])
|
|
28
|
+
const eventKey = useMemo(() => `tab_${group}_changed`, [group])
|
|
29
|
+
const scrollPosition = useRef<number>(0)
|
|
30
|
+
|
|
31
|
+
const changeSelectedTab = (tab: T) => {
|
|
32
|
+
if (tab.value === selectedTab?.value) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
scrollPosition.current = window.scrollY
|
|
36
|
+
setSelectedTab(tab)
|
|
37
|
+
localStorage.setItem(storageKey, tab.value)
|
|
38
|
+
window.dispatchEvent(
|
|
39
|
+
new CustomEvent<EventData>(eventKey, {
|
|
40
|
+
detail: {
|
|
41
|
+
storageValue: tab.value,
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const findTabItem = useCallback(
|
|
48
|
+
(val: string) => {
|
|
49
|
+
const lowerVal = val.toLowerCase()
|
|
50
|
+
return tabs.find((t) => t.value.toLowerCase() === lowerVal)
|
|
51
|
+
},
|
|
52
|
+
[tabs]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
const handleStorageChange = useCallback(
|
|
56
|
+
(e: CustomEvent<EventData>) => {
|
|
57
|
+
if (e.detail.storageValue !== selectedTab?.value) {
|
|
58
|
+
// check if tab exists
|
|
59
|
+
const tab = findTabItem(e.detail.storageValue)
|
|
60
|
+
if (tab) {
|
|
61
|
+
setSelectedTab(tab)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
[selectedTab, findTabItem]
|
|
66
|
+
) as EventListener
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (!selectedTab) {
|
|
70
|
+
const storedSelectedTabValue = localStorage.getItem(storageKey)
|
|
71
|
+
setSelectedTab(
|
|
72
|
+
storedSelectedTabValue
|
|
73
|
+
? findTabItem(storedSelectedTabValue) || tabs[0]
|
|
74
|
+
: tabs[0]
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
}, [selectedTab, storageKey, tabs, findTabItem])
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
window.addEventListener(eventKey, handleStorageChange)
|
|
81
|
+
|
|
82
|
+
return () => {
|
|
83
|
+
window.removeEventListener(eventKey, handleStorageChange)
|
|
84
|
+
}
|
|
85
|
+
}, [handleStorageChange, eventKey])
|
|
86
|
+
|
|
87
|
+
useLayoutEffect(() => {
|
|
88
|
+
if (scrollPosition.current && window.scrollY !== scrollPosition.current) {
|
|
89
|
+
window.scrollTo(0, scrollPosition.current)
|
|
90
|
+
}
|
|
91
|
+
}, [selectedTab])
|
|
92
|
+
|
|
93
|
+
return { selectedTab, changeSelectedTab }
|
|
94
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import clsx from "clsx"
|
|
2
|
+
import React from "react"
|
|
3
|
+
|
|
4
|
+
export type BareboneLayoutProps = {
|
|
5
|
+
htmlClassName?: string
|
|
6
|
+
children: React.ReactNode
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const BareboneLayout = ({
|
|
10
|
+
htmlClassName,
|
|
11
|
+
children,
|
|
12
|
+
}: BareboneLayoutProps) => {
|
|
13
|
+
return (
|
|
14
|
+
<div className={clsx("h-full w-full", htmlClassName)}>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { useEffect } from "react"
|
|
3
|
+
import clsx from "clsx"
|
|
4
|
+
import {
|
|
5
|
+
MainNav,
|
|
6
|
+
useAiAssistant,
|
|
7
|
+
useIsBrowser,
|
|
8
|
+
useLayout,
|
|
9
|
+
useSidebar,
|
|
10
|
+
useSiteConfig,
|
|
11
|
+
} from ".."
|
|
12
|
+
import { ContentMenu } from "../components/ContentMenu"
|
|
13
|
+
|
|
14
|
+
export type MainContentLayoutProps = {
|
|
15
|
+
mainWrapperClasses?: string
|
|
16
|
+
contentClassName?: string
|
|
17
|
+
children: React.ReactNode
|
|
18
|
+
showContentMenu?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const MainContentLayout = ({
|
|
22
|
+
children,
|
|
23
|
+
mainWrapperClasses,
|
|
24
|
+
contentClassName,
|
|
25
|
+
showContentMenu = true,
|
|
26
|
+
}: MainContentLayoutProps) => {
|
|
27
|
+
const { isBrowser } = useIsBrowser()
|
|
28
|
+
const { desktopSidebarOpen } = useSidebar()
|
|
29
|
+
const { mainContentRef, showCollapsedNavbar } = useLayout()
|
|
30
|
+
const { frontmatter } = useSiteConfig()
|
|
31
|
+
const { chatOpened } = useAiAssistant()
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!isBrowser) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
const rootLayout = document.getElementById("root-layout")
|
|
38
|
+
if (desktopSidebarOpen) {
|
|
39
|
+
rootLayout?.classList.add("lg:grid-cols-[221px_1fr]")
|
|
40
|
+
} else {
|
|
41
|
+
rootLayout?.classList.remove("lg:grid-cols-[221px_1fr]")
|
|
42
|
+
}
|
|
43
|
+
}, [desktopSidebarOpen, isBrowser])
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className={clsx(
|
|
48
|
+
"relative max-w-full",
|
|
49
|
+
"h-full flex-1",
|
|
50
|
+
"flex flex-col",
|
|
51
|
+
"gap-docs_0.5 lg:py-docs_0.25 lg:mr-docs_0.25 scroll-m-docs_0.25",
|
|
52
|
+
!desktopSidebarOpen && "lg:ml-docs_0.25",
|
|
53
|
+
mainWrapperClasses
|
|
54
|
+
)}
|
|
55
|
+
>
|
|
56
|
+
<div
|
|
57
|
+
className={clsx(
|
|
58
|
+
"bg-acmekit-bg-base",
|
|
59
|
+
"flex-col items-center",
|
|
60
|
+
"h-full w-full",
|
|
61
|
+
"overflow-y-scroll overflow-x-hidden",
|
|
62
|
+
"md:rounded-docs_DEFAULT",
|
|
63
|
+
"shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
|
|
64
|
+
mainWrapperClasses
|
|
65
|
+
)}
|
|
66
|
+
id="main"
|
|
67
|
+
ref={mainContentRef as React.RefObject<HTMLDivElement>}
|
|
68
|
+
>
|
|
69
|
+
<MainNav />
|
|
70
|
+
<div
|
|
71
|
+
className={clsx(
|
|
72
|
+
"pt-docs_4 lg:pt-docs_6 pb-docs_8 lg:pb-docs_4",
|
|
73
|
+
showContentMenu && "grid grid-cols-1 lg:mx-auto",
|
|
74
|
+
desktopSidebarOpen && "lg:grid-cols-[1fr_221px]",
|
|
75
|
+
chatOpened && showCollapsedNavbar && "pl-docs_1",
|
|
76
|
+
contentClassName
|
|
77
|
+
)}
|
|
78
|
+
id="content"
|
|
79
|
+
>
|
|
80
|
+
<div className="flex justify-center">{children}</div>
|
|
81
|
+
</div>
|
|
82
|
+
{showContentMenu && !frontmatter.hide_content_menu && <ContentMenu />}
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
)
|
|
86
|
+
}
|