@open-press/core 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/engine/cli.mjs +1 -1
  2. package/engine/commands/_shared.mjs +10 -5
  3. package/engine/commands/deploy.mjs +19 -4
  4. package/engine/output/static-server.mjs +16 -9
  5. package/package.json +1 -1
  6. package/src/openpress/app/OpenPressApp.tsx +4 -1
  7. package/src/openpress/app/OpenPressRuntime.tsx +26 -1
  8. package/src/openpress/reader/PageThumbnailsPanel.tsx +28 -5
  9. package/src/openpress/reader/SlidePresentationPage.tsx +36 -19
  10. package/src/openpress/reader/SlidePublicPage.tsx +332 -0
  11. package/src/openpress/reader/index.ts +1 -0
  12. package/src/openpress/reader/pageViewportScaleModel.ts +5 -3
  13. package/src/openpress/reader/usePageViewportScale.ts +9 -5
  14. package/src/openpress/workbench/Workbench.tsx +46 -164
  15. package/src/openpress/workbench/actions/DeploymentControl.tsx +1 -1
  16. package/src/openpress/workbench/actions/ExportControl.tsx +267 -0
  17. package/src/openpress/workbench/actions/index.ts +1 -1
  18. package/src/openpress/workbench/actions/useDeploymentWorkbench.ts +7 -2
  19. package/src/openpress/workbench/hooks/useWorkbenchNavigation.ts +42 -0
  20. package/src/openpress/workbench/project/ProjectEntryPanel.tsx +2 -278
  21. package/src/openpress/workbench/shell/WorkbenchToolbarActions.tsx +206 -0
  22. package/src/styles/openpress/app-shell.css +0 -83
  23. package/src/styles/openpress/print-route.css +1 -3
  24. package/src/styles/openpress/project-preview-panel.css +5 -783
  25. package/src/styles/openpress/public-viewer.css +7 -249
  26. package/src/styles/openpress/reader-runtime.css +0 -274
  27. package/src/styles/openpress/slide-presenter.css +150 -0
  28. package/src/styles/openpress/slide-public-viewer.css +222 -0
  29. package/src/styles/openpress/workbench-dialog.css +267 -0
  30. package/src/styles/openpress/workbench-export.css +154 -0
  31. package/src/styles/openpress/workbench-inline-editor.css +128 -0
  32. package/src/styles/openpress/workbench-panels.css +0 -88
  33. package/src/styles/openpress/workbench-search.css +257 -0
  34. package/src/styles/openpress/workbench-toolbar.css +422 -0
  35. package/src/styles/openpress/workbench.css +34 -1263
  36. package/src/styles/openpress/workspace-gallery.css +0 -5
  37. package/src/styles/openpress.css +7 -1
  38. package/vite.config.ts +16 -9
  39. package/src/openpress/workbench/actions/ExportImageControl.tsx +0 -96
  40. package/src/styles/openpress/media-workspace.css +0 -230
