@open-press/core 0.3.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.
Files changed (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/engine/chrome-pdf.d.mts +34 -0
  4. package/engine/chrome-pdf.mjs +344 -0
  5. package/engine/cli.mjs +93 -0
  6. package/engine/commands/_shared.mjs +170 -0
  7. package/engine/commands/deploy.mjs +31 -0
  8. package/engine/commands/dev.mjs +26 -0
  9. package/engine/commands/export.mjs +8 -0
  10. package/engine/commands/init.mjs +24 -0
  11. package/engine/commands/inspect.mjs +35 -0
  12. package/engine/commands/migrate-to-react.mjs +27 -0
  13. package/engine/commands/pdf.mjs +26 -0
  14. package/engine/commands/preview.mjs +26 -0
  15. package/engine/commands/render.mjs +17 -0
  16. package/engine/commands/replace.mjs +41 -0
  17. package/engine/commands/search.mjs +33 -0
  18. package/engine/commands/typecheck.mjs +5 -0
  19. package/engine/commands/validate.mjs +17 -0
  20. package/engine/config.d.mts +40 -0
  21. package/engine/config.mjs +160 -0
  22. package/engine/deploy-sync.mjs +15 -0
  23. package/engine/document-export.mjs +15 -0
  24. package/engine/file-utils.mjs +106 -0
  25. package/engine/fonts.mjs +62 -0
  26. package/engine/init.mjs +90 -0
  27. package/engine/inspection.mjs +348 -0
  28. package/engine/issue-report.mjs +44 -0
  29. package/engine/katex-assets.mjs +45 -0
  30. package/engine/page-block.mjs +30 -0
  31. package/engine/page-renderer.mjs +217 -0
  32. package/engine/pdf-media.mjs +45 -0
  33. package/engine/public-assets.mjs +19 -0
  34. package/engine/react/chapter-css.mjs +53 -0
  35. package/engine/react/comment-endpoint.d.mts +11 -0
  36. package/engine/react/comment-endpoint.mjs +128 -0
  37. package/engine/react/comment-marker.mjs +306 -0
  38. package/engine/react/document-entry.mjs +253 -0
  39. package/engine/react/document-export.mjs +392 -0
  40. package/engine/react/mdx-compile.mjs +295 -0
  41. package/engine/react/measurement-css.mjs +44 -0
  42. package/engine/react/migrate-to-react.mjs +355 -0
  43. package/engine/react/pagination-constants.mjs +3 -0
  44. package/engine/react/pagination.mjs +121 -0
  45. package/engine/react/project-asset-endpoint.d.mts +10 -0
  46. package/engine/react/project-asset-endpoint.mjs +379 -0
  47. package/engine/react/workspace-discovery.mjs +156 -0
  48. package/engine/source-text-tools.mjs +280 -0
  49. package/engine/source-workspace.mjs +76 -0
  50. package/engine/static-server.mjs +493 -0
  51. package/engine/validation.mjs +172 -0
  52. package/index.html +13 -0
  53. package/package.json +86 -0
  54. package/src/openpress/App.tsx +127 -0
  55. package/src/openpress/composerMentions.ts +188 -0
  56. package/src/openpress/core/basePages.tsx +87 -0
  57. package/src/openpress/core/index.tsx +20 -0
  58. package/src/openpress/core/types.ts +71 -0
  59. package/src/openpress/frameScheduler.ts +32 -0
  60. package/src/openpress/indexes.ts +329 -0
  61. package/src/openpress/inspector.ts +282 -0
  62. package/src/openpress/pageRoute.ts +21 -0
  63. package/src/openpress/pagination.ts +845 -0
  64. package/src/openpress/projectIdentity.ts +15 -0
  65. package/src/openpress/projectSources.ts +24 -0
  66. package/src/openpress/projectWorkspace.tsx +919 -0
  67. package/src/openpress/publicPage.tsx +469 -0
  68. package/src/openpress/reactDocumentMetadata.ts +41 -0
  69. package/src/openpress/readerPageRegistry.ts +41 -0
  70. package/src/openpress/readerRuntime.ts +230 -0
  71. package/src/openpress/readerScroll.ts +92 -0
  72. package/src/openpress/readerState.ts +15 -0
  73. package/src/openpress/renderer.tsx +91 -0
  74. package/src/openpress/runtimeMode.ts +22 -0
  75. package/src/openpress/types.ts +112 -0
  76. package/src/openpress/workbench.tsx +1299 -0
  77. package/src/openpress/workbenchPanels.tsx +122 -0
  78. package/src/openpress/workbenchTypes.ts +4 -0
  79. package/src/styles/openpress/app-shell.css +251 -0
  80. package/src/styles/openpress/media-workspace.css +230 -0
  81. package/src/styles/openpress/print-route.css +186 -0
  82. package/src/styles/openpress/project-workspace.css +1318 -0
  83. package/src/styles/openpress/public-viewer.css +983 -0
  84. package/src/styles/openpress/reader-runtime.css +792 -0
  85. package/src/styles/openpress/responsive.css +384 -0
  86. package/src/styles/openpress/workbench-panels.css +558 -0
  87. package/src/styles/openpress/workbench.css +720 -0
  88. package/src/styles/openpress.css +14 -0
  89. package/tsconfig.json +37 -0
  90. package/vite.config.ts +512 -0
@@ -0,0 +1,122 @@
1
+ import { type CSSProperties, type MouseEvent as ReactMouseEvent } from "react";
2
+ import type { BookmarkItem } from "./indexes";
3
+
4
+ type BookmarkSelectOptions = {
5
+ behavior?: ScrollBehavior;
6
+ };
7
+
8
+ export function Bookmarks({
9
+ items,
10
+ currentPageIndex,
11
+ onSelectPage,
12
+ }: {
13
+ items: BookmarkItem[];
14
+ currentPageIndex: number;
15
+ onSelectPage: (pageIndex: number, options?: BookmarkSelectOptions) => void;
16
+ }) {
17
+ const goToPage = (event: ReactMouseEvent<HTMLButtonElement>, pageIndex: number) => {
18
+ event.preventDefault();
19
+ onSelectPage(pageIndex, { behavior: "smooth" });
20
+ };
21
+
22
+ if (items.length === 0) {
23
+ return <p className="openpress-asset-empty">尚無書籤</p>;
24
+ }
25
+
26
+ return (
27
+ <>
28
+ {items.map((item, index) => {
29
+ const groupActive = currentPageIndex >= item.pageIndex && currentPageIndex <= item.endPageIndex;
30
+ const activeSub = item.subs.find((sub) => currentPageIndex >= sub.pageIndex && currentPageIndex <= sub.endPageIndex);
31
+ const h2SelfActive = groupActive && !activeSub;
32
+ const itemLabel = item.label ?? String(index + 1).padStart(2, "0");
33
+ return (
34
+ <div className={`bookmark-group${groupActive ? " is-open" : ""}`} key={item.id}>
35
+ <button
36
+ type="button"
37
+ className={`bookmark-item bookmark-h2${h2SelfActive ? " is-active" : ""}`}
38
+ data-openpress-page-index={item.pageIndex}
39
+ onClick={(event) => goToPage(event, item.pageIndex)}
40
+ >
41
+ <span className="bookmark-index">{itemLabel}</span>
42
+ <span className="bookmark-title">{item.title}</span>
43
+ </button>
44
+ <div className="bookmark-subs">
45
+ {item.subs.map((sub, subIndex) => {
46
+ const subActive = currentPageIndex >= sub.pageIndex && currentPageIndex <= sub.endPageIndex;
47
+ const activeTopic = sub.subs.find((topic) => currentPageIndex >= topic.pageIndex && currentPageIndex <= topic.endPageIndex);
48
+ const subSelfActive = subActive && !activeTopic;
49
+ const subLabel = sub.label ?? `${itemLabel}.${subIndex + 1}`;
50
+ return (
51
+ <div className="bookmark-subgroup" key={sub.id}>
52
+ <button
53
+ type="button"
54
+ className={`bookmark-item bookmark-h3${subSelfActive ? " is-active" : ""}`}
55
+ data-openpress-page-index={sub.pageIndex}
56
+ onClick={(event) => goToPage(event, sub.pageIndex)}
57
+ >
58
+ <span className="bookmark-index">{subLabel}</span>
59
+ <span className="bookmark-title">{sub.title}</span>
60
+ </button>
61
+ {sub.subs.map((topic, topicIndex) => {
62
+ const topicActive = currentPageIndex >= topic.pageIndex && currentPageIndex <= topic.endPageIndex;
63
+ const topicLabel = topic.label ?? `${subLabel}.${topicIndex + 1}`;
64
+ return (
65
+ <button
66
+ type="button"
67
+ className={`bookmark-item bookmark-h4${topicActive ? " is-active" : ""}`}
68
+ data-openpress-page-index={topic.pageIndex}
69
+ onClick={(event) => goToPage(event, topic.pageIndex)}
70
+ key={topic.id}
71
+ >
72
+ <span className="bookmark-index">{topicLabel}</span>
73
+ <span className="bookmark-title">{topic.title}</span>
74
+ </button>
75
+ );
76
+ })}
77
+ </div>
78
+ );
79
+ })}
80
+ </div>
81
+ </div>
82
+ );
83
+ })}
84
+ </>
85
+ );
86
+ }
87
+
88
+ export function CurrentPagePanel({
89
+ currentPageLabel,
90
+ totalPageLabel,
91
+ progressPercent,
92
+ title,
93
+ pageLabelPrefix,
94
+ showHeading = true,
95
+ showTitle = true,
96
+ }: {
97
+ currentPageLabel: string;
98
+ totalPageLabel: string;
99
+ progressPercent: number;
100
+ title: string;
101
+ pageLabelPrefix?: string;
102
+ showHeading?: boolean;
103
+ showTitle?: boolean;
104
+ }) {
105
+ return (
106
+ <section className="openpress-panel-section openpress-panel-section--current" aria-label="目前頁面">
107
+ {showHeading ? <div className="openpress-panel-heading">目前頁面</div> : null}
108
+ <div className="openpress-current-page-card">
109
+ <div className="openpress-current-page-card__number" aria-label="目前頁數">
110
+ {pageLabelPrefix ? <span className="openpress-current-page-card__prefix">{pageLabelPrefix}</span> : null}
111
+ <span data-openpress-current-page>{currentPageLabel}</span>
112
+ <span className="sep">/</span>
113
+ <span data-openpress-total-pages>{totalPageLabel}</span>
114
+ </div>
115
+ {showTitle ? <div className="openpress-current-page-card__title">{title}</div> : null}
116
+ <div className="openpress-current-page-card__progress" aria-hidden="true">
117
+ <span style={{ "--progress": `${progressPercent}%` } as CSSProperties} />
118
+ </div>
119
+ </div>
120
+ </section>
121
+ );
122
+ }
@@ -0,0 +1,4 @@
1
+ import type { IndexedHtmlPage } from "./indexes";
2
+ import type { HtmlPageBlock } from "./types";
3
+
4
+ export type DisplayPage = IndexedHtmlPage & Pick<HtmlPageBlock, "source">;
@@ -0,0 +1,251 @@
1
+ :root {
2
+ --openpress-scrollbar-track: #141414;
3
+ --openpress-scrollbar-track-sidebar: #171717;
4
+ --openpress-scrollbar-thumb: rgb(255 255 255 / 18%);
5
+ --openpress-scrollbar-thumb-hover: rgb(255 255 255 / 28%);
6
+
7
+ color-scheme: dark;
8
+ color: var(--openpress-text);
9
+ background: #141414;
10
+ font-family: var(--openpress-font-family);
11
+ scrollbar-color: var(--openpress-scrollbar-thumb) var(--openpress-scrollbar-track);
12
+ scrollbar-width: thin;
13
+ }
14
+
15
+ * {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ *::-webkit-scrollbar {
20
+ width: 10px;
21
+ height: 10px;
22
+ }
23
+
24
+ *::-webkit-scrollbar-track {
25
+ background: transparent;
26
+ }
27
+
28
+ *::-webkit-scrollbar-thumb {
29
+ border: 3px solid transparent;
30
+ border-radius: 999px;
31
+ background-color: var(--openpress-scrollbar-thumb);
32
+ background-clip: content-box;
33
+ }
34
+
35
+ *::-webkit-scrollbar-thumb:hover {
36
+ background-color: var(--openpress-scrollbar-thumb-hover);
37
+ }
38
+
39
+ *::-webkit-scrollbar-corner {
40
+ background: transparent;
41
+ }
42
+
43
+ body {
44
+ margin: 0;
45
+ overflow-x: hidden;
46
+ scrollbar-color: var(--openpress-scrollbar-thumb) var(--openpress-scrollbar-track);
47
+ scrollbar-width: thin;
48
+ }
49
+
50
+ /* ── Full-page loading screen ───────────────────────────────── */
51
+ .openpress-loading-screen {
52
+ position: fixed;
53
+ inset: 0;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ background: #141414;
58
+ }
59
+
60
+ .openpress-loading-screen__inner {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: center;
64
+ gap: 20px;
65
+ }
66
+
67
+ .openpress-loading-screen__label {
68
+ color: rgb(200 200 200 / 40%);
69
+ font-size: 12px;
70
+ letter-spacing: 0.12em;
71
+ text-transform: uppercase;
72
+ }
73
+
74
+ .openpress-loading-dots {
75
+ display: flex;
76
+ gap: 8px;
77
+ }
78
+
79
+ .openpress-loading-dots span {
80
+ width: 6px;
81
+ height: 6px;
82
+ border-radius: 50%;
83
+ background: var(--openpress-accent, #e5c97a);
84
+ animation: openpress-dot-pulse 1.2s ease-in-out infinite;
85
+ }
86
+
87
+ .openpress-loading-dots span:nth-child(2) { animation-delay: 0.2s; }
88
+ .openpress-loading-dots span:nth-child(3) { animation-delay: 0.4s; }
89
+
90
+ @keyframes openpress-dot-pulse {
91
+ 0%, 80%, 100% { opacity: 0.15; transform: scale(0.8); }
92
+ 40% { opacity: 1; transform: scale(1); }
93
+ }
94
+
95
+ .openpress-load-state {
96
+ position: fixed;
97
+ top: 16px;
98
+ left: 50%;
99
+ z-index: 20;
100
+ transform: translateX(-50%);
101
+ border: 1px solid rgb(255 255 255 / 14%);
102
+ padding: 8px 12px;
103
+ background: rgb(20 20 20 / 86%);
104
+ color: #d8dadd;
105
+ font-size: 13px;
106
+ }
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
+ /* ── Empty document state ───────────────────────────────────── */
192
+
193
+ .openpress-empty-state {
194
+ display: grid;
195
+ place-items: center;
196
+ min-height: 100vh;
197
+ padding: 48px 24px;
198
+ }
199
+
200
+ .openpress-empty-state__panel {
201
+ max-width: 560px;
202
+ border: 1px solid var(--openpress-scrollbar-thumb);
203
+ border-radius: 8px;
204
+ padding: 36px 32px;
205
+ background: rgb(255 255 255 / 3%);
206
+ color: var(--openpress-text-on-dark, #f4f4f4);
207
+ }
208
+
209
+ .openpress-empty-state__eyebrow {
210
+ margin: 0 0 8px;
211
+ font-size: 12px;
212
+ font-weight: 600;
213
+ letter-spacing: 0.16em;
214
+ text-transform: uppercase;
215
+ color: var(--openpress-text-secondary, #c6c6c6);
216
+ }
217
+
218
+ .openpress-empty-state__title {
219
+ margin: 0 0 16px;
220
+ font-size: 22px;
221
+ font-weight: 500;
222
+ line-height: 1.4;
223
+ }
224
+
225
+ .openpress-empty-state__body {
226
+ margin: 0 0 16px;
227
+ font-size: 14px;
228
+ line-height: 1.6;
229
+ color: var(--openpress-text-secondary, #c6c6c6);
230
+ }
231
+
232
+ .openpress-empty-state__body code,
233
+ .openpress-empty-state__steps code {
234
+ padding: 1px 6px;
235
+ border-radius: 4px;
236
+ background: rgb(255 255 255 / 8%);
237
+ font-family: var(--openpress-font-mono, "SFMono-Regular", "Menlo", monospace);
238
+ font-size: 13px;
239
+ }
240
+
241
+ .openpress-empty-state__steps {
242
+ margin: 0;
243
+ padding-left: 1.2em;
244
+ font-size: 14px;
245
+ line-height: 1.7;
246
+ color: var(--openpress-text-secondary, #c6c6c6);
247
+ }
248
+
249
+ .openpress-empty-state__steps li {
250
+ margin-bottom: 4px;
251
+ }
@@ -0,0 +1,230 @@
1
+ .openpress-media-assets {
2
+ display: grid;
3
+ grid-template-rows: auto minmax(120px, 1fr) auto auto auto;
4
+ min-height: 0;
5
+ overflow: hidden;
6
+ }
7
+
8
+ .openpress-media-workspace-page {
9
+ position: absolute;
10
+ inset: 0;
11
+ z-index: 8;
12
+ padding: 28px clamp(24px, 4vw, 48px) 40px;
13
+ background: #141414;
14
+ color: #dfe1dd;
15
+ overflow: auto;
16
+ }
17
+
18
+ .openpress-media-workspace-header {
19
+ display: flex;
20
+ gap: 18px;
21
+ align-items: start;
22
+ justify-content: space-between;
23
+ border-bottom: 1px solid rgb(255 255 255 / 9%);
24
+ padding-bottom: 18px;
25
+ }
26
+
27
+ .openpress-media-workspace-header .openpress-panel-heading {
28
+ padding: 0 0 8px;
29
+ }
30
+
31
+ .openpress-media-workspace-header h2 {
32
+ margin: 0;
33
+ color: #f2f2f0;
34
+ font-size: 22px;
35
+ font-weight: 500;
36
+ line-height: 1.2;
37
+ }
38
+
39
+ .openpress-media-workspace-header p {
40
+ margin: 8px 0 0;
41
+ color: #858c93;
42
+ font-size: 12px;
43
+ }
44
+
45
+ .openpress-media-workspace-back {
46
+ flex: 0 0 auto;
47
+ }
48
+
49
+ .openpress-media-asset-list {
50
+ display: grid;
51
+ min-height: 0;
52
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
53
+ gap: 10px;
54
+ overflow: auto;
55
+ padding: 18px 0;
56
+ scrollbar-width: none;
57
+ }
58
+
59
+ .openpress-media-asset-list::-webkit-scrollbar {
60
+ width: 0;
61
+ height: 0;
62
+ display: none;
63
+ }
64
+
65
+ .openpress-media-asset {
66
+ display: grid;
67
+ grid-template-columns: 54px minmax(0, 1fr);
68
+ gap: 12px;
69
+ align-items: center;
70
+ min-height: 66px;
71
+ border: 1px solid rgb(255 255 255 / 9%);
72
+ padding: 10px;
73
+ background: rgb(255 255 255 / 3%);
74
+ color: #a2a8ae;
75
+ text-decoration: none;
76
+ transition:
77
+ border-color 160ms ease,
78
+ background 160ms ease,
79
+ color 160ms ease;
80
+ }
81
+
82
+ .openpress-media-asset:hover {
83
+ border-color: rgb(255 255 255 / 18%);
84
+ background: rgb(255 255 255 / 6%);
85
+ color: #f3f3ef;
86
+ }
87
+
88
+ .openpress-media-asset__thumb {
89
+ display: grid;
90
+ width: 54px;
91
+ height: 54px;
92
+ place-items: center;
93
+ overflow: hidden;
94
+ border: 1px solid rgb(255 255 255 / 10%);
95
+ background: #101010;
96
+ }
97
+
98
+ .openpress-media-asset__thumb img {
99
+ display: block;
100
+ width: 100%;
101
+ height: 100%;
102
+ object-fit: cover;
103
+ }
104
+
105
+ .openpress-media-asset--svg .openpress-media-asset__thumb img {
106
+ object-fit: contain;
107
+ padding: 5px;
108
+ background: #f4f4f0;
109
+ }
110
+
111
+ .openpress-media-asset__meta {
112
+ min-width: 0;
113
+ }
114
+
115
+ .openpress-media-asset__meta strong {
116
+ display: block;
117
+ overflow: hidden;
118
+ color: #e2e4e1;
119
+ font-size: 12px;
120
+ font-weight: 500;
121
+ line-height: 1.2;
122
+ text-overflow: ellipsis;
123
+ white-space: nowrap;
124
+ }
125
+
126
+ .openpress-media-asset__meta small {
127
+ display: block;
128
+ overflow: hidden;
129
+ margin-top: 4px;
130
+ color: #6b7178;
131
+ font-size: 10px;
132
+ line-height: 1.2;
133
+ text-overflow: ellipsis;
134
+ white-space: nowrap;
135
+ }
136
+
137
+ .openpress-media-dropzone {
138
+ display: grid;
139
+ gap: 7px;
140
+ margin: 0 0 14px;
141
+ border: 1px dashed rgb(255 255 255 / 18%);
142
+ padding: 12px;
143
+ background: rgb(255 255 255 / 2%);
144
+ color: #7f868d;
145
+ font-size: 11px;
146
+ line-height: 1.45;
147
+ transition:
148
+ border-color 160ms ease,
149
+ background 160ms ease,
150
+ color 160ms ease;
151
+ }
152
+
153
+ .openpress-media-dropzone[data-drag-active="true"] {
154
+ border-color: rgb(223 75 33 / 70%);
155
+ background: rgb(223 75 33 / 9%);
156
+ color: #ece7df;
157
+ }
158
+
159
+ .openpress-media-dropzone__action,
160
+ .openpress-staged-asset button {
161
+ width: fit-content;
162
+ border: 1px solid rgb(255 255 255 / 14%);
163
+ padding: 6px 9px;
164
+ background: rgb(255 255 255 / 4%);
165
+ color: #ececea;
166
+ font: inherit;
167
+ font-size: 11px;
168
+ cursor: pointer;
169
+ }
170
+
171
+ .openpress-media-dropzone__action:hover,
172
+ .openpress-staged-asset button:hover {
173
+ border-color: rgb(255 255 255 / 24%);
174
+ background: rgb(255 255 255 / 8%);
175
+ }
176
+
177
+ .openpress-staged-assets {
178
+ display: grid;
179
+ max-height: 180px;
180
+ gap: 8px;
181
+ overflow: auto;
182
+ padding: 0 0 12px;
183
+ scrollbar-width: none;
184
+ }
185
+
186
+ .openpress-staged-asset {
187
+ display: grid;
188
+ grid-template-columns: 34px minmax(0, 1fr) auto;
189
+ gap: 9px;
190
+ align-items: center;
191
+ }
192
+
193
+ .openpress-staged-asset img {
194
+ width: 34px;
195
+ height: 34px;
196
+ object-fit: cover;
197
+ border: 1px solid rgb(255 255 255 / 10%);
198
+ background: #111;
199
+ }
200
+
201
+ .openpress-staged-asset span {
202
+ min-width: 0;
203
+ }
204
+
205
+ .openpress-staged-asset strong,
206
+ .openpress-staged-asset small {
207
+ display: block;
208
+ overflow: hidden;
209
+ text-overflow: ellipsis;
210
+ white-space: nowrap;
211
+ }
212
+
213
+ .openpress-staged-asset strong {
214
+ color: #dedfdd;
215
+ font-size: 11px;
216
+ font-weight: 500;
217
+ }
218
+
219
+ .openpress-staged-asset small {
220
+ margin-top: 3px;
221
+ color: #70767d;
222
+ font-size: 10px;
223
+ }
224
+
225
+ body::-webkit-scrollbar,
226
+ html::-webkit-scrollbar {
227
+ width: 0;
228
+ height: 0;
229
+ display: none;
230
+ }