@atom63/resume 0.1.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/dist/chunk-FL25EF7U.js +384 -0
- package/dist/chunk-FL25EF7U.js.map +1 -0
- package/dist/editor/index.css +225 -0
- package/dist/editor/index.css.map +1 -0
- package/dist/editor/index.d.ts +35 -0
- package/dist/editor/index.js +127 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/index.css +334 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +232 -0
- package/dist/index.js +638 -0
- package/dist/index.js.map +1 -0
- package/dist/vite/index.d.ts +26 -0
- package/dist/vite/index.js +73 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +108 -0
- package/src/styles/css-modules.d.ts +5 -0
- package/src/styles/document.css +170 -0
- package/src/styles/styles.css +9 -0
- package/src/styles/styles.d.ts +3 -0
- package/src/styles/tokens.css +48 -0
- package/src/styles/tokens.d.ts +3 -0
- package/src/styles/viewer.css +205 -0
package/dist/index.css
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/* src/styles/tokens.css */
|
|
2
|
+
[data-resume-document] {
|
|
3
|
+
--paper-width: 8.5in;
|
|
4
|
+
--paper-height: 11in;
|
|
5
|
+
--paper-pad-x: 0.7in;
|
|
6
|
+
--paper-pad-y: 0.6in;
|
|
7
|
+
--paper-gap: 32px;
|
|
8
|
+
--doc-meta-col: 11rem;
|
|
9
|
+
--doc-resume-cols: 1fr 2fr;
|
|
10
|
+
--doc-col-gap: 0.75rem;
|
|
11
|
+
--doc-col-pad: 1.5rem;
|
|
12
|
+
--doc-block-gap: 0.375rem;
|
|
13
|
+
--doc-section-gap: 0.5rem;
|
|
14
|
+
--doc-group-gap: 0.125rem;
|
|
15
|
+
--doc-text: 10px;
|
|
16
|
+
--doc-text-xs: 8px;
|
|
17
|
+
--doc-leading: 1.4;
|
|
18
|
+
--doc-leading-heading: 1.5;
|
|
19
|
+
--doc-ink: #000;
|
|
20
|
+
--doc-ink-body: #404040;
|
|
21
|
+
--doc-ink-muted: #737373;
|
|
22
|
+
--doc-ink-faint: #a3a3a3;
|
|
23
|
+
--doc-rule: #d4d4d4;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* src/styles/document.css */
|
|
27
|
+
.doc-meta-grid {
|
|
28
|
+
display: grid;
|
|
29
|
+
min-width: 0;
|
|
30
|
+
grid-template-columns: var(--doc-meta-col) minmax(0, 1fr);
|
|
31
|
+
gap: var(--doc-col-gap);
|
|
32
|
+
}
|
|
33
|
+
.doc-resume-grid {
|
|
34
|
+
display: grid;
|
|
35
|
+
min-width: 0;
|
|
36
|
+
grid-template-columns: var(--doc-resume-cols);
|
|
37
|
+
}
|
|
38
|
+
.doc-col {
|
|
39
|
+
display: flex;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: var(--doc-block-gap);
|
|
43
|
+
}
|
|
44
|
+
.doc-group {
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
gap: var(--doc-group-gap);
|
|
48
|
+
}
|
|
49
|
+
.doc-section {
|
|
50
|
+
margin-top: var(--doc-section-gap);
|
|
51
|
+
}
|
|
52
|
+
.doc-body {
|
|
53
|
+
font-size: var(--doc-text);
|
|
54
|
+
line-height: var(--doc-leading);
|
|
55
|
+
color: var(--doc-ink-body);
|
|
56
|
+
overflow-wrap: break-word;
|
|
57
|
+
}
|
|
58
|
+
.doc-meta {
|
|
59
|
+
font-size: var(--doc-text);
|
|
60
|
+
line-height: var(--doc-leading);
|
|
61
|
+
color: var(--doc-ink-muted);
|
|
62
|
+
}
|
|
63
|
+
.doc-heading {
|
|
64
|
+
font-size: var(--doc-text);
|
|
65
|
+
line-height: var(--doc-leading-heading);
|
|
66
|
+
color: var(--doc-ink);
|
|
67
|
+
font-weight: 700;
|
|
68
|
+
text-transform: uppercase;
|
|
69
|
+
}
|
|
70
|
+
.doc-title {
|
|
71
|
+
font-size: var(--doc-text);
|
|
72
|
+
line-height: 1;
|
|
73
|
+
color: var(--doc-ink);
|
|
74
|
+
font-weight: 700;
|
|
75
|
+
text-transform: uppercase;
|
|
76
|
+
}
|
|
77
|
+
.doc-subheading {
|
|
78
|
+
font-size: var(--doc-text);
|
|
79
|
+
line-height: 1;
|
|
80
|
+
color: var(--doc-ink);
|
|
81
|
+
font-weight: 600;
|
|
82
|
+
}
|
|
83
|
+
.doc-strong {
|
|
84
|
+
color: var(--doc-ink);
|
|
85
|
+
font-weight: 600;
|
|
86
|
+
}
|
|
87
|
+
.doc-link {
|
|
88
|
+
color: var(--doc-ink-body);
|
|
89
|
+
text-decoration: underline;
|
|
90
|
+
touch-action: manipulation;
|
|
91
|
+
}
|
|
92
|
+
.doc-rule {
|
|
93
|
+
margin: 0.25rem 0;
|
|
94
|
+
border-bottom: 1px solid var(--doc-rule);
|
|
95
|
+
}
|
|
96
|
+
.doc-footer {
|
|
97
|
+
font-size: var(--doc-text-xs);
|
|
98
|
+
color: var(--doc-ink-faint);
|
|
99
|
+
margin-top: auto;
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: flex-end;
|
|
102
|
+
justify-content: space-between;
|
|
103
|
+
}
|
|
104
|
+
.doc-footer a {
|
|
105
|
+
color: inherit;
|
|
106
|
+
}
|
|
107
|
+
.doc-header {
|
|
108
|
+
margin-bottom: 0.75rem;
|
|
109
|
+
}
|
|
110
|
+
.doc-header-col {
|
|
111
|
+
display: flex;
|
|
112
|
+
min-width: 0;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
justify-content: space-between;
|
|
115
|
+
}
|
|
116
|
+
.doc-header-left {
|
|
117
|
+
padding-right: var(--doc-col-pad);
|
|
118
|
+
}
|
|
119
|
+
.doc-header-right {
|
|
120
|
+
padding-left: var(--doc-col-pad);
|
|
121
|
+
}
|
|
122
|
+
.doc-header-right > p + p {
|
|
123
|
+
margin-top: 0.125rem;
|
|
124
|
+
}
|
|
125
|
+
.doc-links {
|
|
126
|
+
margin-top: 0.75rem;
|
|
127
|
+
}
|
|
128
|
+
.doc-links > p {
|
|
129
|
+
margin-top: 0;
|
|
130
|
+
color: var(--doc-ink-muted);
|
|
131
|
+
}
|
|
132
|
+
.doc-links a {
|
|
133
|
+
color: inherit;
|
|
134
|
+
}
|
|
135
|
+
.doc-links em {
|
|
136
|
+
color: var(--doc-ink-faint);
|
|
137
|
+
}
|
|
138
|
+
.doc-entry-body {
|
|
139
|
+
min-width: 0;
|
|
140
|
+
}
|
|
141
|
+
.doc-col-sidebar {
|
|
142
|
+
grid-column-start: 1;
|
|
143
|
+
grid-row-start: 1;
|
|
144
|
+
padding-right: var(--doc-col-pad);
|
|
145
|
+
}
|
|
146
|
+
.doc-col-main {
|
|
147
|
+
grid-column-start: 2;
|
|
148
|
+
grid-row-start: 1;
|
|
149
|
+
padding-left: var(--doc-col-pad);
|
|
150
|
+
}
|
|
151
|
+
.doc-list {
|
|
152
|
+
list-style: disc;
|
|
153
|
+
padding-left: 0.75rem;
|
|
154
|
+
}
|
|
155
|
+
.doc-em {
|
|
156
|
+
font-style: normal;
|
|
157
|
+
}
|
|
158
|
+
.doc-hr {
|
|
159
|
+
margin: 0.75rem 0;
|
|
160
|
+
}
|
|
161
|
+
.doc-pages {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
}
|
|
165
|
+
.doc-page {
|
|
166
|
+
position: relative;
|
|
167
|
+
display: flex;
|
|
168
|
+
flex-direction: column;
|
|
169
|
+
background: #fff;
|
|
170
|
+
color: #000;
|
|
171
|
+
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* src/styles/viewer.css */
|
|
175
|
+
#resume-print-target,
|
|
176
|
+
#resume-print-target * {
|
|
177
|
+
-webkit-text-size-adjust: none;
|
|
178
|
+
text-size-adjust: none;
|
|
179
|
+
}
|
|
180
|
+
[data-resume-scale-root] {
|
|
181
|
+
transform-origin: top left;
|
|
182
|
+
}
|
|
183
|
+
.resume-viewer {
|
|
184
|
+
display: flex;
|
|
185
|
+
flex-direction: column;
|
|
186
|
+
height: 100%;
|
|
187
|
+
overflow: hidden;
|
|
188
|
+
}
|
|
189
|
+
.resume-viewer-toolbar {
|
|
190
|
+
display: flex;
|
|
191
|
+
align-items: center;
|
|
192
|
+
justify-content: space-between;
|
|
193
|
+
gap: 0.75rem;
|
|
194
|
+
padding: 0.375rem 0.75rem;
|
|
195
|
+
border-bottom: 1px solid rgb(0 0 0 / 0.08);
|
|
196
|
+
background: #fff;
|
|
197
|
+
flex: 0 0 auto;
|
|
198
|
+
}
|
|
199
|
+
.resume-viewer-pagecount {
|
|
200
|
+
font-size: 0.8125rem;
|
|
201
|
+
color: rgb(0 0 0 / 0.55);
|
|
202
|
+
}
|
|
203
|
+
.resume-viewer-controls {
|
|
204
|
+
display: flex;
|
|
205
|
+
align-items: center;
|
|
206
|
+
gap: 0.25rem;
|
|
207
|
+
}
|
|
208
|
+
.resume-viewer-btn-group {
|
|
209
|
+
display: flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
}
|
|
212
|
+
.resume-viewer-btn {
|
|
213
|
+
display: inline-flex;
|
|
214
|
+
align-items: center;
|
|
215
|
+
justify-content: center;
|
|
216
|
+
height: 2rem;
|
|
217
|
+
min-width: 2rem;
|
|
218
|
+
padding: 0 0.375rem;
|
|
219
|
+
border: 0;
|
|
220
|
+
border-radius: 0.375rem;
|
|
221
|
+
background: transparent;
|
|
222
|
+
color: rgb(0 0 0 / 0.7);
|
|
223
|
+
font-size: 0.8125rem;
|
|
224
|
+
cursor: pointer;
|
|
225
|
+
}
|
|
226
|
+
.resume-viewer-btn:hover:not(:disabled) {
|
|
227
|
+
background: rgb(0 0 0 / 0.06);
|
|
228
|
+
}
|
|
229
|
+
.resume-viewer-btn:disabled {
|
|
230
|
+
opacity: 0.4;
|
|
231
|
+
cursor: default;
|
|
232
|
+
}
|
|
233
|
+
.resume-viewer-btn-active {
|
|
234
|
+
background: rgb(0 0 0 / 0.08);
|
|
235
|
+
color: rgb(0 0 0 / 0.9);
|
|
236
|
+
}
|
|
237
|
+
.resume-viewer-btn-text {
|
|
238
|
+
padding: 0 0.625rem;
|
|
239
|
+
}
|
|
240
|
+
.resume-viewer-zoom-label {
|
|
241
|
+
display: inline-flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
justify-content: center;
|
|
244
|
+
height: 2rem;
|
|
245
|
+
width: 3rem;
|
|
246
|
+
border: 0;
|
|
247
|
+
border-radius: 0.375rem;
|
|
248
|
+
background: transparent;
|
|
249
|
+
color: rgb(0 0 0 / 0.55);
|
|
250
|
+
font-size: 0.8125rem;
|
|
251
|
+
font-variant-numeric: tabular-nums;
|
|
252
|
+
cursor: pointer;
|
|
253
|
+
}
|
|
254
|
+
.resume-viewer-zoom-label:hover {
|
|
255
|
+
background: rgb(0 0 0 / 0.06);
|
|
256
|
+
}
|
|
257
|
+
.resume-viewer-icon {
|
|
258
|
+
width: 1rem;
|
|
259
|
+
height: 1rem;
|
|
260
|
+
}
|
|
261
|
+
.resume-viewer-scroll {
|
|
262
|
+
flex: 1 1 auto;
|
|
263
|
+
min-height: 0;
|
|
264
|
+
overflow: auto;
|
|
265
|
+
background: rgb(244 244 245);
|
|
266
|
+
}
|
|
267
|
+
.resume-viewer-scroll-grab {
|
|
268
|
+
cursor: grab;
|
|
269
|
+
}
|
|
270
|
+
.resume-viewer-scroll-grabbing {
|
|
271
|
+
cursor: grabbing;
|
|
272
|
+
}
|
|
273
|
+
.resume-viewer-scroll-mobile {
|
|
274
|
+
touch-action: none;
|
|
275
|
+
user-select: none;
|
|
276
|
+
}
|
|
277
|
+
.resume-viewer-stage {
|
|
278
|
+
margin-top: 1.5rem;
|
|
279
|
+
margin-bottom: 1.5rem;
|
|
280
|
+
padding-left: 1rem;
|
|
281
|
+
padding-right: 1rem;
|
|
282
|
+
}
|
|
283
|
+
.resume-viewer-page-box {
|
|
284
|
+
margin-left: auto;
|
|
285
|
+
margin-right: auto;
|
|
286
|
+
}
|
|
287
|
+
.resume-viewer-scale-root {
|
|
288
|
+
position: relative;
|
|
289
|
+
}
|
|
290
|
+
.resume-viewer-content {
|
|
291
|
+
position: relative;
|
|
292
|
+
display: flex;
|
|
293
|
+
flex-direction: column;
|
|
294
|
+
color: #000;
|
|
295
|
+
}
|
|
296
|
+
[data-slot=scroll-area-viewport][data-pan-active],
|
|
297
|
+
.resume-viewer-scroll[data-pan-active] {
|
|
298
|
+
background-color: color-mix(in oklch, var(--muted) 42%, transparent);
|
|
299
|
+
}
|
|
300
|
+
@media (prefers-reduced-motion: reduce) {
|
|
301
|
+
[data-slot=scroll-area-viewport][data-pan-active],
|
|
302
|
+
.resume-viewer-scroll[data-pan-active] {
|
|
303
|
+
transition: none;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
#resume-print-target a,
|
|
307
|
+
#resume-print-target button {
|
|
308
|
+
touch-action: manipulation;
|
|
309
|
+
}
|
|
310
|
+
@media print {
|
|
311
|
+
body:has(#resume-print-clone) > :not(#resume-print-clone) {
|
|
312
|
+
display: none !important;
|
|
313
|
+
}
|
|
314
|
+
#resume-print-clone {
|
|
315
|
+
color: black !important;
|
|
316
|
+
background: white !important;
|
|
317
|
+
}
|
|
318
|
+
#resume-print-clone > div {
|
|
319
|
+
gap: 0 !important;
|
|
320
|
+
}
|
|
321
|
+
[data-resume-page] {
|
|
322
|
+
box-shadow: none !important;
|
|
323
|
+
break-after: page;
|
|
324
|
+
break-inside: avoid;
|
|
325
|
+
}
|
|
326
|
+
[data-resume-page]:last-child {
|
|
327
|
+
break-after: auto;
|
|
328
|
+
}
|
|
329
|
+
@page {
|
|
330
|
+
size: letter;
|
|
331
|
+
margin: 0;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/*# sourceMappingURL=index.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/styles/tokens.css","../src/styles/document.css","../src/styles/viewer.css"],"sourcesContent":["/*\n * @atom63/resume — paper/document design tokens.\n *\n * The single source of truth for the resume/CV look. Override any token (e.g.\n * in your own stylesheet, scoped to [data-resume-document]) to restyle the\n * resume and CV together; the React primitives only compose these.\n *\n * --paper-* : page geometry (defaults: US Letter @ 96dpi; override for A4).\n * --doc-* : document language (layout, type, ink).\n *\n * Print-fixed by design: doc sizes are absolute px for PDF fidelity, independent\n * of any host typography-scale setting. The font *family* is inherited (so the\n * document follows the host font), which is why pagination re-measures on font\n * change.\n *\n * NOTE: the numeric --paper-* defaults and --doc-block-gap MUST stay in sync with\n * geometry.ts (the JS packer reads the same numbers to compute page breaks).\n */\n[data-resume-document] {\n /* Page geometry (US Letter @ 96dpi — see geometry.ts) */\n --paper-width: 8.5in;\n --paper-height: 11in;\n --paper-pad-x: 0.7in;\n --paper-pad-y: 0.6in;\n --paper-gap: 32px; /* screen-only gap between page frames */\n\n /* Document layout */\n --doc-meta-col: 11rem; /* left meta/label column (header name, section label, year|role) */\n --doc-resume-cols: 1fr 2fr; /* resume sidebar | main split */\n --doc-col-gap: 0.75rem; /* gap between the meta column and content */\n --doc-col-pad: 1.5rem; /* resume two-column inner gutter */\n --doc-block-gap: 0.375rem; /* between blocks within a column (== BLOCK_GAP_PX) */\n --doc-section-gap: 0.5rem; /* space above a section */\n --doc-group-gap: 0.125rem; /* within a tight group (title + meta line) */\n\n /* Type */\n --doc-text: 10px;\n --doc-text-xs: 8px;\n --doc-leading: 1.4;\n --doc-leading-heading: 1.5;\n\n /* Ink (on the white page) */\n --doc-ink: #000; /* headings, strong */\n --doc-ink-body: #404040; /* body copy (neutral-700) */\n --doc-ink-muted: #737373; /* meta / labels (neutral-500) */\n --doc-ink-faint: #a3a3a3; /* footer, faint detail (neutral-400) */\n --doc-rule: #d4d4d4; /* dividers (neutral-300) */\n}\n","/*\n * Resume & CV document layout + type primitives. These classes only COMPOSE the\n * design tokens — the token vocabulary itself (the paper and doc custom\n * properties) lives in tokens.css (imported separately, or together via\n * styles.css). Keep this file token-free so consumers can adopt just the tokens,\n * or restyle without forking these classes.\n */\n\n/* Layout primitives */\n.doc-meta-grid {\n display: grid;\n min-width: 0;\n grid-template-columns: var(--doc-meta-col) minmax(0, 1fr);\n gap: var(--doc-col-gap);\n}\n.doc-resume-grid {\n display: grid;\n min-width: 0;\n grid-template-columns: var(--doc-resume-cols);\n}\n.doc-col {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: var(--doc-block-gap);\n}\n.doc-group {\n display: flex;\n flex-direction: column;\n gap: var(--doc-group-gap);\n}\n.doc-section {\n margin-top: var(--doc-section-gap);\n}\n\n/* Type primitives */\n.doc-body {\n font-size: var(--doc-text);\n line-height: var(--doc-leading);\n color: var(--doc-ink-body);\n overflow-wrap: break-word;\n}\n.doc-meta {\n font-size: var(--doc-text);\n line-height: var(--doc-leading);\n color: var(--doc-ink-muted);\n}\n.doc-heading {\n font-size: var(--doc-text);\n line-height: var(--doc-leading-heading);\n color: var(--doc-ink);\n font-weight: 700;\n text-transform: uppercase;\n}\n.doc-title {\n font-size: var(--doc-text);\n line-height: 1;\n color: var(--doc-ink);\n font-weight: 700;\n text-transform: uppercase;\n}\n.doc-subheading {\n font-size: var(--doc-text);\n line-height: 1;\n color: var(--doc-ink);\n font-weight: 600;\n}\n.doc-strong {\n color: var(--doc-ink);\n font-weight: 600;\n}\n.doc-link {\n color: var(--doc-ink-body);\n text-decoration: underline;\n /* touch-manipulation equivalent for links */\n touch-action: manipulation;\n}\n.doc-rule {\n margin: 0.25rem 0;\n border-bottom: 1px solid var(--doc-rule);\n}\n.doc-footer {\n font-size: var(--doc-text-xs);\n color: var(--doc-ink-faint);\n /* Layout (replacing Tailwind utilities) */\n margin-top: auto;\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n}\n.doc-footer a {\n color: inherit;\n}\n\n/* Header / layout helpers (replacing Tailwind utilities) */\n.doc-header {\n margin-bottom: 0.75rem;\n}\n.doc-header-col {\n display: flex;\n min-width: 0;\n flex-direction: column;\n justify-content: space-between;\n}\n.doc-header-left {\n padding-right: var(--doc-col-pad);\n}\n.doc-header-right {\n padding-left: var(--doc-col-pad);\n}\n.doc-header-right > p + p {\n margin-top: 0.125rem;\n}\n\n.doc-links {\n margin-top: 0.75rem;\n}\n.doc-links > p {\n margin-top: 0;\n color: var(--doc-ink-muted);\n}\n.doc-links a {\n color: inherit;\n}\n.doc-links em {\n color: var(--doc-ink-faint);\n}\n\n.doc-entry-body {\n min-width: 0;\n}\n\n/* Two-column grid placement (sidebar | main), used on every page incl. continuations */\n.doc-col-sidebar {\n grid-column-start: 1;\n grid-row-start: 1;\n padding-right: var(--doc-col-pad);\n}\n.doc-col-main {\n grid-column-start: 2;\n grid-row-start: 1;\n padding-left: var(--doc-col-pad);\n}\n\n.doc-list {\n list-style: disc;\n padding-left: 0.75rem;\n}\n.doc-em {\n font-style: normal;\n}\n.doc-hr {\n margin: 0.75rem 0;\n}\n\n/* Page frame (Tailwind shadow-lg + bg-white + text-black + flex column) */\n.doc-pages {\n display: flex;\n flex-direction: column;\n}\n.doc-page {\n position: relative;\n display: flex;\n flex-direction: column;\n background: #fff;\n color: #000;\n box-shadow:\n 0 10px 15px -3px rgb(0 0 0 / 0.1),\n 0 4px 6px -4px rgb(0 0 0 / 0.1);\n}\n","/* Screen preview — keep letter layout stable on mobile browsers. */\n#resume-print-target,\n#resume-print-target * {\n -webkit-text-size-adjust: none;\n text-size-adjust: none;\n}\n\n[data-resume-scale-root] {\n transform-origin: top left;\n}\n\n/* ResumeViewer chrome — the standalone component's own layout (toolbar +\n scroll viewport + scaled page stage). Tailwind-free; the package ships these\n classes so the viewer is self-styled. The neutral viewport background mirrors\n the old muted canvas; the page frames come from the document and paper tokens\n defined in tokens.css and document.css. */\n.resume-viewer {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n\n.resume-viewer-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n padding: 0.375rem 0.75rem;\n border-bottom: 1px solid rgb(0 0 0 / 0.08);\n background: #fff;\n flex: 0 0 auto;\n}\n\n.resume-viewer-pagecount {\n font-size: 0.8125rem;\n color: rgb(0 0 0 / 0.55);\n}\n\n.resume-viewer-controls {\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.resume-viewer-btn-group {\n display: flex;\n align-items: center;\n}\n\n.resume-viewer-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 2rem;\n min-width: 2rem;\n padding: 0 0.375rem;\n border: 0;\n border-radius: 0.375rem;\n background: transparent;\n color: rgb(0 0 0 / 0.7);\n font-size: 0.8125rem;\n cursor: pointer;\n}\n\n.resume-viewer-btn:hover:not(:disabled) {\n background: rgb(0 0 0 / 0.06);\n}\n\n.resume-viewer-btn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.resume-viewer-btn-active {\n background: rgb(0 0 0 / 0.08);\n color: rgb(0 0 0 / 0.9);\n}\n\n.resume-viewer-btn-text {\n padding: 0 0.625rem;\n}\n\n.resume-viewer-zoom-label {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n height: 2rem;\n width: 3rem;\n border: 0;\n border-radius: 0.375rem;\n background: transparent;\n color: rgb(0 0 0 / 0.55);\n font-size: 0.8125rem;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n}\n\n.resume-viewer-zoom-label:hover {\n background: rgb(0 0 0 / 0.06);\n}\n\n.resume-viewer-icon {\n width: 1rem;\n height: 1rem;\n}\n\n.resume-viewer-scroll {\n flex: 1 1 auto;\n min-height: 0;\n overflow: auto;\n background: rgb(244 244 245);\n}\n\n.resume-viewer-scroll-grab {\n cursor: grab;\n}\n\n.resume-viewer-scroll-grabbing {\n cursor: grabbing;\n}\n\n.resume-viewer-scroll-mobile {\n touch-action: none;\n user-select: none;\n}\n\n.resume-viewer-stage {\n margin-top: 1.5rem;\n margin-bottom: 1.5rem;\n padding-left: 1rem;\n padding-right: 1rem;\n}\n\n.resume-viewer-page-box {\n margin-left: auto;\n margin-right: auto;\n}\n\n.resume-viewer-scale-root {\n position: relative;\n}\n\n.resume-viewer-content {\n position: relative;\n display: flex;\n flex-direction: column;\n color: #000;\n}\n\n[data-slot=\"scroll-area-viewport\"][data-pan-active],\n.resume-viewer-scroll[data-pan-active] {\n background-color: color-mix(in oklch, var(--muted) 42%, transparent);\n}\n\n@media (prefers-reduced-motion: reduce) {\n [data-slot=\"scroll-area-viewport\"][data-pan-active],\n .resume-viewer-scroll[data-pan-active] {\n transition: none;\n }\n}\n\n#resume-print-target a,\n#resume-print-target button {\n touch-action: manipulation;\n}\n\n@media print {\n /* Body children are hidden/restored via JS (beforeprint/afterprint)\n to preserve <style>/<link>/<script> tags. */\n\n /* Hard isolation: while the resume's print clone exists, hide every other\n direct body child (other app windows, stray clones) regardless of JS\n hide-ordering across apps. Scoped to the clone's presence so it never\n affects another app's print. */\n body:has(#resume-print-clone) > :not(#resume-print-clone) {\n display: none !important;\n }\n\n /* The clone is a plain wrapper around the engine's real 8.5x11 page frames\n (a direct child of body — no positioning needed). */\n #resume-print-clone {\n color: black !important;\n background: white !important;\n }\n\n /* Frames stack with a screen-only gap; remove it so each maps 1:1 to a page. */\n #resume-print-clone > div {\n gap: 0 !important;\n }\n\n [data-resume-page] {\n box-shadow: none !important;\n break-after: page;\n break-inside: avoid;\n }\n [data-resume-page]:last-child {\n break-after: auto;\n }\n\n @page {\n size: letter;\n margin: 0;\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ReactNode, ComponentType, RefObject } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mounted as the MDX `wrapper`, so it receives [Header, Columns, Footer].
|
|
7
|
+
* Measures each column's blocks in a hidden layer, packs them into pages, and
|
|
8
|
+
* renders physical page frames. Reports pageCount up to ResumeApp.
|
|
9
|
+
*/
|
|
10
|
+
declare function PaginatedResume({ children }: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
}): react_jsx_runtime.JSX.Element;
|
|
13
|
+
|
|
14
|
+
declare function Header({ children, meta, }: {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Use the universal meta grid (left label column + content), the same track
|
|
18
|
+
* widths as <Section> and <Entry>, so the header aligns with everything
|
|
19
|
+
* below it. The default is the resume's sidebar|main split.
|
|
20
|
+
*/
|
|
21
|
+
meta?: boolean;
|
|
22
|
+
}): react_jsx_runtime.JSX.Element;
|
|
23
|
+
declare function HeaderLeft({ children }: {
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
}): react_jsx_runtime.JSX.Element;
|
|
26
|
+
declare function HeaderRight({ children }: {
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
}): react_jsx_runtime.JSX.Element;
|
|
29
|
+
declare function Links({ children }: {
|
|
30
|
+
children: React.ReactNode;
|
|
31
|
+
}): react_jsx_runtime.JSX.Element;
|
|
32
|
+
declare function Group({ children }: {
|
|
33
|
+
children: React.ReactNode;
|
|
34
|
+
}): react_jsx_runtime.JSX.Element;
|
|
35
|
+
/**
|
|
36
|
+
* A record row (award, media mention, talk, …): a `year | role` meta column on
|
|
37
|
+
* the left and the linked title on the right. Each Entry is a single pagination
|
|
38
|
+
* block, so render long CV lists as a flat sequence of Entry elements (NOT one
|
|
39
|
+
* <ul>) so pages can break between them.
|
|
40
|
+
*/
|
|
41
|
+
declare function Entry({ year, role, children, }: {
|
|
42
|
+
year?: string;
|
|
43
|
+
role?: string;
|
|
44
|
+
children: React.ReactNode;
|
|
45
|
+
}): react_jsx_runtime.JSX.Element;
|
|
46
|
+
/** A thin full-width divider — the CV uses one under the header band. */
|
|
47
|
+
declare function Rule(): react_jsx_runtime.JSX.Element;
|
|
48
|
+
/**
|
|
49
|
+
* Editorial section: the label sits in the left meta column (aligned with the
|
|
50
|
+
* `year | role` column of Entry rows) and the content fills the right column,
|
|
51
|
+
* so prose sections share one left edge with the record rows below. The
|
|
52
|
+
* .doc-section margin keeps every section on the same vertical rhythm as the
|
|
53
|
+
* record-section headings (h3). One pagination block — keep a body under a page.
|
|
54
|
+
*/
|
|
55
|
+
declare function Section({ label, children }: {
|
|
56
|
+
label: string;
|
|
57
|
+
children: React.ReactNode;
|
|
58
|
+
}): react_jsx_runtime.JSX.Element;
|
|
59
|
+
declare function Footer({ children }: {
|
|
60
|
+
children: React.ReactNode;
|
|
61
|
+
}): react_jsx_runtime.JSX.Element;
|
|
62
|
+
declare function Columns({ children }: {
|
|
63
|
+
children: React.ReactNode;
|
|
64
|
+
}): react_jsx_runtime.JSX.Element;
|
|
65
|
+
declare function Sidebar({ children }: {
|
|
66
|
+
children: React.ReactNode;
|
|
67
|
+
}): react_jsx_runtime.JSX.Element;
|
|
68
|
+
declare function Main({ children }: {
|
|
69
|
+
children: React.ReactNode;
|
|
70
|
+
}): react_jsx_runtime.JSX.Element;
|
|
71
|
+
declare const resumeMdxComponents: {
|
|
72
|
+
ResumeDocument: typeof PaginatedResume;
|
|
73
|
+
Header: typeof Header;
|
|
74
|
+
HeaderLeft: typeof HeaderLeft;
|
|
75
|
+
HeaderRight: typeof HeaderRight;
|
|
76
|
+
Links: typeof Links;
|
|
77
|
+
Group: typeof Group;
|
|
78
|
+
Entry: typeof Entry;
|
|
79
|
+
Rule: typeof Rule;
|
|
80
|
+
Section: typeof Section;
|
|
81
|
+
Footer: typeof Footer;
|
|
82
|
+
Columns: typeof Columns;
|
|
83
|
+
Sidebar: typeof Sidebar;
|
|
84
|
+
Main: typeof Main;
|
|
85
|
+
h1: ({ children, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
86
|
+
h3: ({ children, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
87
|
+
h4: ({ children, ...props }: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
88
|
+
p: ({ children, ...props }: React.HTMLAttributes<HTMLParagraphElement>) => react_jsx_runtime.JSX.Element;
|
|
89
|
+
ul: ({ children, ...props }: React.HTMLAttributes<HTMLUListElement>) => react_jsx_runtime.JSX.Element;
|
|
90
|
+
li: ({ children, ...props }: React.HTMLAttributes<HTMLLIElement>) => react_jsx_runtime.JSX.Element;
|
|
91
|
+
strong: ({ children, ...props }: React.HTMLAttributes<HTMLElement>) => react_jsx_runtime.JSX.Element;
|
|
92
|
+
em: ({ children, ...props }: React.HTMLAttributes<HTMLElement>) => react_jsx_runtime.JSX.Element;
|
|
93
|
+
a: ({ children, href, target, rel, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement>) => react_jsx_runtime.JSX.Element;
|
|
94
|
+
hr: (_props: React.HTMLAttributes<HTMLHRElement>) => react_jsx_runtime.JSX.Element;
|
|
95
|
+
h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
96
|
+
h5: (props: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
97
|
+
h6: (props: React.HTMLAttributes<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
|
|
98
|
+
ol: (props: React.HTMLAttributes<HTMLOListElement>) => react_jsx_runtime.JSX.Element;
|
|
99
|
+
blockquote: (props: React.HTMLAttributes<HTMLElement>) => react_jsx_runtime.JSX.Element;
|
|
100
|
+
code: (props: React.HTMLAttributes<HTMLElement>) => react_jsx_runtime.JSX.Element;
|
|
101
|
+
pre: (props: React.HTMLAttributes<HTMLPreElement>) => react_jsx_runtime.JSX.Element;
|
|
102
|
+
img: (props: React.ImgHTMLAttributes<HTMLImageElement>) => react_jsx_runtime.JSX.Element;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** PaginatedResume reports its computed page count up to the host (ResumeViewer). */
|
|
106
|
+
declare const PaginationReportContext: react.Context<((pageCount: number) => void) | null>;
|
|
107
|
+
declare function usePaginationReport(): (pageCount: number) => void;
|
|
108
|
+
/** Optional font-family hint — changes trigger re-measure/re-pagination. */
|
|
109
|
+
declare const ResumeFontFamilyContext: react.Context<string | undefined>;
|
|
110
|
+
declare const useResumeFontFamily: () => string | undefined;
|
|
111
|
+
|
|
112
|
+
declare const PAGE: {
|
|
113
|
+
readonly widthPx: number;
|
|
114
|
+
readonly heightPx: number;
|
|
115
|
+
readonly padXPx: number;
|
|
116
|
+
readonly padYPx: number;
|
|
117
|
+
readonly gapPx: 32;
|
|
118
|
+
};
|
|
119
|
+
declare const BLOCK_GAP_PX = 6;
|
|
120
|
+
|
|
121
|
+
interface Block {
|
|
122
|
+
id: string;
|
|
123
|
+
/** Measured px (offsetHeight + vertical margins). */
|
|
124
|
+
height: number;
|
|
125
|
+
/** Section headings: don't leave them orphaned at a page bottom. */
|
|
126
|
+
keepWithNext: boolean;
|
|
127
|
+
}
|
|
128
|
+
type ColumnKey = 'sidebar' | 'main';
|
|
129
|
+
interface PackInput {
|
|
130
|
+
columns: Record<ColumnKey, Block[]>;
|
|
131
|
+
/** Usable content height for a given page index; index 0 may be shorter (header band). */
|
|
132
|
+
pageUsableHeight: (pageIndex: number) => number;
|
|
133
|
+
/**
|
|
134
|
+
* Vertical gap rendered between consecutive blocks in a column (the flex
|
|
135
|
+
* `gap`). Block heights are measured individually, so the packer must add
|
|
136
|
+
* this back or pages overflow once they hold many blocks. Defaults to 0.
|
|
137
|
+
*/
|
|
138
|
+
blockGap?: number;
|
|
139
|
+
}
|
|
140
|
+
interface PackResult {
|
|
141
|
+
pageCount: number;
|
|
142
|
+
pageOf: Record<ColumnKey, Record<string, number>>;
|
|
143
|
+
/** Blocks taller than a full page — placed alone, allowed to overflow. */
|
|
144
|
+
oversized: string[];
|
|
145
|
+
}
|
|
146
|
+
/** Assign measured blocks to pages per column. Pure: no DOM. */
|
|
147
|
+
declare function packIntoPages(input: PackInput): PackResult;
|
|
148
|
+
|
|
149
|
+
interface ResumeViewerProps {
|
|
150
|
+
/** Compiled MDX component for the document (rendered as <Content />). */
|
|
151
|
+
Content: ComponentType;
|
|
152
|
+
/** Override the MDX component map; defaults to resumeMdxComponents. */
|
|
153
|
+
components?: Record<string, ComponentType<unknown>>;
|
|
154
|
+
/** Font-family hint; a change re-measures/re-paginates. */
|
|
155
|
+
fontFamily?: string;
|
|
156
|
+
/** Whether this viewer owns global print + keyboard shortcuts. Default true. */
|
|
157
|
+
isActive?: boolean;
|
|
158
|
+
/** Suggested PDF filename (becomes document.title during print). */
|
|
159
|
+
pdfFilename?: string;
|
|
160
|
+
/** Called after a successful copy-to-clipboard (host shows its own toast). */
|
|
161
|
+
onCopy?: () => void;
|
|
162
|
+
/** Called when copy-to-clipboard fails. */
|
|
163
|
+
onError?: (error: unknown) => void;
|
|
164
|
+
/** Extra className on the root element. */
|
|
165
|
+
className?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Host content injected at the START of the toolbar, before the page count.
|
|
168
|
+
* Use this to add e.g. a document-variant toggle without re-implementing the
|
|
169
|
+
* viewport. Optional and backward-compatible.
|
|
170
|
+
*/
|
|
171
|
+
toolbarStart?: ReactNode;
|
|
172
|
+
/**
|
|
173
|
+
* Host content injected at the END of the toolbar, after the built-in
|
|
174
|
+
* controls. Use this to add e.g. a "view source" button. Optional and
|
|
175
|
+
* backward-compatible.
|
|
176
|
+
*/
|
|
177
|
+
toolbarEnd?: ReactNode;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
declare function ResumeViewer({ Content, components, fontFamily, isActive, pdfFilename, onCopy, onError, className, toolbarStart, toolbarEnd, }: ResumeViewerProps): react_jsx_runtime.JSX.Element;
|
|
181
|
+
|
|
182
|
+
/** True when the viewport is narrow (<= 768px). SSR-safe (defaults false). */
|
|
183
|
+
declare function useIsMobile(breakpointPx?: number): boolean;
|
|
184
|
+
|
|
185
|
+
declare const SCALE_STEP = 0.1;
|
|
186
|
+
declare const MIN_SCALE = 0.25;
|
|
187
|
+
declare const MAX_SCALE = 2;
|
|
188
|
+
interface UseResumeViewportOptions {
|
|
189
|
+
/** Scroll viewport element (the host attaches this to its scrollable region). */
|
|
190
|
+
scrollRef: RefObject<HTMLDivElement | null>;
|
|
191
|
+
/** Element holding the rendered page frames (the print/copy target). */
|
|
192
|
+
contentRef: RefObject<HTMLDivElement | null>;
|
|
193
|
+
/** Narrow-viewport flag — drives touch pan/pinch vs mouse drag. */
|
|
194
|
+
isMobile: boolean;
|
|
195
|
+
/** Whether this viewport owns global print + keyboard shortcuts. */
|
|
196
|
+
isActive: boolean;
|
|
197
|
+
/** Suggested PDF filename (becomes document.title during print). */
|
|
198
|
+
pdfFilename?: string;
|
|
199
|
+
/** Called after a successful copy-to-clipboard. */
|
|
200
|
+
onCopy?: () => void;
|
|
201
|
+
/** Called when copy-to-clipboard fails. */
|
|
202
|
+
onError?: (error: unknown) => void;
|
|
203
|
+
}
|
|
204
|
+
interface UseResumeViewport {
|
|
205
|
+
/** Current page count (reported by the pagination engine via setPageCount). */
|
|
206
|
+
pageCount: number;
|
|
207
|
+
/** Reporter wired into PaginationReportContext. */
|
|
208
|
+
setPageCount: (n: number) => void;
|
|
209
|
+
/** The scale actually applied to the page stage (fit-to-width or manual zoom). */
|
|
210
|
+
effectiveScale: number;
|
|
211
|
+
/** Whether fit-to-width mode is active. */
|
|
212
|
+
isFitToWidth: boolean;
|
|
213
|
+
/** Total stacked page height (unscaled px) — for sizing the page box. */
|
|
214
|
+
totalHeight: number;
|
|
215
|
+
handleZoomIn: () => void;
|
|
216
|
+
handleZoomOut: () => void;
|
|
217
|
+
handleActualSize: () => void;
|
|
218
|
+
handleFitToWidth: () => void;
|
|
219
|
+
requestPrint: () => void;
|
|
220
|
+
handleCopyText: () => Promise<void>;
|
|
221
|
+
/** Lower/upper zoom bounds (for disabling +/- controls). */
|
|
222
|
+
minScale: number;
|
|
223
|
+
maxScale: number;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Wire the resume viewport behaviour to host-supplied refs and return the
|
|
227
|
+
* derived state + action handlers. The host renders the scaled page stage; the
|
|
228
|
+
* pagination engine inside it reports its page count through `setPageCount`.
|
|
229
|
+
*/
|
|
230
|
+
declare function useResumeViewport({ scrollRef, contentRef, isMobile, isActive, pdfFilename, onCopy, onError, }: UseResumeViewportOptions): UseResumeViewport;
|
|
231
|
+
|
|
232
|
+
export { BLOCK_GAP_PX, type Block, type ColumnKey, Columns, Entry, Footer, Group, Header, MAX_SCALE, MIN_SCALE, Main, PAGE, type PackInput, type PackResult, PaginatedResume, PaginationReportContext, ResumeFontFamilyContext, ResumeViewer, type ResumeViewerProps, Rule, SCALE_STEP, Section, Sidebar, type UseResumeViewport, type UseResumeViewportOptions, packIntoPages, resumeMdxComponents, usePaginationReport, useResumeFontFamily, useIsMobile as useResumeIsMobile, useResumeViewport };
|