@terrafirmagreg-team/ui 1.2.2 → 1.2.4
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 +3 -3
- package/src/components/blocks/canvas/flow-viewport.tsx +6 -2
- package/src/components/blocks/lang/untranslated-chip.tsx +2 -23
- package/src/components/blocks/media/glb/scene.tsx +7 -7
- package/src/components/blocks/media/slideshow.tsx +2 -2
- package/src/components/blocks/page/heading.tsx +9 -4
- package/src/components/layouts/workspace/content.tsx +53 -0
- package/src/components/layouts/workspace/index.ts +12 -0
- package/src/components/layouts/workspace/pagination.tsx +73 -0
- package/src/components/layouts/workspace/workspace.tsx +101 -0
- package/styles/workspace.css +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrafirmagreg-team/ui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared UI kit",
|
|
6
6
|
"license": "LGPL-3.0-only",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@react-three/drei": "10.7.9",
|
|
45
45
|
"@react-three/fiber": "9.8.2",
|
|
46
46
|
"@shadcn/react": "^0.3.1",
|
|
47
|
-
"@terrafirmagreg-team/translate": "1.2.
|
|
47
|
+
"@terrafirmagreg-team/translate": "1.2.4",
|
|
48
48
|
"@xyflow/react": "12.12.0",
|
|
49
49
|
"beautiful-mermaid": "^1.1.3",
|
|
50
50
|
"class-variance-authority": "^0.7.1",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"hast-util-to-jsx-runtime": "^2.3.6",
|
|
56
56
|
"input-otp": "^1.5.0",
|
|
57
57
|
"katex": "^0.19.1",
|
|
58
|
-
"lucide-react": "^
|
|
58
|
+
"lucide-react": "^1.63.0",
|
|
59
59
|
"next-themes": "^0.4.6",
|
|
60
60
|
"react-day-picker": "^10.0.2",
|
|
61
61
|
"react-medium-image-zoom": "^5.4.9",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useEffect, useRef } from 'react';
|
|
4
4
|
import {
|
|
5
5
|
useReactFlow,
|
|
6
|
+
useStore,
|
|
6
7
|
useStoreApi,
|
|
7
8
|
} from '@terrafirmagreg-team/ui/lib/canvas/xyflow';
|
|
8
9
|
import { readStoredViewport } from '@terrafirmagreg-team/ui/lib/canvas/viewport';
|
|
@@ -46,6 +47,7 @@ export function FlowViewport({
|
|
|
46
47
|
}) {
|
|
47
48
|
const { setCenter, setViewport, getZoom } = useReactFlow();
|
|
48
49
|
const storeApi = useStoreApi();
|
|
50
|
+
const paneReady = useStore((s) => s.width > 0 && s.height > 0);
|
|
49
51
|
const initRef = useRef<string | null>(null);
|
|
50
52
|
const preInitRef = useRef<string | null>(null);
|
|
51
53
|
const nodesRef = useRef(nodes);
|
|
@@ -66,6 +68,7 @@ export function FlowViewport({
|
|
|
66
68
|
|
|
67
69
|
useEffect(() => {
|
|
68
70
|
if (viewSize.w < 1 || viewSize.h < 1) return;
|
|
71
|
+
if (!paneReady) return;
|
|
69
72
|
if (!ready) {
|
|
70
73
|
|
|
71
74
|
initRef.current = null;
|
|
@@ -170,6 +173,7 @@ export function FlowViewport({
|
|
|
170
173
|
initFocusId,
|
|
171
174
|
nodes,
|
|
172
175
|
onReady,
|
|
176
|
+
paneReady,
|
|
173
177
|
ready,
|
|
174
178
|
resetKey,
|
|
175
179
|
restoreViewport,
|
|
@@ -229,7 +233,7 @@ export function FlowViewport({
|
|
|
229
233
|
useEffect(() => {
|
|
230
234
|
if (selectedId === lastSelectedRef.current) return;
|
|
231
235
|
lastSelectedRef.current = selectedId ?? null;
|
|
232
|
-
if (initRef.current !==
|
|
236
|
+
if (initRef.current !== initKey || !selectedId) return;
|
|
233
237
|
if (selectedId === suppressPanRef?.current) return;
|
|
234
238
|
const node = nodesRef.current.find((entry) => entry.id === selectedId);
|
|
235
239
|
if (!node) return;
|
|
@@ -237,7 +241,7 @@ export function FlowViewport({
|
|
|
237
241
|
zoom: getZoom() || focusZoom,
|
|
238
242
|
duration: 300,
|
|
239
243
|
});
|
|
240
|
-
}, [focusZoom, getZoom,
|
|
244
|
+
}, [focusZoom, getZoom, initKey, selectedId, suppressPanRef, setCenter]);
|
|
241
245
|
|
|
242
246
|
return null;
|
|
243
247
|
}
|
|
@@ -2,28 +2,7 @@
|
|
|
2
2
|
import { Hint } from '@terrafirmagreg-team/ui/components/blocks/tooltip/hint';
|
|
3
3
|
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
4
4
|
import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
|
|
5
|
-
|
|
6
|
-
function LanguagesIcon({ className }: { className?: string }) {
|
|
7
|
-
return (
|
|
8
|
-
<svg
|
|
9
|
-
viewBox="0 0 24 24"
|
|
10
|
-
fill="none"
|
|
11
|
-
stroke="currentColor"
|
|
12
|
-
strokeWidth="2"
|
|
13
|
-
strokeLinecap="round"
|
|
14
|
-
strokeLinejoin="round"
|
|
15
|
-
className={className}
|
|
16
|
-
aria-hidden
|
|
17
|
-
>
|
|
18
|
-
<path d="m5 8 6 6" />
|
|
19
|
-
<path d="m4 14 6-6 2-3" />
|
|
20
|
-
<path d="M2 5h12" />
|
|
21
|
-
<path d="M7 2h1" />
|
|
22
|
-
<path d="m22 22-5-10-5 10" />
|
|
23
|
-
<path d="M14 18h6" />
|
|
24
|
-
</svg>
|
|
25
|
-
);
|
|
26
|
-
}
|
|
5
|
+
import { Languages } from 'lucide-react';
|
|
27
6
|
|
|
28
7
|
export function UntranslatedChip({ className }: { className?: string }) {
|
|
29
8
|
const t = useTranslations();
|
|
@@ -45,7 +24,7 @@ export function UntranslatedChip({ className }: { className?: string }) {
|
|
|
45
24
|
className,
|
|
46
25
|
)}
|
|
47
26
|
>
|
|
48
|
-
<
|
|
27
|
+
<Languages className="size-3" aria-hidden />
|
|
49
28
|
{t('Untranslated', { note: 'untranslated.chip' })}
|
|
50
29
|
</span>
|
|
51
30
|
</Hint>
|
|
@@ -257,7 +257,7 @@ export function GlbScene({
|
|
|
257
257
|
label: t('Viewer settings', { note: 'ui.viewer.settings' }),
|
|
258
258
|
sliders: [
|
|
259
259
|
{
|
|
260
|
-
icon: <MoveHorizontal />,
|
|
260
|
+
icon: <MoveHorizontal className="size-3.5" />,
|
|
261
261
|
label: t('Width', { note: 'ui.viewer.width' }),
|
|
262
262
|
min: SCENE_WIDTH_MIN,
|
|
263
263
|
max: SCENE_WIDTH_MAX,
|
|
@@ -267,7 +267,7 @@ export function GlbScene({
|
|
|
267
267
|
onChange: setSceneWidth,
|
|
268
268
|
},
|
|
269
269
|
{
|
|
270
|
-
icon: <MoveVertical />,
|
|
270
|
+
icon: <MoveVertical className="size-3.5" />,
|
|
271
271
|
label: t('Height', { note: 'ui.viewer.height' }),
|
|
272
272
|
min: SCENE_HEIGHT_MIN,
|
|
273
273
|
max: SCENE_HEIGHT_MAX,
|
|
@@ -277,7 +277,7 @@ export function GlbScene({
|
|
|
277
277
|
onChange: setSceneHeight,
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
|
-
icon: <Gauge />,
|
|
280
|
+
icon: <Gauge className="size-3.5" />,
|
|
281
281
|
label: t('Rotate speed', { note: 'ui.viewer.rotate_speed' }),
|
|
282
282
|
min: ROTATE_MIN,
|
|
283
283
|
max: ROTATE_MAX,
|
|
@@ -289,7 +289,7 @@ export function GlbScene({
|
|
|
289
289
|
...(multi
|
|
290
290
|
? [
|
|
291
291
|
{
|
|
292
|
-
icon: <Timer />,
|
|
292
|
+
icon: <Timer className="size-3.5" />,
|
|
293
293
|
label: t('Autoplay speed', { note: 'ui.viewer.autoplay_speed' }),
|
|
294
294
|
min: AUTOPLAY_SPEED_MIN,
|
|
295
295
|
max: AUTOPLAY_SPEED_MAX,
|
|
@@ -304,7 +304,7 @@ export function GlbScene({
|
|
|
304
304
|
],
|
|
305
305
|
toggles: [
|
|
306
306
|
{
|
|
307
|
-
icon: <RotateCw />,
|
|
307
|
+
icon: <RotateCw className="size-4" />,
|
|
308
308
|
label: t('Spin', { note: 'ui.viewer.spin' }),
|
|
309
309
|
checked: autoRotate,
|
|
310
310
|
onChange: setAutoRotate,
|
|
@@ -312,7 +312,7 @@ export function GlbScene({
|
|
|
312
312
|
...(multi
|
|
313
313
|
? [
|
|
314
314
|
{
|
|
315
|
-
icon: <Play />,
|
|
315
|
+
icon: <Play className="size-4" />,
|
|
316
316
|
label: t('Autoplay', { note: 'ui.viewer.autoplay' }),
|
|
317
317
|
checked: autoplay,
|
|
318
318
|
onChange: setAutoplay,
|
|
@@ -320,7 +320,7 @@ export function GlbScene({
|
|
|
320
320
|
]
|
|
321
321
|
: []),
|
|
322
322
|
{
|
|
323
|
-
icon: <Grid3x3 />,
|
|
323
|
+
icon: <Grid3x3 className="size-4" />,
|
|
324
324
|
label: t('Grid', { note: 'ui.viewer.grid' }),
|
|
325
325
|
checked: dotGrid,
|
|
326
326
|
onChange: setDotGrid,
|
|
@@ -141,7 +141,7 @@ export function Slideshow({
|
|
|
141
141
|
sliders: multi
|
|
142
142
|
? [
|
|
143
143
|
{
|
|
144
|
-
icon: <Timer />,
|
|
144
|
+
icon: <Timer className="size-3.5" />,
|
|
145
145
|
label: t('Autoplay speed', { note: 'ui.viewer.autoplay_speed' }),
|
|
146
146
|
min: AUTOPLAY_SPEED_MIN,
|
|
147
147
|
max: AUTOPLAY_SPEED_MAX,
|
|
@@ -156,7 +156,7 @@ export function Slideshow({
|
|
|
156
156
|
toggles: multi
|
|
157
157
|
? [
|
|
158
158
|
{
|
|
159
|
-
icon: <Play />,
|
|
159
|
+
icon: <Play className="size-4" />,
|
|
160
160
|
label: t('Autoplay', { note: 'ui.viewer.autoplay' }),
|
|
161
161
|
checked: autoplay,
|
|
162
162
|
onChange: setAutoplay,
|
|
@@ -25,14 +25,19 @@ export function Heading({
|
|
|
25
25
|
return (
|
|
26
26
|
<As
|
|
27
27
|
{...props}
|
|
28
|
+
onClick={(event) => {
|
|
29
|
+
props.onClick?.(event);
|
|
30
|
+
if (event.defaultPrevented) return;
|
|
31
|
+
if ((event.target as HTMLElement).closest('a,button,input,select,textarea,[role="button"],[role="link"]'))
|
|
32
|
+
return;
|
|
33
|
+
window.location.hash = props.id!;
|
|
34
|
+
}}
|
|
28
35
|
className={cn(
|
|
29
|
-
'group/heading flex scroll-m-28 flex-row items-center gap-1',
|
|
36
|
+
'group/heading flex cursor-pointer scroll-m-28 flex-row items-center gap-1',
|
|
30
37
|
props.className,
|
|
31
38
|
)}
|
|
32
39
|
>
|
|
33
|
-
|
|
34
|
-
{props.children}
|
|
35
|
-
</a>
|
|
40
|
+
{props.children}
|
|
36
41
|
<button
|
|
37
42
|
aria-live="polite"
|
|
38
43
|
className={cn(
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
|
|
5
|
+
export function WorkspaceBody({ className, ...props }: ComponentProps<'div'>) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="workspace-body"
|
|
9
|
+
{...props}
|
|
10
|
+
className={cn('prose flex-1', className)}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function WorkspaceDescription({
|
|
16
|
+
children,
|
|
17
|
+
className,
|
|
18
|
+
...props
|
|
19
|
+
}: ComponentProps<'p'>) {
|
|
20
|
+
if (children === undefined) return null;
|
|
21
|
+
return (
|
|
22
|
+
<p
|
|
23
|
+
data-slot="workspace-description"
|
|
24
|
+
{...props}
|
|
25
|
+
className={cn('mb-8 text-lg text-muted-foreground', className)}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</p>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function WorkspaceTitle({ className, ...props }: ComponentProps<'h1'>) {
|
|
33
|
+
return (
|
|
34
|
+
<h1
|
|
35
|
+
data-slot="workspace-title"
|
|
36
|
+
{...props}
|
|
37
|
+
className={cn('text-[1.75em] font-semibold', className)}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function WorkspaceFooter({
|
|
43
|
+
className,
|
|
44
|
+
...props
|
|
45
|
+
}: ComponentProps<'div'>) {
|
|
46
|
+
return (
|
|
47
|
+
<div
|
|
48
|
+
data-slot="workspace-footer"
|
|
49
|
+
className={cn('mt-auto empty:hidden', className)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
WorkspacePaginationItems,
|
|
3
|
+
WorkspaceProps,
|
|
4
|
+
} from './workspace';
|
|
5
|
+
export { Workspace } from './workspace';
|
|
6
|
+
export {
|
|
7
|
+
WorkspaceBody,
|
|
8
|
+
WorkspaceDescription,
|
|
9
|
+
WorkspaceTitle,
|
|
10
|
+
WorkspaceFooter,
|
|
11
|
+
} from './content';
|
|
12
|
+
export { WorkspacePagination } from './pagination';
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { type ComponentProps, useMemo } from 'react';
|
|
3
|
+
import { usePathname } from 'next/navigation';
|
|
4
|
+
import Link from '@terrafirmagreg-team/ui/components/blocks/nav/link';
|
|
5
|
+
import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react';
|
|
6
|
+
import { useFooterItems } from '@terrafirmagreg-team/ui/hooks/use-tree';
|
|
7
|
+
import { useLocationSearch } from '@terrafirmagreg-team/ui/hooks/page/use-location-search';
|
|
8
|
+
import { useTranslations } from '@terrafirmagreg-team/translate/hooks/use-translations';
|
|
9
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
10
|
+
import { isNavItemActive } from '@terrafirmagreg-team/ui/lib/utils/nav-active';
|
|
11
|
+
import type { WorkspacePaginationItems } from './workspace';
|
|
12
|
+
|
|
13
|
+
export function WorkspacePagination({
|
|
14
|
+
items,
|
|
15
|
+
className,
|
|
16
|
+
...props
|
|
17
|
+
}: ComponentProps<'nav'> & { items?: WorkspacePaginationItems }) {
|
|
18
|
+
const footerList = useFooterItems();
|
|
19
|
+
const pathname = usePathname();
|
|
20
|
+
const search = useLocationSearch();
|
|
21
|
+
const { previous, next } = useMemo(() => {
|
|
22
|
+
if (items && (items.previous || items.next)) return items;
|
|
23
|
+
const idx = footerList.findIndex((item) =>
|
|
24
|
+
isNavItemActive(item.url, pathname, search),
|
|
25
|
+
);
|
|
26
|
+
if (idx === -1) return {};
|
|
27
|
+
return { previous: footerList[idx - 1], next: footerList[idx + 1] };
|
|
28
|
+
}, [footerList, items, pathname, search]);
|
|
29
|
+
|
|
30
|
+
if (!previous && !next) return null;
|
|
31
|
+
return (
|
|
32
|
+
<nav
|
|
33
|
+
data-slot="workspace-pagination"
|
|
34
|
+
className={cn('@container grid grid-cols-2 gap-3 mt-8', className)}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{previous && <WorkspacePaginationItem item={previous} next={false} />}
|
|
38
|
+
{next && <WorkspacePaginationItem item={next} next />}
|
|
39
|
+
</nav>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function WorkspacePaginationItem({
|
|
44
|
+
item,
|
|
45
|
+
next,
|
|
46
|
+
}: {
|
|
47
|
+
item: NonNullable<WorkspacePaginationItems['previous']>;
|
|
48
|
+
next: boolean;
|
|
49
|
+
}) {
|
|
50
|
+
const t = useTranslations();
|
|
51
|
+
const Icon = next ? ArrowRightIcon : ArrowLeftIcon;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Link
|
|
55
|
+
href={item.url}
|
|
56
|
+
className={cn(
|
|
57
|
+
'group flex flex-col gap-1 rounded-2xl border p-4 text-sm transition-colors hover:bg-accent/40 @max-md:col-span-full',
|
|
58
|
+
next && 'col-start-2 items-end text-end',
|
|
59
|
+
)}
|
|
60
|
+
>
|
|
61
|
+
<span className="inline-flex items-center gap-1.5 text-muted-foreground">
|
|
62
|
+
{!next && (
|
|
63
|
+
<Icon className="size-3.5 transition-transform group-hover:-translate-x-0.5 rtl:rotate-180" />
|
|
64
|
+
)}
|
|
65
|
+
{next ? t('Next Page', { note: 'ui.next_page' }) : t('Previous Page', { note: 'ui.prev_page' })}
|
|
66
|
+
{next && (
|
|
67
|
+
<Icon className="size-3.5 transition-transform group-hover:translate-x-0.5 rtl:rotate-180" />
|
|
68
|
+
)}
|
|
69
|
+
</span>
|
|
70
|
+
<span className="font-medium">{item.name}</span>
|
|
71
|
+
</Link>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
3
|
+
import { usePathname } from 'next/navigation';
|
|
4
|
+
import type * as PageTree from '@terrafirmagreg-team/translate/types/tree';
|
|
5
|
+
import { cn } from '@terrafirmagreg-team/ui/lib/utils/cn';
|
|
6
|
+
import type { PagePreviewData } from '@terrafirmagreg-team/ui/types/preview';
|
|
7
|
+
import { LeftSidebarExpand } from '@terrafirmagreg-team/ui/components/layouts/left-sidebar';
|
|
8
|
+
import { Breadcrumb } from '@terrafirmagreg-team/ui/components/blocks/nav/breadcrumb';
|
|
9
|
+
import { WorkspaceFooter } from './content';
|
|
10
|
+
import { WorkspacePagination } from './pagination';
|
|
11
|
+
|
|
12
|
+
export type WorkspacePaginationItems = {
|
|
13
|
+
previous?: Pick<PageTree.Item, 'name' | 'description' | 'url'>;
|
|
14
|
+
next?: Pick<PageTree.Item, 'name' | 'description' | 'url'>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type WorkspaceProps = ComponentProps<'article'> & {
|
|
18
|
+
full?: boolean;
|
|
19
|
+
outlineDropdown?: ReactNode;
|
|
20
|
+
breadcrumb?: {
|
|
21
|
+
items?: { name: string; url?: string }[];
|
|
22
|
+
previews?: Record<string, PagePreviewData>;
|
|
23
|
+
};
|
|
24
|
+
pagination?: { items?: WorkspacePaginationItems } | false;
|
|
25
|
+
actions?: ReactNode;
|
|
26
|
+
footer?: ReactNode;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function Workspace({
|
|
30
|
+
full = false,
|
|
31
|
+
outlineDropdown,
|
|
32
|
+
breadcrumb,
|
|
33
|
+
pagination = {},
|
|
34
|
+
actions,
|
|
35
|
+
footer,
|
|
36
|
+
className,
|
|
37
|
+
children,
|
|
38
|
+
...props
|
|
39
|
+
}: WorkspaceProps) {
|
|
40
|
+
const crumbs = breadcrumb?.items ?? [];
|
|
41
|
+
const hasCrumbs = crumbs.length > 0;
|
|
42
|
+
const pathname = usePathname();
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div
|
|
46
|
+
key={pathname}
|
|
47
|
+
id="page-panel"
|
|
48
|
+
data-slot="workspace-panel"
|
|
49
|
+
className="@container relative flex flex-col min-w-0 min-h-0 [grid-area:main] mx-2 bg-background md:ms-0 md:my-2 md:overflow-clip md:rounded-2xl md:border md:shadow-sm print:overflow-visible"
|
|
50
|
+
>
|
|
51
|
+
<header
|
|
52
|
+
data-slot="workspace-header"
|
|
53
|
+
className={cn(
|
|
54
|
+
'absolute inset-x-0 top-0 z-10 flex items-center gap-1.5 h-(--header-height) ps-6 pe-4 bg-linear-to-b from-background to-transparent pointer-events-none *:pointer-events-auto max-md:hidden',
|
|
55
|
+
hasCrumbs || outlineDropdown ? 'from-50%' : 'to-40%',
|
|
56
|
+
)}
|
|
57
|
+
>
|
|
58
|
+
<LeftSidebarExpand />
|
|
59
|
+
{hasCrumbs && (
|
|
60
|
+
<Breadcrumb items={crumbs} previews={breadcrumb?.previews} />
|
|
61
|
+
)}
|
|
62
|
+
{outlineDropdown}
|
|
63
|
+
<div data-slot="workspace-actions" className="ms-auto">
|
|
64
|
+
{actions}
|
|
65
|
+
</div>
|
|
66
|
+
</header>
|
|
67
|
+
<div
|
|
68
|
+
data-slot="workspace-scroll"
|
|
69
|
+
className="flex flex-1 items-start px-4 md:min-h-0 md:pt-(--header-height) md:px-[max(--spacing(6),calc((100%_-_var(--page-width)_-_var(--toc-width))/2))] md:overflow-y-auto md:overscroll-y-contain md:scrollbar-thin md:scrollbar-gutter-stable md:[--docs-height:calc(var(--layout-height)_-_var(--spacing)*4_-_2px_-_var(--header-height))]"
|
|
70
|
+
>
|
|
71
|
+
<article
|
|
72
|
+
id="page"
|
|
73
|
+
data-slot="workspace"
|
|
74
|
+
data-full={full}
|
|
75
|
+
className={cn(
|
|
76
|
+
'flex flex-col gap-4 w-full min-w-0 max-w-(--page-width) pt-6 pb-8 md:min-h-(--docs-height)',
|
|
77
|
+
className,
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
>
|
|
81
|
+
{hasCrumbs && (
|
|
82
|
+
<Breadcrumb
|
|
83
|
+
items={crumbs}
|
|
84
|
+
previews={breadcrumb?.previews}
|
|
85
|
+
className="md:hidden"
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
88
|
+
{children}
|
|
89
|
+
{pagination !== false || footer ? (
|
|
90
|
+
<WorkspaceFooter>
|
|
91
|
+
{pagination !== false && (
|
|
92
|
+
<WorkspacePagination items={pagination.items} />
|
|
93
|
+
)}
|
|
94
|
+
{footer}
|
|
95
|
+
</WorkspaceFooter>
|
|
96
|
+
) : null}
|
|
97
|
+
</article>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|