@@ -0,0 +1,206 @@
1
+ import { Home, MousePointer2, Play, Ruler } from "lucide-react";
2
+ import type { Dispatch, SetStateAction } from "react";
3
+ import type { DeploymentInfo, HtmlPageBlock, SourceBlock, Theme } from "../../document-model";
4
+ import type { PageLayoutMode, PageViewportScaleMode } from "../../reader";
5
+ import {
6
+ DeploymentControl,
7
+ ExportControl,
8
+ PageZoomControl,
9
+ SearchControl,
10
+ } from "../actions";
11
+ import type { DeployStatus, InspectorCommentStatus, PdfActionStatus } from "../workbenchTypes";
12
+ import type { PageGeometrySpec } from "../workbenchFormatters";
13
+ import type { InlineDocumentEditStatus } from "../document";
14
+
15
+ export function WorkbenchToolbarActions({
16
+ pages,
17
+ currentPageIndex,
18
+ pressTitle,
19
+ theme,
20
+ workspaceMode,
21
+ sourceBlocksByPath,
22
+ onSelectPage,
23
+ onBackToWorkspace,
24
+ isSlidePress,
25
+ onOpenPresentation,
26
+ pageGeometry,
27
+ scaleMode,
28
+ scaleLabel,
29
+ pageLayoutMode,
30
+ onScaleModeChange,
31
+ onPageLayoutModeChange,
32
+ inlineEditStatus,
33
+ editStatusMessage,
34
+ inspectorMode,
35
+ inspectorToolbarExpanded,
36
+ inspectorSelectionLabel,
37
+ onInspectorModeChange,
38
+ inspectorCommentStatus,
39
+ inspectorCommentStatusMessage,
40
+ deploymentInfo,
41
+ deploymentStatus,
42
+ localDeployEnabled,
43
+ onDeploy,
44
+ onExportPdf,
45
+ pdfDisabled,
46
+ pdfLabel,
47
+ pdfStatusMessage,
48
+ pdfActionStatus,
49
+ }: {
50
+ pages: HtmlPageBlock[];
51
+ currentPageIndex: number;
52
+ pressTitle: string;
53
+ theme?: Theme;
54
+ workspaceMode: boolean;
55
+ sourceBlocksByPath: Record<string, SourceBlock[]>;
56
+ onSelectPage: (pageIndex: number, options?: { behavior?: ScrollBehavior }) => void;
57
+ onBackToWorkspace?: () => void;
58
+ isSlidePress: boolean;
59
+ onOpenPresentation?: (pageIndex: number) => void;
60
+ pageGeometry: PageGeometrySpec;
61
+ scaleMode: PageViewportScaleMode;
62
+ scaleLabel: string;
63
+ pageLayoutMode: PageLayoutMode;
64
+ onScaleModeChange: Dispatch<SetStateAction<PageViewportScaleMode>>;
65
+ onPageLayoutModeChange: Dispatch<SetStateAction<PageLayoutMode>>;
66
+ inlineEditStatus: InlineDocumentEditStatus;
67
+ editStatusMessage: string;
68
+ inspectorMode: boolean;
69
+ inspectorToolbarExpanded: boolean;
70
+ inspectorSelectionLabel: string;
71
+ onInspectorModeChange: (enabled: boolean) => void;
72
+ inspectorCommentStatus: InspectorCommentStatus;
73
+ inspectorCommentStatusMessage: string;
74
+ deploymentInfo: DeploymentInfo;
75
+ deploymentStatus: DeployStatus;
76
+ localDeployEnabled: boolean;
77
+ onDeploy: () => Promise<void>;
78
+ onExportPdf: () => void;
79
+ pdfDisabled: boolean;
80
+ pdfLabel: string;
81
+ pdfStatusMessage: string | null;
82
+ pdfActionStatus: PdfActionStatus;
83
+ }) {
84
+ return (
85
+ <>
86
+ {onBackToWorkspace ? (
87
+ <div className="openpress-workbench-toolbar__group" aria-label="工作台導覽">
88
+ <button
89
+ type="button"
90
+ className="openpress-workbench-toolbar-action openpress-workbench-toolbar-action--back"
91
+ data-openpress-back-to-workspace
92
+ onClick={onBackToWorkspace}
93
+ title="回到工作台"
94
+ aria-label="回到工作台"
95
+ >
96
+ <Home aria-hidden="true" />
97
+ <span className="openpress-workbench-toolbar-action__label">工作台</span>
98
+ </button>
99
+ </div>
100
+ ) : null}
101
+ <div className="openpress-workbench-toolbar__group" aria-label="匯出">
102
+ <ExportControl
103
+ pages={pages}
104
+ currentPageIndex={currentPageIndex}
105
+ pressTitle={pressTitle}
106
+ theme={theme}
107
+ onExportPdf={onExportPdf}
108
+ pdfDisabled={pdfDisabled}
109
+ pdfLabel={pdfLabel}
110
+ pdfStatusMessage={pdfStatusMessage}
111
+ pdfActionStatus={pdfActionStatus}
112
+ />
113
+ </div>
114
+ <div className="openpress-workbench-toolbar__group openpress-workbench-toolbar__group--page" aria-label="頁面規格">
115
+ {isSlidePress && onOpenPresentation ? (
116
+ <button
117
+ type="button"
118
+ className="openpress-workbench-toolbar-action"
119
+ data-openpress-slide-present
120
+ data-openpress-toolbar-expanded="false"
121
+ data-openpress-toolbar-active="false"
122
+ aria-pressed="false"
123
+ title="進入放映模式"
124
+ aria-label="進入放映模式"
125
+ onClick={() => onOpenPresentation(currentPageIndex)}
126
+ >
127
+ <Play aria-hidden="true" />
128
+ <span className="openpress-workbench-toolbar-action__label">放映</span>
129
+ </button>
130
+ ) : null}
131
+ <button
132
+ type="button"
133
+ className="openpress-workbench-page-geometry"
134
+ data-openpress-page-geometry
135
+ title={pageGeometry.title}
136
+ aria-label={`頁面規格 ${pageGeometry.title}`}
137
+ >
138
+ <Ruler aria-hidden="true" />
139
+ <span className="openpress-workbench-page-geometry__label">{pageGeometry.label}</span>
140
+ <span className="openpress-workbench-page-geometry__dimensions">{pageGeometry.dimensions}</span>
141
+ </button>
142
+ <PageZoomControl
143
+ scaleMode={scaleMode}
144
+ scaleLabel={scaleLabel}
145
+ pageLayoutMode={pageLayoutMode}
146
+ onScaleModeChange={onScaleModeChange}
147
+ onPageLayoutModeChange={onPageLayoutModeChange}
148
+ />
149
+ </div>
150
+ <div className="openpress-workbench-toolbar__group openpress-workbench-toolbar__group--right" aria-label="工作台狀態與發布">
151
+ {workspaceMode ? (
152
+ <SearchControl
153
+ sourceBlocksByPath={sourceBlocksByPath}
154
+ onSelectPage={onSelectPage}
155
+ />
156
+ ) : null}
157
+ {workspaceMode && editStatusMessage ? (
158
+ <span
159
+ className="openpress-dev-edit-status openpress-dev-edit-status--toolbar"
160
+ data-openpress-edit-status={inlineEditStatus.state}
161
+ role="status"
162
+ aria-live="polite"
163
+ >
164
+ {inlineEditStatus.state === "saving" ? <span className="openpress-dev-edit-status__spinner" aria-hidden="true" /> : null}
165
+ <span>{editStatusMessage}</span>
166
+ </span>
167
+ ) : null}
168
+ {workspaceMode ? (
169
+ <button
170
+ type="button"
171
+ className="openpress-workbench-toolbar-action"
172
+ data-openpress-inspector-toggle
173
+ data-openpress-inspector-active={inspectorMode ? "true" : "false"}
174
+ data-openpress-toolbar-expanded={inspectorToolbarExpanded ? "true" : "false"}
175
+ data-openpress-toolbar-active={inspectorToolbarExpanded ? "true" : "false"}
176
+ onClick={() => onInspectorModeChange(!inspectorMode)}
177
+ aria-pressed={inspectorMode}
178
+ title={inspectorMode ? "關閉註解" : "開啟註解"}
179
+ aria-label={inspectorMode ? "關閉註解" : "開啟註解"}
180
+ >
181
+ <MousePointer2 aria-hidden="true" />
182
+ <span className="openpress-workbench-toolbar-action__label">{inspectorMode ? "註解中" : "註解"}</span>
183
+ <span className="openpress-dev-inspector-status">{inspectorSelectionLabel}</span>
184
+ </button>
185
+ ) : null}
186
+ {workspaceMode && inspectorMode ? (
187
+ <span
188
+ className="openpress-dev-inspector-status"
189
+ role="status"
190
+ aria-live="polite"
191
+ data-openpress-inspector-comment-status={inspectorCommentStatus}
192
+ >
193
+ {inspectorCommentStatusMessage}
194
+ </span>
195
+ ) : null}
196
+ {localDeployEnabled ? (
197
+ <DeploymentControl
198
+ info={deploymentInfo}
199
+ status={deploymentStatus}
200
+ onDeploy={onDeploy}
201
+ />
202
+ ) : null}
203
+ </div>
204
+ </>
205
+ );
206
+ }
@@ -105,89 +105,6 @@ body {
105
105
  font-size: 13px;
106
106
  }
