@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.
Files changed (236) hide show
  1. package/dist/Items-YPPZD6C6.mjs +312 -0
  2. package/dist/chunk-JD7BP7O5.mjs +13144 -0
  3. package/dist/index.d.mts +1550 -0
  4. package/dist/index.d.ts +1550 -0
  5. package/dist/index.js +15218 -0
  6. package/dist/index.mjs +366 -0
  7. package/package.json +58 -0
  8. package/src/components/Badge/index.tsx +74 -0
  9. package/src/components/BadgesList/index.tsx +18 -0
  10. package/src/components/BetaBadge/index.tsx +24 -0
  11. package/src/components/Bordered/index.tsx +21 -0
  12. package/src/components/BorderedIcon/index.tsx +60 -0
  13. package/src/components/Breadcrumbs/index.tsx +83 -0
  14. package/src/components/Button/index.tsx +100 -0
  15. package/src/components/Card/Layout/Default/index.tsx +124 -0
  16. package/src/components/Card/Layout/Filler/index.tsx +30 -0
  17. package/src/components/Card/Layout/Large/index.tsx +88 -0
  18. package/src/components/Card/Layout/Mini/index.tsx +142 -0
  19. package/src/components/Card/index.tsx +50 -0
  20. package/src/components/CardList/index.tsx +40 -0
  21. package/src/components/ChildDocs/index.tsx +9 -0
  22. package/src/components/CodeBlock/Actions/AskAi/index.tsx +10 -0
  23. package/src/components/CodeBlock/Actions/Copy/index.tsx +59 -0
  24. package/src/components/CodeBlock/Actions/index.tsx +137 -0
  25. package/src/components/CodeBlock/Collapsible/Button/index.tsx +58 -0
  26. package/src/components/CodeBlock/Collapsible/Fade/index.tsx +55 -0
  27. package/src/components/CodeBlock/Collapsible/Lines/index.tsx +22 -0
  28. package/src/components/CodeBlock/Header/Wrapper/index.tsx +46 -0
  29. package/src/components/CodeBlock/Header/index.tsx +67 -0
  30. package/src/components/CodeBlock/Inline/index.tsx +20 -0
  31. package/src/components/CodeBlock/Line/index.tsx +331 -0
  32. package/src/components/CodeBlock/index.tsx +510 -0
  33. package/src/components/CodeMdx/index.tsx +45 -0
  34. package/src/components/CodeTabs/Item/index.tsx +67 -0
  35. package/src/components/CodeTabs/index.tsx +319 -0
  36. package/src/components/ContentMenu/Actions/index.tsx +7 -0
  37. package/src/components/ContentMenu/Products/index.tsx +64 -0
  38. package/src/components/ContentMenu/Toc/index.tsx +148 -0
  39. package/src/components/ContentMenu/Version/index.tsx +77 -0
  40. package/src/components/ContentMenu/index.tsx +31 -0
  41. package/src/components/CopyButton/index.tsx +76 -0
  42. package/src/components/Details/Summary/index.tsx +75 -0
  43. package/src/components/Details/index.tsx +98 -0
  44. package/src/components/DetailsList/index.tsx +32 -0
  45. package/src/components/DottedSeparator/index.tsx +30 -0
  46. package/src/components/EditButton/index.tsx +32 -0
  47. package/src/components/EditDate/index.tsx +33 -0
  48. package/src/components/ErrorPage/Icon/index.tsx +428 -0
  49. package/src/components/ErrorPage/index.tsx +32 -0
  50. package/src/components/Feedback/Solutions/index.tsx +105 -0
  51. package/src/components/Feedback/index.tsx +304 -0
  52. package/src/components/Footer/index.tsx +23 -0
  53. package/src/components/Heading/H1/index.tsx +21 -0
  54. package/src/components/Heading/H2/index.tsx +47 -0
  55. package/src/components/Heading/H3/index.tsx +42 -0
  56. package/src/components/Heading/H4/index.tsx +14 -0
  57. package/src/components/Heading/index.tsx +4 -0
  58. package/src/components/IconHeadline/index.tsx +15 -0
  59. package/src/components/Icons/AiAssistant/index.tsx +462 -0
  60. package/src/components/Icons/ArrowRightDown/index.tsx +30 -0
  61. package/src/components/Icons/BundledProduct/index.tsx +72 -0
  62. package/src/components/Icons/CalendarRefresh/index.tsx +70 -0
  63. package/src/components/Icons/ChefHat/index.tsx +65 -0
  64. package/src/components/Icons/CircleDottedLine/index.tsx +60 -0
  65. package/src/components/Icons/CloudSolid/index.tsx +47 -0
  66. package/src/components/Icons/ColoredAcmeKit/index.tsx +13 -0
  67. package/src/components/Icons/DecisionProcess/index.tsx +58 -0
  68. package/src/components/Icons/Erp/index.tsx +92 -0
  69. package/src/components/Icons/Github/index.tsx +22 -0
  70. package/src/components/Icons/House/index.tsx +23 -0
  71. package/src/components/Icons/ImageBinary/index.tsx +69 -0
  72. package/src/components/Icons/Kapa/index.tsx +22 -0
  73. package/src/components/Icons/Markdown/index.tsx +25 -0
  74. package/src/components/Icons/NavigationDropdown/Admin/index.tsx +33 -0
  75. package/src/components/Icons/NavigationDropdown/Doc/index.tsx +41 -0
  76. package/src/components/Icons/NavigationDropdown/DocV1/index.tsx +37 -0
  77. package/src/components/Icons/NavigationDropdown/Modules/index.tsx +33 -0
  78. package/src/components/Icons/NavigationDropdown/Resources/index.tsx +37 -0
  79. package/src/components/Icons/NavigationDropdown/Store/index.tsx +37 -0
  80. package/src/components/Icons/NavigationDropdown/Ui/index.tsx +37 -0
  81. package/src/components/Icons/NavigationDropdown/User/index.tsx +37 -0
  82. package/src/components/Icons/PuzzleColored/index.tsx +35 -0
  83. package/src/components/Icons/QuestionMark/index.tsx +23 -0
  84. package/src/components/Icons/Restock/index.tsx +55 -0
  85. package/src/components/Icons/ScrollText/index.tsx +68 -0
  86. package/src/components/Icons/ShadedBg/index.tsx +334 -0
  87. package/src/components/Icons/Shop/index.tsx +68 -0
  88. package/src/components/Icons/SidebarLeft/index.tsx +42 -0
  89. package/src/components/Icons/StripeColored/index.tsx +60 -0
  90. package/src/components/Icons/ThumbDown/index.tsx +23 -0
  91. package/src/components/Icons/ThumbUp/index.tsx +23 -0
  92. package/src/components/Icons/WindowPaintbrush/index.tsx +57 -0
  93. package/src/components/Icons/index.tsx +20 -0
  94. package/src/components/InlineCode/index.tsx +42 -0
  95. package/src/components/InlineIcon/index.tsx +21 -0
  96. package/src/components/InlineThemeImage/index.tsx +14 -0
  97. package/src/components/Input/Search/index.tsx +64 -0
  98. package/src/components/Input/Text/index.tsx +39 -0
  99. package/src/components/Kbd/index.tsx +33 -0
  100. package/src/components/Label/index.tsx +19 -0
  101. package/src/components/Link/index.tsx +67 -0
  102. package/src/components/LinkButton/index.tsx +43 -0
  103. package/src/components/Loading/Dots/index.tsx +16 -0
  104. package/src/components/Loading/Spinner/index.tsx +19 -0
  105. package/src/components/Loading/index.tsx +43 -0
  106. package/src/components/MDXComponents/index.tsx +209 -0
  107. package/src/components/MainNav/DesktopMenu/ThemeMenu/index.tsx +76 -0
  108. package/src/components/MainNav/DesktopMenu/index.tsx +100 -0
  109. package/src/components/MainNav/Items/Dropdown/index.tsx +88 -0
  110. package/src/components/MainNav/Items/Link/index.tsx +34 -0
  111. package/src/components/MainNav/Items/index.tsx +61 -0
  112. package/src/components/MainNav/MobileMenu/Main/index.tsx +67 -0
  113. package/src/components/MainNav/MobileMenu/SubMenu/index.tsx +77 -0
  114. package/src/components/MainNav/MobileMenu/index.tsx +103 -0
  115. package/src/components/MainNav/Version/index.tsx +33 -0
  116. package/src/components/MainNav/index.tsx +153 -0
  117. package/src/components/MarkdownContent/index.tsx +41 -0
  118. package/src/components/Menu/Action/index.tsx +43 -0
  119. package/src/components/Menu/Divider/index.tsx +35 -0
  120. package/src/components/Menu/Dropdown/index.tsx +78 -0
  121. package/src/components/Menu/Item/index.tsx +36 -0
  122. package/src/components/Menu/SubMenu/index.tsx +47 -0
  123. package/src/components/Menu/index.tsx +44 -0
  124. package/src/components/Modal/Footer/index.tsx +29 -0
  125. package/src/components/Modal/Header/index.tsx +33 -0
  126. package/src/components/Modal/index.tsx +124 -0
  127. package/src/components/Note/Layout/index.tsx +139 -0
  128. package/src/components/Note/Types/checks.tsx +7 -0
  129. package/src/components/Note/Types/default.tsx +7 -0
  130. package/src/components/Note/Types/error.tsx +7 -0
  131. package/src/components/Note/Types/soon.tsx +7 -0
  132. package/src/components/Note/Types/sucess.tsx +7 -0
  133. package/src/components/Note/Types/warning.tsx +7 -0
  134. package/src/components/Note/index.tsx +32 -0
  135. package/src/components/Notices/DeprecatedNotice/index.tsx +33 -0
  136. package/src/components/Notices/ExpandableNotice/index.tsx +36 -0
  137. package/src/components/Notices/FeatureFlagNotice/index.tsx +36 -0
  138. package/src/components/Notices/VersionNotice/index.tsx +37 -0
  139. package/src/components/Notification/Item/Layout/Default/index.tsx +89 -0
  140. package/src/components/Notification/Item/index.tsx +88 -0
  141. package/src/components/Notification/index.tsx +65 -0
  142. package/src/components/Pagination/Card/index.tsx +80 -0
  143. package/src/components/Pagination/index.tsx +35 -0
  144. package/src/components/Prerequisites/Item/index.tsx +43 -0
  145. package/src/components/Prerequisites/index.tsx +94 -0
  146. package/src/components/RadioItem/index.tsx +38 -0
  147. package/src/components/Rating/index.tsx +133 -0
  148. package/src/components/RootProviders/index.tsx +31 -0
  149. package/src/components/Select/Badge/index.tsx +122 -0
  150. package/src/components/Select/Dropdown/index.tsx +188 -0
  151. package/src/components/Select/Input/index.tsx +123 -0
  152. package/src/components/Select/index.ts +13 -0
  153. package/src/components/Sidebar/Child/index.tsx +43 -0
  154. package/src/components/Sidebar/Item/Category/index.tsx +151 -0
  155. package/src/components/Sidebar/Item/Link/index.tsx +174 -0
  156. package/src/components/Sidebar/Item/Sidebar/index.tsx +67 -0
  157. package/src/components/Sidebar/Item/SubCategory/index.tsx +83 -0
  158. package/src/components/Sidebar/Item/index.tsx +41 -0
  159. package/src/components/Sidebar/Top/MobileClose/index.tsx +21 -0
  160. package/src/components/Sidebar/Top/index.tsx +33 -0
  161. package/src/components/Sidebar/index.tsx +153 -0
  162. package/src/components/SourceCodeLink/index.tsx +37 -0
  163. package/src/components/SplitLists/index.tsx +58 -0
  164. package/src/components/Table/index.tsx +87 -0
  165. package/src/components/Tabs/index.tsx +106 -0
  166. package/src/components/TextArea/index.tsx +30 -0
  167. package/src/components/ThemeImage/index.tsx +26 -0
  168. package/src/components/Toggle/index.tsx +28 -0
  169. package/src/components/Tooltip/index.tsx +65 -0
  170. package/src/components/TypeList/Items/index.tsx +337 -0
  171. package/src/components/TypeList/index.tsx +63 -0
  172. package/src/components/WideSection/index.tsx +25 -0
  173. package/src/components/ZoomImg/index.tsx +17 -0
  174. package/src/components/index.ts +75 -0
  175. package/src/constants.tsx +261 -0
  176. package/src/global-config.ts +11 -0
  177. package/src/hooks/index.ts +14 -0
  178. package/src/hooks/use-active-on-scroll/index.tsx +223 -0
  179. package/src/hooks/use-click-outside/index.tsx +37 -0
  180. package/src/hooks/use-collapsible/index.tsx +128 -0
  181. package/src/hooks/use-collapsible-code-lines/index.tsx +149 -0
  182. package/src/hooks/use-copy/index.tsx +28 -0
  183. package/src/hooks/use-heading-url/index.tsx +32 -0
  184. package/src/hooks/use-is-external-link/index.tsx +19 -0
  185. package/src/hooks/use-keyboard-shortcut/index.tsx +71 -0
  186. package/src/hooks/use-mutation-observer/index.ts +32 -0
  187. package/src/hooks/use-page-scroll-manager/index.tsx +82 -0
  188. package/src/hooks/use-resize-observer/index.ts +20 -0
  189. package/src/hooks/use-scroll-utils/index.tsx +372 -0
  190. package/src/hooks/use-select/index.tsx +99 -0
  191. package/src/hooks/use-tabs/index.tsx +94 -0
  192. package/src/index.ts +8 -0
  193. package/src/layouts/barebone.tsx +18 -0
  194. package/src/layouts/index.ts +4 -0
  195. package/src/layouts/main-content.tsx +86 -0
  196. package/src/layouts/root.tsx +43 -0
  197. package/src/layouts/tight.tsx +29 -0
  198. package/src/layouts/wide.tsx +25 -0
  199. package/src/providers/AiAssistant/index.tsx +65 -0
  200. package/src/providers/BrowserProvider/index.tsx +40 -0
  201. package/src/providers/ColorMode/index.tsx +73 -0
  202. package/src/providers/Layout/index.tsx +52 -0
  203. package/src/providers/MainNav/index.tsx +134 -0
  204. package/src/providers/Mobile/index.tsx +62 -0
  205. package/src/providers/Modal/index.tsx +52 -0
  206. package/src/providers/Notification/index.tsx +149 -0
  207. package/src/providers/Pagination/index.tsx +230 -0
  208. package/src/providers/Search/index.tsx +91 -0
  209. package/src/providers/Sidebar/index.tsx +745 -0
  210. package/src/providers/SiteConfig/index.tsx +70 -0
  211. package/src/providers/index.ts +13 -0
  212. package/src/types/config.ts +34 -0
  213. package/src/types/frontmatter.ts +23 -0
  214. package/src/types/general.ts +1 -0
  215. package/src/types/index.ts +9 -0
  216. package/src/types/menu.ts +40 -0
  217. package/src/types/navigation-dropdown.ts +16 -0
  218. package/src/types/navigation.ts +21 -0
  219. package/src/types/sidebar.ts +109 -0
  220. package/src/types/toc.ts +19 -0
  221. package/src/types/ui.ts +9 -0
  222. package/src/utils/array-same-elms.ts +10 -0
  223. package/src/utils/capitalize.ts +3 -0
  224. package/src/utils/check-sidebar-item-visibility.ts +47 -0
  225. package/src/utils/decode-str.ts +8 -0
  226. package/src/utils/dom-utils.ts +29 -0
  227. package/src/utils/event-parser.ts +54 -0
  228. package/src/utils/get-link-with-base-path.ts +3 -0
  229. package/src/utils/get-navbar-items.ts +55 -0
  230. package/src/utils/get-scrolled-top.ts +8 -0
  231. package/src/utils/index.ts +13 -0
  232. package/src/utils/is-elm-window.ts +3 -0
  233. package/src/utils/is-in-view.ts +10 -0
  234. package/src/utils/os-browser-utils.ts +39 -0
  235. package/src/utils/set-obj-value.ts +38 -0
  236. package/src/utils/sidebar-utils.ts +129 -0
