@open-press/core 0.7.0 → 0.8.0
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/engine/commands/dev.mjs +2 -2
- package/engine/commands/upgrade.mjs +47 -5
- package/engine/output/chrome-pdf.mjs +18 -3
- package/engine/output/static-server.mjs +39 -0
- package/engine/react/comment-endpoint.mjs +13 -39
- package/engine/react/comment-marker.mjs +30 -6
- package/engine/react/document-entry.mjs +11 -0
- package/engine/react/document-export.mjs +45 -5
- package/engine/react/http-json.mjs +24 -0
- package/engine/react/mdx-compile.mjs +187 -3
- package/engine/react/measurement-css.mjs +93 -1
- package/engine/react/object-entities.mjs +119 -0
- package/engine/react/pipeline/allocate.mjs +10 -7
- package/engine/react/pipeline/frame-measurement.mjs +40 -9
- package/engine/react/project-asset-endpoint.mjs +6 -24
- package/engine/react/source-edit-endpoint.d.mts +10 -0
- package/engine/react/source-edit-endpoint.mjs +75 -0
- package/engine/react/sources/mdx-resolver.mjs +12 -14
- package/engine/react/style-discovery.mjs +1 -4
- package/engine/runtime/file-walk.mjs +22 -0
- package/engine/runtime/inspection.mjs +1 -20
- package/engine/runtime/path-utils.mjs +20 -0
- package/engine/runtime/source-text-tools.d.mts +102 -0
- package/engine/runtime/source-text-tools.mjs +551 -16
- package/engine/runtime/source-workspace.mjs +4 -31
- package/package.json +1 -1
- package/src/openpress/{App.tsx → app/OpenPressApp.tsx} +25 -12
- package/src/openpress/{renderer.tsx → app/OpenPressRuntime.tsx} +10 -7
- package/src/openpress/app/index.ts +2 -0
- package/src/openpress/core/Frame.tsx +9 -11
- package/src/openpress/core/FrameContext.tsx +8 -3
- package/src/openpress/core/MdxArea.tsx +11 -12
- package/src/openpress/core/cn.ts +4 -0
- package/src/openpress/core/index.tsx +2 -1
- package/src/openpress/core/primitives.tsx +29 -8
- package/src/openpress/core/types.ts +8 -0
- package/src/openpress/{anchorMap.ts → document-model/anchorMapModel.ts} +1 -1
- package/src/openpress/{indexes.ts → document-model/documentIndexes.ts} +1 -1
- package/src/openpress/{types.ts → document-model/documentTypes.ts} +42 -0
- package/src/openpress/document-model/index.ts +6 -0
- package/src/openpress/document-model/objectEntityModel.ts +51 -0
- package/src/openpress/{projectIdentity.ts → document-model/projectIdentityModel.ts} +1 -1
- package/src/openpress/{reactDocumentMetadata.ts → document-model/reactDocumentMetadataModel.ts} +1 -1
- package/src/openpress/manuscript/index.tsx +49 -7
- package/src/openpress/{publicPage.tsx → reader/PublicReaderPage.tsx} +31 -51
- package/src/openpress/{workbenchPanels.tsx → reader/ReaderNavigationPanel.tsx} +6 -5
- package/src/openpress/reader/index.ts +10 -0
- package/src/openpress/reader/pageViewportScaleModel.ts +73 -0
- package/src/openpress/reader/readerTypes.ts +4 -0
- package/src/openpress/reader/usePageViewportScale.ts +119 -0
- package/src/openpress/reader/usePanelState.ts +56 -0
- package/src/openpress/reader/useReaderHashSync.ts +61 -0
- package/src/openpress/reader/useReaderKeyboardNav.ts +48 -0
- package/src/openpress/reader/useReaderRuntime.ts +146 -0
- package/src/openpress/reader/useReaderScrollAnchor.ts +64 -0
- package/src/openpress/shared/Panel.tsx +77 -0
- package/src/openpress/shared/index.ts +4 -0
- package/src/openpress/shared/numberUtils.ts +3 -0
- package/src/openpress/{runtimeMode.ts → shared/runtimeMode.ts} +0 -11
- package/src/openpress/workbench/Workbench.tsx +407 -0
- package/src/openpress/workbench/actions/DeploymentControl.tsx +157 -0
- package/src/openpress/workbench/actions/PageZoomControl.tsx +182 -0
- package/src/openpress/workbench/actions/SearchControl.tsx +345 -0
- package/src/openpress/workbench/actions/deploymentStatusModel.ts +112 -0
- package/src/openpress/workbench/actions/index.ts +5 -0
- package/src/openpress/workbench/actions/useDeploymentWorkbench.ts +136 -0
- package/src/openpress/workbench/dialog/WorkbenchDialog.tsx +72 -0
- package/src/openpress/workbench/dialog/index.ts +1 -0
- package/src/openpress/workbench/document/components/DocumentPanel.tsx +127 -0
- package/src/openpress/workbench/document/components/InlineSourceEditorLayer.tsx +207 -0
- package/src/openpress/workbench/document/components/ReaderStage.tsx +9 -0
- package/src/openpress/workbench/document/hooks/useDocumentWorkbenchModel.ts +34 -0
- package/src/openpress/workbench/document/hooks/useInlineDocumentEditor.ts +525 -0
- package/src/openpress/workbench/document/index.ts +10 -0
- package/src/openpress/workbench/index.ts +2 -0
- package/src/openpress/workbench/inspector/InlineInspectorLayer.tsx +459 -0
- package/src/openpress/workbench/inspector/index.ts +5 -0
- package/src/openpress/workbench/inspector/inlineCommentModel.ts +125 -0
- package/src/openpress/workbench/inspector/inspectorGeometryModel.ts +160 -0
- package/src/openpress/workbench/inspector/inspectorModel.ts +408 -0
- package/src/openpress/workbench/inspector/useInspectorComments.ts +248 -0
- package/src/openpress/workbench/mentions/MentionSuggestionList.tsx +41 -0
- package/src/openpress/workbench/mentions/index.ts +2 -0
- package/src/openpress/{composerMentions.ts → workbench/mentions/useComposerMentions.ts} +1 -4
- package/src/openpress/workbench/panels/Panel.tsx +1 -0
- package/src/openpress/workbench/panels/PendingCommentsPanel.tsx +76 -0
- package/src/openpress/workbench/panels/WorkbenchControlPanel.tsx +29 -0
- package/src/openpress/workbench/panels/index.ts +3 -0
- package/src/openpress/workbench/project/ProjectEntryPanel.tsx +523 -0
- package/src/openpress/workbench/project/ProjectPreviewDialog.tsx +35 -0
- package/src/openpress/workbench/project/index.ts +2 -0
- package/src/openpress/workbench/project/projectPreviewTypes.ts +11 -0
- package/src/openpress/workbench/shell/WorkbenchShell.tsx +167 -0
- package/src/openpress/workbench/shell/index.ts +1 -0
- package/src/openpress/workbench/workbenchFormatters.ts +120 -0
- package/src/openpress/workbench/workbenchTypes.ts +35 -0
- package/src/styles/openpress/print-route.css +0 -2
- package/src/styles/openpress/{project-workspace.css → project-preview-panel.css} +13 -407
- package/src/styles/openpress/public-viewer.css +25 -320
- package/src/styles/openpress/reader-runtime.css +243 -55
- package/src/styles/openpress/responsive.css +145 -270
- package/src/styles/openpress/workbench-panels.css +214 -178
- package/src/styles/openpress/workbench.css +986 -451
- package/src/styles/openpress.css +1 -1
- package/vite.config.ts +50 -0
- package/src/openpress/inspector.ts +0 -282
- package/src/openpress/projectWorkspace.tsx +0 -919
- package/src/openpress/readerRuntime.ts +0 -230
- package/src/openpress/workbench.tsx +0 -1265
- package/src/openpress/workbenchTypes.ts +0 -4
- /package/src/openpress/{readerPageRegistry.ts → reader/readerPageRegistry.ts} +0 -0
- /package/src/openpress/{pageRoute.ts → reader/readerPageRoute.ts} +0 -0
- /package/src/openpress/{readerScroll.ts → reader/readerScroll.ts} +0 -0
- /package/src/openpress/{readerState.ts → reader/readerStateModel.ts} +0 -0
- /package/src/openpress/{frameScheduler.ts → shared/frameScheduler.ts} +0 -0
- /package/src/openpress/{projectSources.ts → workbench/project/projectSourceModel.ts} +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState, type RefCallback } from "react";
|
|
2
|
+
import { pageIndexFromHash } from "./readerPageRoute";
|
|
3
|
+
import { createReaderPageRegistry } from "./readerPageRegistry";
|
|
4
|
+
import { clampReaderPageIndex, formatReaderPageNumber, normalizeReaderPageCount } from "./readerStateModel";
|
|
5
|
+
import { createPageVisibilityObserver, scrollToPage } from "./readerScroll";
|
|
6
|
+
import { usePanelState } from "./usePanelState";
|
|
7
|
+
import { useReaderScrollAnchor } from "./useReaderScrollAnchor";
|
|
8
|
+
import { useReaderHashSync } from "./useReaderHashSync";
|
|
9
|
+
import { useReaderKeyboardNav } from "./useReaderKeyboardNav";
|
|
10
|
+
|
|
11
|
+
export interface SetPageOptions {
|
|
12
|
+
behavior?: ScrollBehavior;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UseReaderRuntimeOptions {
|
|
16
|
+
pageCount: number;
|
|
17
|
+
leftPanelBreakpoint?: number;
|
|
18
|
+
rightPanelBreakpoint?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useReaderRuntime({
|
|
22
|
+
pageCount,
|
|
23
|
+
leftPanelBreakpoint,
|
|
24
|
+
rightPanelBreakpoint = 1000,
|
|
25
|
+
}: UseReaderRuntimeOptions) {
|
|
26
|
+
const normalizedPageCount = normalizeReaderPageCount(pageCount);
|
|
27
|
+
const stageRef = useRef<HTMLElement | null>(null);
|
|
28
|
+
const [pageRegistrationVersion, setPageRegistrationVersion] = useState(0);
|
|
29
|
+
const pageRegistry = useRef<ReturnType<typeof createReaderPageRegistry<HTMLElement>> | null>(null);
|
|
30
|
+
if (!pageRegistry.current) {
|
|
31
|
+
pageRegistry.current = createReaderPageRegistry<HTMLElement>(setPageRegistrationVersion);
|
|
32
|
+
}
|
|
33
|
+
const pageRefs = useMemo(() => ({
|
|
34
|
+
get current() {
|
|
35
|
+
return pageRegistry.current?.refs ?? [];
|
|
36
|
+
},
|
|
37
|
+
}), []) as { current: Array<HTMLElement | null> };
|
|
38
|
+
|
|
39
|
+
const [currentPageIndex, setCurrentPageIndex] = useState(() => {
|
|
40
|
+
if (typeof window === "undefined") return 0;
|
|
41
|
+
const fromHash = pageIndexFromHash(window.location.hash, normalizedPageCount);
|
|
42
|
+
return fromHash ?? 0;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const currentPageIndexRef = useRef(currentPageIndex);
|
|
46
|
+
currentPageIndexRef.current = currentPageIndex;
|
|
47
|
+
|
|
48
|
+
const { pendingScrollTargetRef, armPendingScrollTarget, clearPendingScrollTarget, reAnchorAfterPaint } =
|
|
49
|
+
useReaderScrollAnchor({ stageRef, pageRefs, currentPageIndexRef });
|
|
50
|
+
|
|
51
|
+
const { leftPanelOpen, rightPanelOpen, toggleLeftPanel, toggleRightPanel } = usePanelState({
|
|
52
|
+
leftPanelBreakpoint,
|
|
53
|
+
rightPanelBreakpoint,
|
|
54
|
+
// scroll-snap-type: y mandatory re-aligns to the closest snap point on
|
|
55
|
+
// viewport change, which can land one page off from where the reader was.
|
|
56
|
+
onAfterResize: reAnchorAfterPaint,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Trim the registry + clamp current page when the page count shrinks.
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
pageRegistry.current?.trim(normalizedPageCount);
|
|
62
|
+
setCurrentPageIndex((idx) => clampReaderPageIndex(idx, normalizedPageCount));
|
|
63
|
+
}, [normalizedPageCount]);
|
|
64
|
+
|
|
65
|
+
// Drive currentPageIndex from visible pages. Suppress intermediates while a
|
|
66
|
+
// programmatic scroll is in flight.
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
const stage = stageRef.current;
|
|
69
|
+
if (!stage) return undefined;
|
|
70
|
+
const observer = createPageVisibilityObserver(stage, (pageIndex) => {
|
|
71
|
+
if (pendingScrollTargetRef.current !== null) {
|
|
72
|
+
if (pageIndex !== pendingScrollTargetRef.current) return;
|
|
73
|
+
clearPendingScrollTarget();
|
|
74
|
+
}
|
|
75
|
+
setCurrentPageIndex((prev) => (prev === pageIndex ? prev : pageIndex));
|
|
76
|
+
});
|
|
77
|
+
if (!observer) return undefined;
|
|
78
|
+
pageRegistry.current?.refs.forEach((el) => el && observer.observe(el));
|
|
79
|
+
return () => observer.disconnect();
|
|
80
|
+
}, [clearPendingScrollTarget, normalizedPageCount, pageRegistrationVersion, pendingScrollTargetRef]);
|
|
81
|
+
|
|
82
|
+
// When refs change (initial mount, pagination kicks in), re-anchor the stage
|
|
83
|
+
// to the page we already believe we're on so scroll-snap mandatory doesn't
|
|
84
|
+
// pull us to whichever page is closest.
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const refs = pageRegistry.current?.refs ?? [];
|
|
87
|
+
const idx = currentPageIndexRef.current;
|
|
88
|
+
if (idx === 0) return;
|
|
89
|
+
if (!refs[idx]) return;
|
|
90
|
+
armPendingScrollTarget(idx);
|
|
91
|
+
scrollToPage(refs, idx, "instant", stageRef.current);
|
|
92
|
+
}, [armPendingScrollTarget, pageRegistrationVersion]);
|
|
93
|
+
|
|
94
|
+
const setPage = useCallback(
|
|
95
|
+
(pageIndex: number, options: SetPageOptions = {}) => {
|
|
96
|
+
const refs = pageRegistry.current?.refs ?? [];
|
|
97
|
+
const target = clampReaderPageIndex(pageIndex, normalizedPageCount);
|
|
98
|
+
armPendingScrollTarget(target);
|
|
99
|
+
setCurrentPageIndex(target);
|
|
100
|
+
scrollToPage(refs, target, options.behavior ?? "smooth", stageRef.current);
|
|
101
|
+
},
|
|
102
|
+
[armPendingScrollTarget, normalizedPageCount],
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const nextPage = useCallback(() => {
|
|
106
|
+
setPage(currentPageIndexRef.current + 1);
|
|
107
|
+
}, [setPage]);
|
|
108
|
+
|
|
109
|
+
const prevPage = useCallback(() => {
|
|
110
|
+
setPage(currentPageIndexRef.current - 1);
|
|
111
|
+
}, [setPage]);
|
|
112
|
+
|
|
113
|
+
useReaderHashSync({
|
|
114
|
+
stageRef,
|
|
115
|
+
pageRefs,
|
|
116
|
+
currentPageIndex,
|
|
117
|
+
currentPageIndexRef,
|
|
118
|
+
normalizedPageCount,
|
|
119
|
+
setCurrentPageIndex,
|
|
120
|
+
armPendingScrollTarget,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
useReaderKeyboardNav({ nextPage, prevPage, setPage, normalizedPageCount });
|
|
124
|
+
|
|
125
|
+
const registerPage = useCallback<(pageIndex: number) => RefCallback<HTMLElement>>(
|
|
126
|
+
(pageIndex) => pageRegistry.current?.registerPage(pageIndex) ?? (() => undefined),
|
|
127
|
+
[],
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const progressPercent =
|
|
131
|
+
normalizedPageCount <= 1 ? 100 : ((currentPageIndex + 1) / normalizedPageCount) * 100;
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
stageRef,
|
|
135
|
+
currentPageIndex,
|
|
136
|
+
currentPageLabel: formatReaderPageNumber(currentPageIndex + 1),
|
|
137
|
+
totalPageLabel: formatReaderPageNumber(normalizedPageCount),
|
|
138
|
+
progressPercent,
|
|
139
|
+
leftPanelOpen,
|
|
140
|
+
rightPanelOpen,
|
|
141
|
+
registerPage,
|
|
142
|
+
setPage,
|
|
143
|
+
toggleLeftPanel,
|
|
144
|
+
toggleRightPanel,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, type MutableRefObject } from "react";
|
|
2
|
+
import { scrollToPage } from "./readerScroll";
|
|
3
|
+
|
|
4
|
+
// Generous upper bound on a smooth scrollIntoView. If the target ref is gone or
|
|
5
|
+
// the browser never settles on it, clear the guard so the IO observer regains
|
|
6
|
+
// authority over currentPageIndex.
|
|
7
|
+
const PROGRAMMATIC_SCROLL_FALLBACK_MS = 2500;
|
|
8
|
+
|
|
9
|
+
export interface UseReaderScrollAnchorOptions {
|
|
10
|
+
stageRef: MutableRefObject<HTMLElement | null>;
|
|
11
|
+
pageRefs: MutableRefObject<Array<HTMLElement | null>>;
|
|
12
|
+
currentPageIndexRef: MutableRefObject<number>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ReaderScrollAnchor {
|
|
16
|
+
pendingScrollTargetRef: MutableRefObject<number | null>;
|
|
17
|
+
armPendingScrollTarget: (target: number) => void;
|
|
18
|
+
clearPendingScrollTarget: () => void;
|
|
19
|
+
reAnchorAfterPaint: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function useReaderScrollAnchor({
|
|
23
|
+
stageRef,
|
|
24
|
+
pageRefs,
|
|
25
|
+
currentPageIndexRef,
|
|
26
|
+
}: UseReaderScrollAnchorOptions): ReaderScrollAnchor {
|
|
27
|
+
// While a programmatic scroll is in flight, the IntersectionObserver should
|
|
28
|
+
// only accept the destination page (not the intermediates we sweep past).
|
|
29
|
+
const pendingScrollTargetRef = useRef<number | null>(null);
|
|
30
|
+
const pendingScrollClearTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
31
|
+
|
|
32
|
+
const armPendingScrollTarget = useCallback((target: number) => {
|
|
33
|
+
pendingScrollTargetRef.current = target;
|
|
34
|
+
if (pendingScrollClearTimerRef.current !== null) clearTimeout(pendingScrollClearTimerRef.current);
|
|
35
|
+
pendingScrollClearTimerRef.current = setTimeout(() => {
|
|
36
|
+
pendingScrollTargetRef.current = null;
|
|
37
|
+
pendingScrollClearTimerRef.current = null;
|
|
38
|
+
}, PROGRAMMATIC_SCROLL_FALLBACK_MS);
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const clearPendingScrollTarget = useCallback(() => {
|
|
42
|
+
pendingScrollTargetRef.current = null;
|
|
43
|
+
if (pendingScrollClearTimerRef.current !== null) {
|
|
44
|
+
clearTimeout(pendingScrollClearTimerRef.current);
|
|
45
|
+
pendingScrollClearTimerRef.current = null;
|
|
46
|
+
}
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
useEffect(() => () => clearPendingScrollTarget(), [clearPendingScrollTarget]);
|
|
50
|
+
|
|
51
|
+
// Re-anchor the stage to the page we already believe we're on. scroll-snap
|
|
52
|
+
// mandatory would otherwise snap to whichever page is closest after a layout
|
|
53
|
+
// change. Pin to the active programmatic target if there is one.
|
|
54
|
+
const reAnchorAfterPaint = useCallback(() => {
|
|
55
|
+
if (typeof window === "undefined") return;
|
|
56
|
+
window.requestAnimationFrame(() => {
|
|
57
|
+
const refs = pageRefs.current;
|
|
58
|
+
const target = pendingScrollTargetRef.current ?? currentPageIndexRef.current;
|
|
59
|
+
scrollToPage(refs, target, "instant", stageRef.current);
|
|
60
|
+
});
|
|
61
|
+
}, [currentPageIndexRef, pageRefs, stageRef]);
|
|
62
|
+
|
|
63
|
+
return { pendingScrollTargetRef, armPendingScrollTarget, clearPendingScrollTarget, reAnchorAfterPaint };
|
|
64
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef } from "react";
|
|
2
|
+
import { cn } from "../core/cn";
|
|
3
|
+
|
|
4
|
+
type PanelProps = ComponentPropsWithoutRef<"section">;
|
|
5
|
+
type PanelHeaderProps = ComponentPropsWithoutRef<"header">;
|
|
6
|
+
type PanelDivProps = ComponentPropsWithoutRef<"div">;
|
|
7
|
+
type PanelTextProps = ComponentPropsWithoutRef<"p">;
|
|
8
|
+
type PanelTitleProps = ComponentPropsWithoutRef<"h2">;
|
|
9
|
+
type PanelSectionTitleProps = ComponentPropsWithoutRef<"h3">;
|
|
10
|
+
type PanelButtonProps = ComponentPropsWithoutRef<"button">;
|
|
11
|
+
|
|
12
|
+
function PanelRoot({ className, ...props }: PanelProps) {
|
|
13
|
+
return <section {...props} className={cn("openpress-panel", className)} />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function PanelHeader({ className, ...props }: PanelHeaderProps) {
|
|
17
|
+
return <header {...props} className={cn("openpress-panel-header", className)} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function PanelKicker({ className, ...props }: ComponentPropsWithoutRef<"span">) {
|
|
21
|
+
return <span {...props} className={cn("openpress-panel-kicker", className)} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function PanelTitle({ className, ...props }: PanelTitleProps) {
|
|
25
|
+
return <h2 {...props} className={cn("openpress-panel-title", className)} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function PanelDescription({ className, ...props }: PanelTextProps) {
|
|
29
|
+
return <p {...props} className={cn("openpress-panel-description", className)} />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function PanelActions({ className, ...props }: PanelDivProps) {
|
|
33
|
+
return <div {...props} className={cn("openpress-panel-actions", className)} />;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function PanelActionButton({ className, ...props }: PanelButtonProps) {
|
|
37
|
+
return <button {...props} className={cn("openpress-panel-action-button", className)} />;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function PanelBody({ className, ...props }: PanelDivProps) {
|
|
41
|
+
return <div {...props} className={cn("openpress-panel-body", className)} />;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function PanelSection({ className, ...props }: PanelProps) {
|
|
45
|
+
return <section {...props} className={cn("openpress-panel-section", className)} />;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function PanelSectionTitle({ className, ...props }: PanelSectionTitleProps) {
|
|
49
|
+
return <h3 {...props} className={cn("openpress-panel-section-title", className)} />;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function PanelSectionDescription({ className, ...props }: PanelTextProps) {
|
|
53
|
+
return <p {...props} className={cn("openpress-panel-section-description", className)} />;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function PanelEmpty({ className, ...props }: PanelDivProps) {
|
|
57
|
+
return <div {...props} className={cn("openpress-panel-empty", className)} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function PanelError({ className, role = "alert", ...props }: PanelTextProps) {
|
|
61
|
+
return <p {...props} role={role} className={cn("openpress-panel-error", className)} />;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const Panel = Object.assign(PanelRoot, {
|
|
65
|
+
Header: PanelHeader,
|
|
66
|
+
Kicker: PanelKicker,
|
|
67
|
+
Title: PanelTitle,
|
|
68
|
+
Description: PanelDescription,
|
|
69
|
+
Actions: PanelActions,
|
|
70
|
+
ActionButton: PanelActionButton,
|
|
71
|
+
Body: PanelBody,
|
|
72
|
+
Section: PanelSection,
|
|
73
|
+
SectionTitle: PanelSectionTitle,
|
|
74
|
+
SectionDescription: PanelSectionDescription,
|
|
75
|
+
Empty: PanelEmpty,
|
|
76
|
+
Error: PanelError,
|
|
77
|
+
});
|
|
@@ -9,14 +9,3 @@ export function isWorkspaceModeLocation(location: Pick<Location, "hostname" | "s
|
|
|
9
9
|
export function isPrintModeLocation(location: Pick<Location, "search">) {
|
|
10
10
|
return new URLSearchParams(location.search).has("print");
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
export function buildPublicPreviewHref(currentHref: string, pageIndex?: number) {
|
|
14
|
-
const url = new URL(currentHref);
|
|
15
|
-
url.searchParams.delete("dev");
|
|
16
|
-
url.searchParams.delete("workspace");
|
|
17
|
-
url.searchParams.delete("fontPreview");
|
|
18
|
-
if (typeof pageIndex === "number") {
|
|
19
|
-
url.hash = `page-${String(pageIndex + 1).padStart(2, "0")}`;
|
|
20
|
-
}
|
|
21
|
-
return url.toString();
|
|
22
|
-
}
|