107
107
 
108
- /* ── Action Overlay(部署)──────────────────────────────────── */
109
- .openpress-action-overlay {
110
- position: fixed;
111
- inset: 0;
112
- z-index: 200;
113
- display: flex;
114
- align-items: center;
115
- justify-content: center;
116
- background: rgb(10 10 10 / 72%);
117
- backdrop-filter: blur(12px);
118
- -webkit-backdrop-filter: blur(12px);
119
- animation: openpress-overlay-in 0.18s ease both;
120
- }
121
-
122
- @keyframes openpress-overlay-in {
123
- from { opacity: 0; }
124
- to { opacity: 1; }
125
- }
126
-
127
- .openpress-action-overlay__card {
128
- display: flex;
129
- flex-direction: column;
130
- align-items: center;
131
- gap: 10px;
132
- border: 1px solid rgb(255 255 255 / 12%);
133
- border-radius: 16px;
134
- padding: 36px 48px;
135
- background: rgb(22 22 22 / 96%);
136
- box-shadow: 0 24px 64px rgb(0 0 0 / 60%);
137
- text-align: center;
138
- min-width: 220px;
139
- }
140
-
141
- .openpress-action-overlay__title {
142
- margin: 0;
143
- color: #f2f2f0;
144
- font-size: 15px;
145
- font-weight: 600;
146
- letter-spacing: 0.01em;
147
- }
148
-
149
- .openpress-action-overlay__sub {
150
- margin: 0;
151
- color: rgb(200 200 200 / 60%);
152
- font-size: 12px;
153
- }
154
-
155
- /* ── Deploy Icon ─────────────────────────────────────────────── */
156
- .openpress-deploy-icon {
157
- position: relative;
158
- width: 80px;
159
- height: 80px;
160
- display: flex;
161
- align-items: center;
162
- justify-content: center;
163
- }
164
-
165
- .openpress-deploy-icon--deploying { color: var(--openpress-accent, #e5c97a); }
166
- .openpress-deploy-icon--deployed { color: #6ee7a0; }
167
- .openpress-deploy-icon--failed { color: #f87171; }
168
-
169
- .openpress-deploy-rocket {
170
- animation: openpress-rocket-fly 1.4s ease-in-out infinite alternate;
171
- }
172
-
173
- @keyframes openpress-rocket-fly {
174
- from { transform: translateY(4px) rotate(-6deg); }
175
- to { transform: translateY(-6px) rotate(6deg); }
176
- }
177
-
178
- .openpress-deploy-orbit {
179
- position: absolute;
180
- inset: 0;
181
- width: 80px;
182
- height: 80px;
183
- animation: openpress-orbit-spin 2.4s linear infinite;
184
- }
185
-
186
- @keyframes openpress-orbit-spin {
187
- from { transform: rotate(0deg); }
188
- to { transform: rotate(360deg); }
189
- }
190
-
191
108
  /* ── Empty document state ───────────────────────────────────── */
192
109
 
193
110
  .openpress-empty-state {
@@ -27,7 +27,6 @@
27
27
  }
28
28
 
29
29
  .openpress-workbench,
30
- .openpress-public-shell,
31
30
  .openpress-reader-app,
32
31
  .openpress-reader-app.is-closed-left,
33
32
  .openpress-reader-app.is-closed-right,
@@ -47,8 +46,7 @@
47
46
  .reader-navbar,
48
47
  .reader-side-nav,
49
48
  .openpress-workspace-panel,
50
- .openpress-public-identity,
51
- .openpress-html-page__toolbar {
49
+ .openpress-public-identity {
52
50
  display: none !important;
53
51
  }
54
52