@@ -0,0 +1,745 @@
1
+
2
+ import React, {
3
+ createContext,
4
+ useCallback,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useReducer,
9
+ useRef,
10
+ useState,
11
+ } from "react"
12
+ import { Sidebar } from "../../types"
13
+ import {
14
+ areSidebarItemsEqual,
15
+ findSidebarItem,
16
+ getSidebarItemWithHistory,
17
+ isSidebarItemLink,
18
+ } from "../../utils/sidebar-utils"
19
+ import { useSiteConfig } from "../SiteConfig"
20
+ import { useIsBrowser } from "../BrowserProvider"
21
+ import { getScrolledTop } from "../../utils/get-scrolled-top"
22
+ import { useLocation, useNavigate } from "react-router-dom"
23
+
24
+ export type SidebarActionOptions = {
25
+ sidebar_id: string
26
+ /**
27
+ * When specified, the items are added as children of the parent item
28
+ */
29
+ parent?: {
30
+ type: Sidebar.InteractiveSidebarItemTypes
31
+ path: string
32
+ title: string
33
+ /**
34
+ * Whether to change the loaded state of the parent item
35
+ */
36
+ changeLoaded?: boolean
37
+ }
38
+ /**
39
+ * The position to insert the items at
40
+ */
41
+ indexPosition?: number
42
+ /**
43
+ * If enabled, the items are filtered to not add items that already exist
44
+ */
45
+ ignoreExisting?: boolean
46
+ }
47
+
48
+ export type SidebarStyleOptions = {
49
+ /**
50
+ * Useful for projects that have nested sidebars.
51
+ */
52
+ disableActiveTransition?: boolean
53
+ }
54
+
55
+ export type UpdateSidebarItemTypes =
56
+ | Partial<Pick<Sidebar.SidebarItemLink, "path" | "title" | "additionalElms">>
57
+ | Partial<
58
+ Pick<
59
+ Sidebar.SidebarItemCategory,
60
+ "title" | "loaded" | "onOpen" | "children"
61
+ >
62
+ >
63
+ | Partial<Pick<Sidebar.SidebarItemSidebar, "title" | "children">>
64
+
65
+ export type UpdateActionType = {
66
+ sidebar_id: string
67
+ items: {
68
+ existingItem: Sidebar.SidebarItem
69
+ newItem: UpdateSidebarItemTypes
70
+ options?: {
71
+ setChildrenBehavior: "replace" | "merge"
72
+ }
73
+ }[]
74
+ }
75
+
76
+ export type SidebarContextType = {
77
+ sidebars: Sidebar.Sidebar[]
78
+ /**
79
+ * The sidebar that is currently shown
80
+ */
81
+ shownSidebar: Sidebar.Sidebar | Sidebar.SidebarItemSidebar | undefined
82
+ activePath: string | null
83
+ activeItem: Sidebar.SidebarItemLink | null
84
+ setActivePath: (path: string | null) => void
85
+ /**
86
+ * Check if an item is active. This includes checking its child items,
87
+ * so for UI links that have children, the `checkLinkChildren` option should be set to `false`
88
+ * to ensure that the link isn't shown as active if a child link is active.
89
+ */
90
+ isItemActive: (options: {
91
+ item: Sidebar.InteractiveSidebarItem
92
+ checkLinkChildren?: boolean
93
+ }) => boolean
94
+ addItems: (
95
+ items: Sidebar.SidebarItem[],
96
+ options?: SidebarActionOptions
97
+ ) => void
98
+ updateItems: (options: UpdateActionType) => void
99
+ removeItems: (options: {
100
+ items: Sidebar.SidebarItem[]
101
+ sidebar_id: string
102
+ }) => void
103
+ mobileSidebarOpen: boolean
104
+ setMobileSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>
105
+ desktopSidebarOpen: boolean
106
+ setDesktopSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>
107
+ // Whether the items in the sidebar are static or are added dynamically
108
+ // TODO look into generating the sidebar item of the API reference
109
+ isSidebarStatic: boolean
110
+ /**
111
+ * Whether the active path should change when the hash changes
112
+ * This is only used by the API reference
113
+ */
114
+ shouldHandleHashChange: boolean
115
+ sidebarRef: React.RefObject<HTMLDivElement | null>
116
+ /**
117
+ * Go back in the sidebar history
118
+ */
119
+ goBack: () => void
120
+ /**
121
+ * The height of the top part of the sidebar
122
+ */
123
+ sidebarTopHeight: number
124
+ setSidebarTopHeight: React.Dispatch<React.SetStateAction<number>>
125
+ /**
126
+ * Reset the sidebar to its initial state (the sidebars passed as a prop)
127
+ */
128
+ resetItems: () => void
129
+ updatePersistedCategoryState: (title: string, opened: boolean) => void
130
+ getPersistedCategoryState: (title: string) => boolean | undefined
131
+ persistCategoryState: boolean
132
+ isSidebarShown: boolean
133
+ sidebarHistory: string[]
134
+ /**
135
+ * Get the first link child of a sidebar
136
+ */
137
+ getSidebarFirstLinkChild: (
138
+ sidebar: Sidebar.Sidebar | Sidebar.SidebarItemSidebar
139
+ ) => Sidebar.SidebarItemLink | undefined
140
+ getSidebar: (
141
+ sidebar_id: string
142
+ ) => Sidebar.Sidebar | Sidebar.SidebarItemSidebar
143
+ } & SidebarStyleOptions
144
+
145
+ export const SidebarContext = createContext<SidebarContextType | null>(null)
146
+
147
+ export type ActionType =
148
+ | {
149
+ type: "add" | "update-child"
150
+ items: Sidebar.SidebarItem[]
151
+ options?: SidebarActionOptions
152
+ }
153
+ | {
154
+ type: "replace"
155
+ sidebars: Sidebar.Sidebar[]
156
+ }
157
+ | {
158
+ type: "remove"
159
+ items: Sidebar.SidebarItem[]
160
+ sidebar_id: string
161
+ }
162
+ | ({
163
+ type: "update"
164
+ } & UpdateActionType)
165
+
166
+ export const reducer = (
167
+ state: Sidebar.Sidebar[],
168
+ actionData: ActionType
169
+ ): Sidebar.Sidebar[] => {
170
+ switch (actionData.type) {
171
+ case "replace":
172
+ return actionData.sidebars
173
+ case "remove": {
174
+ const { sidebar_id, items: itemsToRemove } = actionData
175
+ return state.map((sidebar) => {
176
+ if (sidebar.sidebar_id === sidebar_id) {
177
+ return {
178
+ ...sidebar,
179
+ items: sidebar.items.filter((item) => {
180
+ return !itemsToRemove.some((itemToRemove) =>
181
+ areSidebarItemsEqual({
182
+ itemA: item,
183
+ itemB: itemToRemove,
184
+ })
185
+ )
186
+ }),
187
+ }
188
+ }
189
+ return sidebar
190
+ })
191
+ }
192
+ case "update":
193
+ return state.map((sidebar) => {
194
+ if (sidebar.sidebar_id === actionData.sidebar_id) {
195
+ return {
196
+ ...sidebar,
197
+ items: sidebar.items.map((item) => {
198
+ const itemToUpdate = actionData.items.find((i) =>
199
+ areSidebarItemsEqual({
200
+ itemA: item,
201
+ itemB: i.existingItem,
202
+ })
203
+ )
204
+ if (itemToUpdate) {
205
+ const updatedItem = {
206
+ ...item,
207
+ ...itemToUpdate.newItem,
208
+ } as Sidebar.SidebarItem
209
+
210
+ if ("children" in updatedItem) {
211
+ updatedItem.children =
212
+ itemToUpdate.options?.setChildrenBehavior === "merge"
213
+ ? [
214
+ ...((item as Sidebar.InteractiveSidebarItem)
215
+ .children || []),
216
+ ...(updatedItem.children || []),
217
+ ]
218
+ : updatedItem.children
219
+ }
220
+
221
+ return updatedItem
222
+ }
223
+ return item
224
+ }),
225
+ }
226
+ }
227
+ return sidebar
228
+ })
229
+ }
230
+
231
+ const { type, options } = actionData
232
+ let { items } = actionData
233
+
234
+ const { parent, ignoreExisting = false, indexPosition } = options || {}
235
+ const sidebarIndex = state.findIndex(
236
+ (s) => s.sidebar_id === options?.sidebar_id
237
+ )
238
+ const sidebar = state[sidebarIndex]
239
+
240
+ if (!sidebar) {
241
+ return state
242
+ }
243
+
244
+ if (!ignoreExisting) {
245
+ items = items.filter(
246
+ (item) =>
247
+ findSidebarItem({ sidebarItems: sidebar.items, item }) === undefined
248
+ )
249
+ }
250
+
251
+ if (!items.length) {
252
+ return state
253
+ }
254
+
255
+ switch (type) {
256
+ case "add":
257
+ return [
258
+ ...state.slice(0, sidebarIndex),
259
+ {
260
+ ...sidebar,
261
+ items:
262
+ indexPosition !== undefined
263
+ ? [
264
+ ...sidebar.items.slice(0, indexPosition),
265
+ ...items,
266
+ ...sidebar.items.slice(indexPosition),
267
+ ]
268
+ : [...sidebar.items, ...items],
269
+ },
270
+ ...state.slice(sidebarIndex + 1),
271
+ ]
272
+ case "update-child":
273
+ // find item index
274
+ return [
275
+ ...state.slice(0, sidebarIndex),
276
+ {
277
+ ...sidebar,
278
+ items: sidebar.items.map((i) => {
279
+ if (i.type === "separator") {
280
+ return i
281
+ }
282
+ if (
283
+ parent &&
284
+ areSidebarItemsEqual({
285
+ itemA: i,
286
+ itemB: parent as Sidebar.InteractiveSidebarItem,
287
+ })
288
+ ) {
289
+ return {
290
+ ...i,
291
+ children:
292
+ indexPosition !== undefined
293
+ ? [
294
+ ...(i.children?.slice(0, indexPosition) || []),
295
+ ...items,
296
+ ...(i.children?.slice(indexPosition) || []),
297
+ ]
298
+ : [...(i.children || []), ...items],
299
+ loaded: parent.changeLoaded
300
+ ? true
301
+ : isSidebarItemLink(i)
302
+ ? i.loaded
303
+ : true,
304
+ }
305
+ }
306
+ return i
307
+ }),
308
+ },
309
+ ...state.slice(sidebarIndex + 1),
310
+ ]
311
+ default:
312
+ return state
313
+ }
314
+ }
315
+
316
+ export type SidebarProviderProps = {
317
+ children?: React.ReactNode
318
+ isLoading?: boolean
319
+ setIsLoading?: React.Dispatch<React.SetStateAction<boolean>>
320
+ sidebars: Sidebar.Sidebar[]
321
+ shouldHandleHashChange?: boolean
322
+ shouldHandlePathChange?: boolean
323
+ scrollableElement?: Element | Window
324
+ isSidebarStatic?: boolean
325
+ persistCategoryState?: boolean
326
+ disableActiveTransition?: boolean
327
+ } & SidebarStyleOptions
328
+
329
+ export const SidebarProvider = ({
330
+ children,
331
+ isLoading,
332
+ setIsLoading,
333
+ sidebars: initialSidebars = [],
334
+ shouldHandleHashChange = false,
335
+ shouldHandlePathChange = true,
336
+ scrollableElement,
337
+ isSidebarStatic = true,
338
+ persistCategoryState = true,
339
+ disableActiveTransition = true,
340
+ }: SidebarProviderProps) => {
341
+ const {
342
+ config: { project },
343
+ } = useSiteConfig()
344
+ const categoriesStorageKey = `${project.title}_categories`
345
+ const hideSidebarStorageKey = `hide_sidebar`
346
+ const [sidebars, dispatch] = useReducer(reducer, initialSidebars)
347
+ const [activePath, setActivePath] = useState<string | null>("")
348
+ const [mobileSidebarOpen, setMobileSidebarOpen] = useState<boolean>(false)
349
+ const [desktopSidebarOpen, setDesktopSidebarOpen] = useState(true)
350
+ const sidebarRef = useRef<HTMLDivElement>(null)
351
+ const [sidebarTopHeight, setSidebarTopHeight] = useState(0)
352
+
353
+ const { pathname } = useLocation()
354
+ const navigate = useNavigate()
355
+ const { isBrowser } = useIsBrowser()
356
+
357
+ const resolvedScrollableElement = useMemo(() => {
358
+ if (!isBrowser) {
359
+ return
360
+ }
361
+
362
+ return scrollableElement || window
363
+ }, [scrollableElement, isBrowser])
364
+
365
+ const activeMainSidebar = useMemo(() => {
366
+ if (!activePath || sidebars.length === 1) {
367
+ // set first sidebar as active
368
+ return sidebars[0]
369
+ }
370
+ return (
371
+ sidebars.find(
372
+ (s) =>
373
+ findSidebarItem({
374
+ sidebarItems: s.items,
375
+ item: { type: "link", path: activePath, title: "" },
376
+ compareTitles: false,
377
+ }) !== undefined
378
+ ) || sidebars[0]
379
+ )
380
+ }, [sidebars, activePath])
381
+
382
+ const { activeItem, sidebarHistory } = useMemo(() => {
383
+ if (!activePath) {
384
+ return {
385
+ activeItem: null,
386
+ sidebarHistory: [] as string[],
387
+ }
388
+ }
389
+ const result =
390
+ getSidebarItemWithHistory({
391
+ sidebarItems: activeMainSidebar.items,
392
+ item: { type: "link", path: activePath, title: "" },
393
+ compareTitles: false,
394
+ }) || null
395
+
396
+ return {
397
+ ...result,
398
+ sidebarHistory: [
399
+ activeMainSidebar.sidebar_id,
400
+ ...(result.sidebarHistory || []),
401
+ ],
402
+ activeItem: (result.item as Sidebar.SidebarItemLink) || null,
403
+ }
404
+ }, [activePath, activeMainSidebar])
405
+
406
+ const getSidebar = useCallback(
407
+ (sidebar_id: string) => {
408
+ return (
409
+ sidebars.find((s) => s.sidebar_id === sidebar_id) ||
410
+ (findSidebarItem({
411
+ sidebarItems: activeMainSidebar.items || [],
412
+ item: { type: "sidebar", sidebar_id, title: "" },
413
+ compareTitles: false,
414
+ }) as Sidebar.SidebarItemSidebar)
415
+ )
416
+ },
417
+ [sidebars, activeMainSidebar]
418
+ )
419
+
420
+ const shownSidebar = useMemo(() => {
421
+ if (!sidebarHistory.length) {
422
+ return sidebars.length === 1 ? sidebars[0] : undefined
423
+ }
424
+
425
+ return getSidebar(sidebarHistory[sidebarHistory.length - 1])
426
+ }, [activeMainSidebar, sidebarHistory, getSidebar])
427
+
428
+ const isItemActive: SidebarContextType["isItemActive"] = useCallback(
429
+ ({ item, checkLinkChildren = true }): boolean => {
430
+ if (!activePath) {
431
+ return false
432
+ }
433
+
434
+ if (isSidebarItemLink(item)) {
435
+ if (item.path === activePath) {
436
+ return true
437
+ } else if (!checkLinkChildren) {
438
+ return false
439
+ }
440
+ }
441
+
442
+ return (
443
+ item.children?.some((child) => {
444
+ if (child.type === "separator") {
445
+ return false
446
+ }
447
+
448
+ return isItemActive({
449
+ item: child as Sidebar.InteractiveSidebarItem,
450
+ checkLinkChildren,
451
+ })
452
+ }) || false
453
+ )
454
+ },
455
+ [activePath]
456
+ )
457
+
458
+ const isSidebarShown = useMemo(() => {
459
+ if (!isBrowser) {
460
+ return true
461
+ }
462
+
463
+ return document.getElementsByTagName("aside").length > 0
464
+ }, [isBrowser])
465
+
466
+ const addItems = (
467
+ newItems: Sidebar.SidebarItem[],
468
+ options?: SidebarActionOptions
469
+ ) => {
470
+ dispatch({
471
+ type: options?.parent ? "update-child" : "add",
472
+ items: newItems,
473
+ options,
474
+ })
475
+ }
476
+
477
+ const updateItems = ({ sidebar_id, items }: UpdateActionType) => {
478
+ dispatch({
479
+ type: "update",
480
+ items,
481
+ sidebar_id,
482
+ })
483
+ }
484
+
485
+ const removeItems = ({
486
+ items,
487
+ sidebar_id,
488
+ }: {
489
+ items: Sidebar.SidebarItem[]
490
+ sidebar_id: string
491
+ }) => {
492
+ dispatch({
493
+ type: "remove",
494
+ items,
495
+ sidebar_id,
496
+ })
497
+ }
498
+
499
+ const resetItems = useCallback(() => {
500
+ dispatch({
501
+ type: "replace",
502
+ sidebars: initialSidebars,
503
+ })
504
+ }, [initialSidebars])
505
+
506
+ const init = () => {
507
+ const currentPath = location.hash.replace("#", "")
508
+ if (currentPath) {
509
+ setActivePath(currentPath)
510
+ } else {
511
+ const firstChild = getFirstLinkChild(activeMainSidebar.items)
512
+
513
+ if (firstChild) {
514
+ setActivePath(firstChild.path)
515
+ }
516
+ }
517
+ }
518
+
519
+ useEffect(() => {
520
+ if (shouldHandleHashChange) {
521
+ init()
522
+ }
523
+ }, [shouldHandleHashChange])
524
+
525
+ const handleScroll = useCallback(() => {
526
+ const scrolledTop = getScrolledTop(resolvedScrollableElement)
527
+ // account for navbar height
528
+ if (scrolledTop >= 0 && scrolledTop <= 56) {
529
+ const firstChild = getFirstLinkChild(activeMainSidebar.items)
530
+
531
+ if (firstChild) {
532
+ setActivePath(firstChild.path)
533
+ navigate(`#${firstChild.path}`, { replace: false })
534
+ }
535
+ }
536
+ }, [activeMainSidebar, resolvedScrollableElement])
537
+
538
+ useEffect(() => {
539
+ if (!shouldHandleHashChange || !resolvedScrollableElement) {
540
+ return
541
+ }
542
+
543
+ resolvedScrollableElement.addEventListener("scroll", handleScroll)
544
+
545
+ return () => {
546
+ resolvedScrollableElement.removeEventListener("scroll", handleScroll)
547
+ }
548
+ }, [shouldHandleHashChange, resolvedScrollableElement, handleScroll])
549
+
550
+ useEffect(() => {
551
+ if (!shouldHandleHashChange || !isBrowser) {
552
+ return
553
+ }
554
+
555
+ // this is mainly triggered by Algolia
556
+ const handleHashChange = () => {
557
+ const currentPath = location.hash.replace("#", "")
558
+ if (currentPath !== activePath) {
559
+ setActivePath(currentPath)
560
+ }
561
+ }
562
+
563
+ window.addEventListener("hashchange", handleHashChange)
564
+
565
+ return () => {
566
+ window.removeEventListener("hashchange", handleHashChange)
567
+ }
568
+ }, [shouldHandleHashChange, isBrowser])
569
+
570
+ useEffect(() => {
571
+ if (isLoading && sidebars.length) {
572
+ setIsLoading?.(false)
573
+ }
574
+ }, [sidebars, isLoading, setIsLoading])
575
+
576
+ useEffect(() => {
577
+ if (!shouldHandlePathChange) {
578
+ return
579
+ }
580
+
581
+ if (pathname !== activePath) {
582
+ setActivePath(pathname)
583
+ }
584
+ }, [shouldHandlePathChange, pathname])
585
+
586
+ useEffect(() => {
587
+ if (!isBrowser) {
588
+ return
589
+ }
590
+
591
+ const storageValue = localStorage.getItem(hideSidebarStorageKey)
592
+
593
+ if (storageValue !== null) {
594
+ setDesktopSidebarOpen(storageValue === "false")
595
+ }
596
+ }, [isBrowser])
597
+
598
+ useEffect(() => {
599
+ if (!isBrowser) {
600
+ return
601
+ }
602
+
603
+ localStorage.setItem(
604
+ hideSidebarStorageKey,
605
+ `${desktopSidebarOpen === false}`
606
+ )
607
+ }, [isBrowser, desktopSidebarOpen])
608
+
609
+ useEffect(() => {
610
+ if (initialSidebars[0].sidebar_id !== sidebars[0].sidebar_id) {
611
+ resetItems()
612
+ }
613
+ }, [initialSidebars])
614
+
615
+ const updatePersistedCategoryState = (title: string, opened: boolean) => {
616
+ const storageData = JSON.parse(
617
+ localStorage.getItem(categoriesStorageKey) || "{}"
618
+ )
619
+ if (!Object.hasOwn(storageData, project.title)) {
620
+ storageData[project.title] = {}
621
+ }
622
+
623
+ storageData[project.title] = {
624
+ ...storageData[project.title],
625
+ [title]: opened,
626
+ }
627
+
628
+ localStorage.setItem(categoriesStorageKey, JSON.stringify(storageData))
629
+ }
630
+
631
+ const getPersistedCategoryState = (title: string): boolean | undefined => {
632
+ const storageData = JSON.parse(
633
+ localStorage.getItem(categoriesStorageKey) || "{}"
634
+ )
635
+
636
+ return !Object.hasOwn(storageData, project.title) ||
637
+ !Object.hasOwn(storageData[project.title], title)
638
+ ? undefined
639
+ : storageData[project.title][title]
640
+ }
641
+
642
+ const getFirstLinkChild = useCallback(
643
+ (items: Sidebar.SidebarItem[]): Sidebar.SidebarItemLink | undefined => {
644
+ let foundItem: Sidebar.SidebarItemLink | undefined
645
+ items.some((item) => {
646
+ if (item.type === "link") {
647
+ foundItem = item
648
+ } else if ("children" in item && item.children) {
649
+ foundItem = getFirstLinkChild(item.children)
650
+ }
651
+
652
+ return foundItem !== undefined
653
+ })
654
+
655
+ return foundItem
656
+ },
657
+ []
658
+ )
659
+
660
+ const getSidebarFirstLinkChild = useCallback(
661
+ (
662
+ sidebar: Sidebar.Sidebar | Sidebar.SidebarItemSidebar
663
+ ): Sidebar.SidebarItemLink | undefined => {
664
+ const itemsToSearch =
665
+ "items" in sidebar ? sidebar.items : sidebar.children || []
666
+
667
+ return getFirstLinkChild(itemsToSearch)
668
+ },
669
+ [getFirstLinkChild]
670
+ )
671
+
672
+ const openSidebar = (sidebar_id: string) => {
673
+ const sidebar = getSidebar(sidebar_id)
674
+ if (!sidebar) {
675
+ return
676
+ }
677
+
678
+ const firstChild = getSidebarFirstLinkChild(sidebar)
679
+
680
+ if (firstChild) {
681
+ setActivePath(firstChild.path)
682
+ navigate(
683
+ firstChild.isPathHref ? firstChild.path : `#${firstChild.path}`,
684
+ { replace: true }
685
+ )
686
+ }
687
+ }
688
+
689
+ const goBack = () => {
690
+ if (!sidebarHistory || sidebarHistory.length <= 1) {
691
+ openSidebar(activeMainSidebar.sidebar_id)
692
+ } else {
693
+ const lastSidebar = sidebarHistory[sidebarHistory.length - 2]
694
+
695
+ openSidebar(lastSidebar)
696
+ }
697
+ }
698
+
699
+ return (
700
+ <SidebarContext.Provider
701
+ value={{
702
+ sidebars,
703
+ shownSidebar,
704
+ activePath,
705
+ activeItem,
706
+ setActivePath,
707
+ isItemActive,
708
+ addItems,
709
+ updateItems,
710
+ removeItems,
711
+ mobileSidebarOpen,
712
+ setMobileSidebarOpen,
713
+ desktopSidebarOpen,
714
+ setDesktopSidebarOpen,
715
+ isSidebarStatic,
716
+ shouldHandleHashChange,
717
+ sidebarRef,
718
+ goBack,
719
+ sidebarTopHeight,
720
+ setSidebarTopHeight,
721
+ resetItems,
722
+ updatePersistedCategoryState,
723
+ getPersistedCategoryState,
724
+ persistCategoryState,
725
+ isSidebarShown,
726
+ sidebarHistory,
727
+ getSidebarFirstLinkChild,
728
+ getSidebar,
729
+ disableActiveTransition,
730
+ }}
731
+ >
732
+ {children}
733
+ </SidebarContext.Provider>
734
+ )
735
+ }
736
+
737
+ export const useSidebar = (): SidebarContextType => {
738
+ const context = useContext(SidebarContext)
739
+
740
+ if (!context) {
741
+ throw new Error("useSidebar must be used inside a SidebarProvider")
742
+ }
743
+
744
+ return context
745
+ }