@hadoku/resume-bot 0.0.0-stage → 3.14.16
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/README.md +135 -3
- package/dist/App.d.ts +9 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/ChatInterface-mHtxUGpp.js +128 -0
- package/dist/ChatInterface-mHtxUGpp.js.map +1 -0
- package/dist/ResumeViewer-C-uxZ-7E.js +296 -0
- package/dist/ResumeViewer-C-uxZ-7E.js.map +1 -0
- package/dist/builder/BlockCard.d.ts +15 -0
- package/dist/builder/BlockCard.d.ts.map +1 -0
- package/dist/builder/BuilderApp.d.ts +3 -0
- package/dist/builder/BuilderApp.d.ts.map +1 -0
- package/dist/builder/api.d.ts +37 -0
- package/dist/builder/api.d.ts.map +1 -0
- package/dist/builder/entry.d.ts +8 -0
- package/dist/builder/entry.d.ts.map +1 -0
- package/dist/builder/useBuilderAuth.d.ts +10 -0
- package/dist/builder/useBuilderAuth.d.ts.map +1 -0
- package/dist/builder.js +537 -0
- package/dist/builder.js.map +1 -0
- package/dist/components/ChatInterface.d.ts +10 -0
- package/dist/components/ChatInterface.d.ts.map +1 -0
- package/dist/components/ResumeDocument.d.ts +30 -0
- package/dist/components/ResumeDocument.d.ts.map +1 -0
- package/dist/components/ResumeViewer.d.ts +12 -0
- package/dist/components/ResumeViewer.d.ts.map +1 -0
- package/dist/entry-BTJjyohQ.js +154 -0
- package/dist/entry-BTJjyohQ.js.map +1 -0
- package/dist/entry.d.ts +22 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/markdown-vendor-61sRGACd.js +10510 -0
- package/dist/markdown-vendor-61sRGACd.js.map +1 -0
- package/dist/rehype-vendor-C_Q-vwLE.js +5647 -0
- package/dist/rehype-vendor-C_Q-vwLE.js.map +1 -0
- package/dist/services/api.d.ts +62 -0
- package/dist/services/api.d.ts.map +1 -0
- package/dist/style.css +1 -0
- package/dist/worker/application-extras.d.ts +56 -0
- package/dist/worker/application-extras.d.ts.map +1 -0
- package/dist/worker/blocks.d.ts +12 -0
- package/dist/worker/blocks.d.ts.map +1 -0
- package/dist/worker/builder.d.ts +33 -0
- package/dist/worker/builder.d.ts.map +1 -0
- package/dist/worker/constants.d.ts +39 -0
- package/dist/worker/constants.d.ts.map +1 -0
- package/dist/worker/contact.d.ts +34 -0
- package/dist/worker/contact.d.ts.map +1 -0
- package/dist/worker/cover-letter.d.ts +16 -0
- package/dist/worker/cover-letter.d.ts.map +1 -0
- package/dist/worker/index.d.ts +38 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/llm.d.ts +77 -0
- package/dist/worker/llm.d.ts.map +1 -0
- package/dist/worker/pdf.d.ts +46 -0
- package/dist/worker/pdf.d.ts.map +1 -0
- package/dist/worker/rate-limit.d.ts +10 -0
- package/dist/worker/rate-limit.d.ts.map +1 -0
- package/dist/worker/resume.d.ts +33 -0
- package/dist/worker/resume.d.ts.map +1 -0
- package/dist/worker/skeleton.d.ts +73 -0
- package/dist/worker/skeleton.d.ts.map +1 -0
- package/dist/worker/tailored-resume.d.ts +31 -0
- package/dist/worker/tailored-resume.d.ts.map +1 -0
- package/dist/worker/typography.d.ts +12 -0
- package/dist/worker/typography.d.ts.map +1 -0
- package/dist/worker/variants.d.ts +51 -0
- package/dist/worker/variants.d.ts.map +1 -0
- package/dist/worker.js +42508 -0
- package/package.json +43 -4
package/dist/builder.js
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
import { jsxs as c, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { createRoot as Z } from "react-dom/client";
|
|
3
|
+
import { logger as E } from "@wolffm/logger/client";
|
|
4
|
+
import { useState as d, useRef as ee, useEffect as W, useMemo as D } from "react";
|
|
5
|
+
class H extends Error {
|
|
6
|
+
constructor(i, l) {
|
|
7
|
+
super(i), this.status = l, this.name = "BuilderApiError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
let X = "";
|
|
11
|
+
function re(e) {
|
|
12
|
+
X = e.replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
async function j(e, i) {
|
|
15
|
+
const l = await fetch(`${X}/builder${e}`, {
|
|
16
|
+
...i,
|
|
17
|
+
credentials: "include",
|
|
18
|
+
headers: { "Content-Type": "application/json", ...i?.headers ?? {} }
|
|
19
|
+
});
|
|
20
|
+
if (!l.ok) {
|
|
21
|
+
let s = `${l.status}`;
|
|
22
|
+
try {
|
|
23
|
+
const u = await l.json();
|
|
24
|
+
s = u.message ? `${u.error}: ${u.message}` : u.error ?? s;
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
throw new H(s, l.status);
|
|
28
|
+
}
|
|
29
|
+
return await l.json();
|
|
30
|
+
}
|
|
31
|
+
function ae() {
|
|
32
|
+
return j("/blocks");
|
|
33
|
+
}
|
|
34
|
+
function oe(e) {
|
|
35
|
+
return j(`/blocks/${encodeURIComponent(e.id)}`, {
|
|
36
|
+
method: "PUT",
|
|
37
|
+
body: JSON.stringify(e)
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function te(e) {
|
|
41
|
+
return j(`/blocks/${encodeURIComponent(e)}`, { method: "DELETE" });
|
|
42
|
+
}
|
|
43
|
+
function ne(e, i) {
|
|
44
|
+
return j(`/feedback/${encodeURIComponent(e)}`, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
body: JSON.stringify({ text: i })
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const le = [
|
|
50
|
+
"experience",
|
|
51
|
+
"project",
|
|
52
|
+
"skills",
|
|
53
|
+
"education",
|
|
54
|
+
"summary",
|
|
55
|
+
"header"
|
|
56
|
+
];
|
|
57
|
+
function M({
|
|
58
|
+
block: e,
|
|
59
|
+
feedback: i,
|
|
60
|
+
existingIds: l,
|
|
61
|
+
isNew: s = !1,
|
|
62
|
+
onSave: u,
|
|
63
|
+
onDelete: p,
|
|
64
|
+
onCancel: O,
|
|
65
|
+
onFeedback: R,
|
|
66
|
+
onTagClick: I
|
|
67
|
+
}) {
|
|
68
|
+
const [b, m] = d(e), [y, _] = d(e.tags.join(" ")), [N, g] = d(!1), [B, f] = d(null), [A, v] = d(i?.text ?? ""), [F, k] = d(""), x = ee(void 0);
|
|
69
|
+
W(() => {
|
|
70
|
+
s || (m(e), _(e.tags.join(" ")));
|
|
71
|
+
}, [e, s]);
|
|
72
|
+
const w = s || JSON.stringify({ ...b, tags: C(y) }) !== JSON.stringify(e);
|
|
73
|
+
function C(o) {
|
|
74
|
+
return [...new Set(o.split(/[\s,]+/).filter(Boolean))];
|
|
75
|
+
}
|
|
76
|
+
const T = s && (!/^[a-z0-9][a-z0-9-]*$/.test(b.id) || l.includes(b.id));
|
|
77
|
+
async function S() {
|
|
78
|
+
g(!0), f(null);
|
|
79
|
+
try {
|
|
80
|
+
await u({ ...b, tags: C(y) });
|
|
81
|
+
} catch (o) {
|
|
82
|
+
f(o instanceof Error ? o.message : "Save failed");
|
|
83
|
+
} finally {
|
|
84
|
+
g(!1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function $() {
|
|
88
|
+
if (p && confirm(`Delete block "${e.id}"? This removes it from the live resume.`)) {
|
|
89
|
+
g(!0);
|
|
90
|
+
try {
|
|
91
|
+
await p();
|
|
92
|
+
} catch (o) {
|
|
93
|
+
f(o instanceof Error ? o.message : "Delete failed"), g(!1);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function L(o) {
|
|
98
|
+
v(o), k("typing…"), clearTimeout(x.current), x.current = setTimeout(() => {
|
|
99
|
+
R(e.id, o).then(() => k(o.trim() ? "saved ✓" : "")).catch(() => k("save failed"));
|
|
100
|
+
}, 600);
|
|
101
|
+
}
|
|
102
|
+
return /* @__PURE__ */ c(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
className: `rb-block${i ? " rb-block--has-feedback" : ""}${w ? " rb-block--dirty" : ""}`,
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ c("div", { className: "rb-block__row", children: [
|
|
108
|
+
s ? /* @__PURE__ */ a(
|
|
109
|
+
"input",
|
|
110
|
+
{
|
|
111
|
+
className: "rb-block__id-input",
|
|
112
|
+
placeholder: "block-id (kebab-case)",
|
|
113
|
+
value: b.id,
|
|
114
|
+
onChange: (o) => m({ ...b, id: o.target.value })
|
|
115
|
+
}
|
|
116
|
+
) : /* @__PURE__ */ a("span", { className: "rb-block__id", children: b.id }),
|
|
117
|
+
/* @__PURE__ */ a(
|
|
118
|
+
"select",
|
|
119
|
+
{
|
|
120
|
+
className: "rb-block__type",
|
|
121
|
+
value: b.type,
|
|
122
|
+
onChange: (o) => m({ ...b, type: o.target.value }),
|
|
123
|
+
children: le.map((o) => /* @__PURE__ */ a("option", { value: o, children: o }, o))
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
/* @__PURE__ */ c(
|
|
127
|
+
"label",
|
|
128
|
+
{
|
|
129
|
+
className: "rb-block__prio",
|
|
130
|
+
title: "Priority — how strongly you want this block in a tailored resume. Higher sorts first; a ranking hint, not a hard rule.",
|
|
131
|
+
children: [
|
|
132
|
+
"prio",
|
|
133
|
+
/* @__PURE__ */ a(
|
|
134
|
+
"input",
|
|
135
|
+
{
|
|
136
|
+
type: "number",
|
|
137
|
+
min: 0,
|
|
138
|
+
max: 10,
|
|
139
|
+
value: b.priority,
|
|
140
|
+
onChange: (o) => m({ ...b, priority: Number(o.target.value) })
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
] }),
|
|
147
|
+
/* @__PURE__ */ a(
|
|
148
|
+
"input",
|
|
149
|
+
{
|
|
150
|
+
className: "rb-block__title",
|
|
151
|
+
placeholder: "title (review label — not rendered into the resume)",
|
|
152
|
+
value: b.title,
|
|
153
|
+
onChange: (o) => m({ ...b, title: o.target.value })
|
|
154
|
+
}
|
|
155
|
+
),
|
|
156
|
+
/* @__PURE__ */ a("div", { className: "rb-block__chips", children: C(y).map((o) => /* @__PURE__ */ a(
|
|
157
|
+
"button",
|
|
158
|
+
{
|
|
159
|
+
type: "button",
|
|
160
|
+
className: `rb-tag rb-tag--${U(o)}`,
|
|
161
|
+
onClick: () => I(o),
|
|
162
|
+
title: "filter by this tag",
|
|
163
|
+
children: o
|
|
164
|
+
},
|
|
165
|
+
o
|
|
166
|
+
)) }),
|
|
167
|
+
/* @__PURE__ */ a(
|
|
168
|
+
"input",
|
|
169
|
+
{
|
|
170
|
+
className: "rb-block__tags-input",
|
|
171
|
+
placeholder: "tags (space or comma separated, e.g. tech:python story:scale)",
|
|
172
|
+
value: y,
|
|
173
|
+
onChange: (o) => _(o.target.value)
|
|
174
|
+
}
|
|
175
|
+
),
|
|
176
|
+
/* @__PURE__ */ a(
|
|
177
|
+
"textarea",
|
|
178
|
+
{
|
|
179
|
+
className: "rb-block__content",
|
|
180
|
+
rows: 8,
|
|
181
|
+
placeholder: "content (markdown)",
|
|
182
|
+
value: b.content,
|
|
183
|
+
onChange: (o) => m({ ...b, content: o.target.value })
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
/* @__PURE__ */ c("div", { className: "rb-block__actions", children: [
|
|
187
|
+
/* @__PURE__ */ a(
|
|
188
|
+
"button",
|
|
189
|
+
{
|
|
190
|
+
type: "button",
|
|
191
|
+
className: "rb-builder__btn rb-builder__btn--primary",
|
|
192
|
+
onClick: () => {
|
|
193
|
+
S();
|
|
194
|
+
},
|
|
195
|
+
disabled: N || !w || T,
|
|
196
|
+
children: N ? "Saving…" : s ? "Create" : "Save"
|
|
197
|
+
}
|
|
198
|
+
),
|
|
199
|
+
s ? /* @__PURE__ */ a("button", { type: "button", className: "rb-builder__btn", onClick: O, children: "Cancel" }) : /* @__PURE__ */ a(
|
|
200
|
+
"button",
|
|
201
|
+
{
|
|
202
|
+
type: "button",
|
|
203
|
+
className: "rb-builder__btn rb-builder__btn--danger",
|
|
204
|
+
onClick: () => {
|
|
205
|
+
$();
|
|
206
|
+
},
|
|
207
|
+
disabled: N,
|
|
208
|
+
children: "Delete"
|
|
209
|
+
}
|
|
210
|
+
),
|
|
211
|
+
T && /* @__PURE__ */ a("span", { className: "rb-block__hint", children: "id must be unique kebab-case" }),
|
|
212
|
+
B && /* @__PURE__ */ a("span", { className: "rb-block__hint rb-block__hint--error", children: B })
|
|
213
|
+
] }),
|
|
214
|
+
!s && /* @__PURE__ */ c("div", { className: "rb-block__feedback", children: [
|
|
215
|
+
/* @__PURE__ */ a(
|
|
216
|
+
"textarea",
|
|
217
|
+
{
|
|
218
|
+
rows: 2,
|
|
219
|
+
placeholder: "review note (autosaves)…",
|
|
220
|
+
value: A,
|
|
221
|
+
onChange: (o) => L(o.target.value)
|
|
222
|
+
}
|
|
223
|
+
),
|
|
224
|
+
/* @__PURE__ */ a("span", { className: "rb-block__fb-status", children: F })
|
|
225
|
+
] })
|
|
226
|
+
]
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
var ie = "https://hadoku.me/prefs", Y = "anon", K = "__hadokuWhoami", se = "sess:", ce = "unscoped";
|
|
231
|
+
function q(e) {
|
|
232
|
+
if (!e || e.valid === !1)
|
|
233
|
+
return { userId: Y, userType: "public", scope: "anon" };
|
|
234
|
+
const i = e.userType === "admin" || e.userType === "wife" || e.userType === "service" || e.userType === "friend" || e.userType === "member" || e.userType === "public" ? e.userType : "public", l = typeof e.name == "string" ? e.name : null;
|
|
235
|
+
return typeof e.userId == "string" && e.userId ? { userId: e.userId, userType: i, name: l, scope: "user" } : typeof e.sessionId == "string" && e.sessionId ? {
|
|
236
|
+
userId: `${se}${e.sessionId}`,
|
|
237
|
+
userType: i,
|
|
238
|
+
name: l,
|
|
239
|
+
scope: "session"
|
|
240
|
+
} : { userId: ce, userType: i, name: l, scope: "none" };
|
|
241
|
+
}
|
|
242
|
+
async function G(e, i) {
|
|
243
|
+
const l = {};
|
|
244
|
+
i && (l["X-User-Key"] = i);
|
|
245
|
+
try {
|
|
246
|
+
const s = await fetch(e, {
|
|
247
|
+
method: "GET",
|
|
248
|
+
headers: l,
|
|
249
|
+
credentials: "include",
|
|
250
|
+
cache: "no-store"
|
|
251
|
+
});
|
|
252
|
+
return s.ok ? await s.json() : null;
|
|
253
|
+
} catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function de() {
|
|
258
|
+
const e = globalThis.location;
|
|
259
|
+
return e && (e.protocol === "http:" || e.protocol === "https:") ? "/session/whoami" : `${ie.replace(/\/prefs$/, "")}/session/whoami`;
|
|
260
|
+
}
|
|
261
|
+
async function be(e = {}) {
|
|
262
|
+
const i = e.whoamiUrl ?? de();
|
|
263
|
+
if (e.userKey)
|
|
264
|
+
return q(await G(i, e.userKey));
|
|
265
|
+
const l = globalThis;
|
|
266
|
+
let s = l[K];
|
|
267
|
+
s || (s = G(i), l[K] = s);
|
|
268
|
+
try {
|
|
269
|
+
return q(await s);
|
|
270
|
+
} catch {
|
|
271
|
+
return { userId: Y, userType: "public", scope: "anon" };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function P() {
|
|
275
|
+
if (typeof window > "u") return;
|
|
276
|
+
const e = encodeURIComponent(window.location.pathname + window.location.search);
|
|
277
|
+
window.location.replace(`/auth?return=${e}`);
|
|
278
|
+
}
|
|
279
|
+
function ue() {
|
|
280
|
+
const [e, i] = d("checking"), [l, s] = d(null);
|
|
281
|
+
return W(() => {
|
|
282
|
+
let u = !1;
|
|
283
|
+
return be().then((p) => {
|
|
284
|
+
if (!u) {
|
|
285
|
+
if (p.userType === "admin") {
|
|
286
|
+
s(p.name ?? null), i("authorized");
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
E.info("[builder] not admin, redirecting to sign in", { userType: p.userType }), i("redirecting"), P();
|
|
290
|
+
}
|
|
291
|
+
}).catch((p) => {
|
|
292
|
+
u || (E.error("[builder] whoami failed", {
|
|
293
|
+
error: p instanceof Error ? p.message : String(p)
|
|
294
|
+
}), i("redirecting"), P());
|
|
295
|
+
}), () => {
|
|
296
|
+
u = !0;
|
|
297
|
+
};
|
|
298
|
+
}, []), { status: e, name: l };
|
|
299
|
+
}
|
|
300
|
+
const pe = [
|
|
301
|
+
"experience",
|
|
302
|
+
"project",
|
|
303
|
+
"skills",
|
|
304
|
+
"education",
|
|
305
|
+
"summary",
|
|
306
|
+
"header"
|
|
307
|
+
];
|
|
308
|
+
function U(e) {
|
|
309
|
+
return e.startsWith("tech:") ? "tech" : e.startsWith("layer:") ? "layer" : e.startsWith("story:") ? "story" : "plain";
|
|
310
|
+
}
|
|
311
|
+
function he() {
|
|
312
|
+
return { id: "", type: "experience", tags: [], title: "", content: "", priority: 5 };
|
|
313
|
+
}
|
|
314
|
+
function me() {
|
|
315
|
+
const { status: e, name: i } = ue(), [l, s] = d([]), [u, p] = d({}), [O, R] = d(!0), [I, b] = d(null), [m, y] = d(""), [_, N] = d(""), [g, B] = d(/* @__PURE__ */ new Set()), [f, A] = d(!0), [v, F] = d("order"), [k, x] = d(null);
|
|
316
|
+
W(() => {
|
|
317
|
+
if (e !== "authorized") return;
|
|
318
|
+
let r = !1;
|
|
319
|
+
return ae().then((t) => {
|
|
320
|
+
r || (s(t.blocks), p(t.feedback));
|
|
321
|
+
}).catch((t) => {
|
|
322
|
+
if (r) return;
|
|
323
|
+
if (t instanceof H && (t.status === 401 || t.status === 403)) {
|
|
324
|
+
P();
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
const n = t instanceof Error ? t.message : "Failed to load blocks";
|
|
328
|
+
b(n), E.error("[builder] load failed", { error: n });
|
|
329
|
+
}).finally(() => {
|
|
330
|
+
r || R(!1);
|
|
331
|
+
}), () => {
|
|
332
|
+
r = !0;
|
|
333
|
+
};
|
|
334
|
+
}, [e]);
|
|
335
|
+
const w = D(() => {
|
|
336
|
+
const r = /* @__PURE__ */ new Map();
|
|
337
|
+
for (const t of l) for (const n of t.tags) r.set(n, (r.get(n) ?? 0) + 1);
|
|
338
|
+
return r;
|
|
339
|
+
}, [l]), C = D(
|
|
340
|
+
() => [...w.keys()].sort(
|
|
341
|
+
(r, t) => U(r).localeCompare(U(t)) || r.localeCompare(t)
|
|
342
|
+
),
|
|
343
|
+
[w]
|
|
344
|
+
), T = D(() => {
|
|
345
|
+
const r = m.trim().toLowerCase();
|
|
346
|
+
let t = l.filter((n) => {
|
|
347
|
+
if (_ && n.type !== _ || r && !(n.id + n.title + n.content).toLowerCase().includes(r)) return !1;
|
|
348
|
+
if (g.size) {
|
|
349
|
+
const h = [...g].filter((z) => n.tags.includes(z)).length;
|
|
350
|
+
if (f ? h !== g.size : h === 0) return !1;
|
|
351
|
+
}
|
|
352
|
+
return !0;
|
|
353
|
+
});
|
|
354
|
+
return v === "priority" ? t = [...t].sort((n, h) => h.priority - n.priority) : v === "type" ? t = [...t].sort((n, h) => n.type.localeCompare(h.type)) : v === "feedback" && (t = [...t].sort((n, h) => (u[h.id] ? 1 : 0) - (u[n.id] ? 1 : 0))), t;
|
|
355
|
+
}, [l, m, _, g, f, v, u]);
|
|
356
|
+
function S(r) {
|
|
357
|
+
B((t) => {
|
|
358
|
+
const n = new Set(t);
|
|
359
|
+
return n.has(r) ? n.delete(r) : n.add(r), n;
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
async function $(r, t) {
|
|
363
|
+
const { block: n } = await oe(r);
|
|
364
|
+
s((h) => {
|
|
365
|
+
const z = h.findIndex((V) => V.id === n.id);
|
|
366
|
+
if (z === -1) return [...h, n];
|
|
367
|
+
const J = [...h];
|
|
368
|
+
return J[z] = n, J;
|
|
369
|
+
}), t && x(null);
|
|
370
|
+
}
|
|
371
|
+
async function L(r) {
|
|
372
|
+
await te(r), s((t) => t.filter((n) => n.id !== r));
|
|
373
|
+
}
|
|
374
|
+
async function o(r, t) {
|
|
375
|
+
const n = await ne(r, t);
|
|
376
|
+
p(n.feedback);
|
|
377
|
+
}
|
|
378
|
+
function Q() {
|
|
379
|
+
const r = new Blob([JSON.stringify(l, null, 2)], { type: "application/json" }), t = URL.createObjectURL(r), n = document.createElement("a");
|
|
380
|
+
n.href = t, n.download = "blocks.json", n.click(), URL.revokeObjectURL(t);
|
|
381
|
+
}
|
|
382
|
+
return e === "checking" ? /* @__PURE__ */ a("p", { className: "rb-builder__status", children: "Checking access…" }) : e === "redirecting" ? /* @__PURE__ */ a("p", { className: "rb-builder__status", children: "Redirecting to sign in…" }) : O ? /* @__PURE__ */ a("p", { className: "rb-builder__status", children: "Loading blocks…" }) : I ? /* @__PURE__ */ a("p", { className: "rb-builder__status rb-builder__status--error", children: I }) : /* @__PURE__ */ c("div", { className: "rb-builder", children: [
|
|
383
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__toolbar", children: [
|
|
384
|
+
/* @__PURE__ */ c("header", { className: "rb-builder__header", children: [
|
|
385
|
+
/* @__PURE__ */ a("h1", { children: "Resume Builder" }),
|
|
386
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__count", children: [
|
|
387
|
+
T.length,
|
|
388
|
+
" / ",
|
|
389
|
+
l.length,
|
|
390
|
+
" blocks"
|
|
391
|
+
] }),
|
|
392
|
+
i && /* @__PURE__ */ c("div", { className: "rb-builder__whoami", children: [
|
|
393
|
+
"Signed in as ",
|
|
394
|
+
/* @__PURE__ */ a("span", { className: "rb-builder__whoami-name", children: i })
|
|
395
|
+
] }),
|
|
396
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__header-actions", children: [
|
|
397
|
+
/* @__PURE__ */ a("button", { type: "button", onClick: Q, className: "rb-builder__btn", children: "Export blocks.json" }),
|
|
398
|
+
/* @__PURE__ */ a(
|
|
399
|
+
"button",
|
|
400
|
+
{
|
|
401
|
+
type: "button",
|
|
402
|
+
onClick: () => x(he()),
|
|
403
|
+
className: "rb-builder__btn rb-builder__btn--primary",
|
|
404
|
+
disabled: k !== null,
|
|
405
|
+
children: "+ New block"
|
|
406
|
+
}
|
|
407
|
+
)
|
|
408
|
+
] })
|
|
409
|
+
] }),
|
|
410
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__controls", children: [
|
|
411
|
+
/* @__PURE__ */ a(
|
|
412
|
+
"input",
|
|
413
|
+
{
|
|
414
|
+
type: "search",
|
|
415
|
+
placeholder: "Search id, title, content…",
|
|
416
|
+
value: m,
|
|
417
|
+
onChange: (r) => y(r.target.value),
|
|
418
|
+
className: "rb-builder__search"
|
|
419
|
+
}
|
|
420
|
+
),
|
|
421
|
+
/* @__PURE__ */ c(
|
|
422
|
+
"select",
|
|
423
|
+
{
|
|
424
|
+
value: _,
|
|
425
|
+
onChange: (r) => N(r.target.value),
|
|
426
|
+
className: "rb-builder__select",
|
|
427
|
+
children: [
|
|
428
|
+
/* @__PURE__ */ a("option", { value: "", children: "all types" }),
|
|
429
|
+
pe.map((r) => /* @__PURE__ */ a("option", { value: r, children: r }, r))
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
),
|
|
433
|
+
/* @__PURE__ */ c(
|
|
434
|
+
"select",
|
|
435
|
+
{
|
|
436
|
+
value: v,
|
|
437
|
+
onChange: (r) => F(r.target.value),
|
|
438
|
+
className: "rb-builder__select",
|
|
439
|
+
children: [
|
|
440
|
+
/* @__PURE__ */ a("option", { value: "order", children: "render order" }),
|
|
441
|
+
/* @__PURE__ */ a("option", { value: "priority", children: "priority ↓" }),
|
|
442
|
+
/* @__PURE__ */ a("option", { value: "type", children: "type" }),
|
|
443
|
+
/* @__PURE__ */ a("option", { value: "feedback", children: "has feedback" })
|
|
444
|
+
]
|
|
445
|
+
}
|
|
446
|
+
),
|
|
447
|
+
/* @__PURE__ */ c("label", { className: "rb-builder__andmode", children: [
|
|
448
|
+
/* @__PURE__ */ a("input", { type: "checkbox", checked: f, onChange: (r) => A(r.target.checked) }),
|
|
449
|
+
"match all tags"
|
|
450
|
+
] })
|
|
451
|
+
] }),
|
|
452
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__legend", children: [
|
|
453
|
+
/* @__PURE__ */ c("span", { className: "rb-builder__legend-item", children: [
|
|
454
|
+
/* @__PURE__ */ a("span", { className: "rb-builder__legend-dot rb-builder__legend-dot--tech" }),
|
|
455
|
+
"tech:"
|
|
456
|
+
] }),
|
|
457
|
+
/* @__PURE__ */ c("span", { className: "rb-builder__legend-item", children: [
|
|
458
|
+
/* @__PURE__ */ a("span", { className: "rb-builder__legend-dot rb-builder__legend-dot--layer" }),
|
|
459
|
+
"layer:"
|
|
460
|
+
] }),
|
|
461
|
+
/* @__PURE__ */ c("span", { className: "rb-builder__legend-item", children: [
|
|
462
|
+
/* @__PURE__ */ a("span", { className: "rb-builder__legend-dot rb-builder__legend-dot--story" }),
|
|
463
|
+
"story:"
|
|
464
|
+
] }),
|
|
465
|
+
/* @__PURE__ */ c("span", { className: "rb-builder__legend-item", children: [
|
|
466
|
+
/* @__PURE__ */ a("span", { className: "rb-builder__legend-dot rb-builder__legend-dot--plain" }),
|
|
467
|
+
"other / always"
|
|
468
|
+
] }),
|
|
469
|
+
/* @__PURE__ */ c("span", { className: "rb-builder__legend-item", children: [
|
|
470
|
+
/* @__PURE__ */ a("strong", { children: "prio" }),
|
|
471
|
+
" = how strongly you want a block (sort/rank hint)"
|
|
472
|
+
] })
|
|
473
|
+
] }),
|
|
474
|
+
/* @__PURE__ */ a("div", { className: "rb-builder__tagbar", children: C.map((r) => /* @__PURE__ */ c(
|
|
475
|
+
"button",
|
|
476
|
+
{
|
|
477
|
+
type: "button",
|
|
478
|
+
onClick: () => S(r),
|
|
479
|
+
className: `rb-tag rb-tag--${U(r)}${g.has(r) ? " rb-tag--active" : ""}`,
|
|
480
|
+
children: [
|
|
481
|
+
r,
|
|
482
|
+
/* @__PURE__ */ a("span", { className: "rb-tag__n", children: w.get(r) })
|
|
483
|
+
]
|
|
484
|
+
},
|
|
485
|
+
r
|
|
486
|
+
)) })
|
|
487
|
+
] }),
|
|
488
|
+
/* @__PURE__ */ c("div", { className: "rb-builder__list", children: [
|
|
489
|
+
k && /* @__PURE__ */ a(
|
|
490
|
+
M,
|
|
491
|
+
{
|
|
492
|
+
block: k,
|
|
493
|
+
feedback: void 0,
|
|
494
|
+
isNew: !0,
|
|
495
|
+
existingIds: l.map((r) => r.id),
|
|
496
|
+
onSave: (r) => $(r, !0),
|
|
497
|
+
onCancel: () => x(null),
|
|
498
|
+
onFeedback: o,
|
|
499
|
+
onTagClick: S
|
|
500
|
+
},
|
|
501
|
+
"__new__"
|
|
502
|
+
),
|
|
503
|
+
T.map((r) => /* @__PURE__ */ a(
|
|
504
|
+
M,
|
|
505
|
+
{
|
|
506
|
+
block: r,
|
|
507
|
+
feedback: u[r.id],
|
|
508
|
+
existingIds: l.map((t) => t.id),
|
|
509
|
+
onSave: (t) => $(t, !1),
|
|
510
|
+
onDelete: () => L(r.id),
|
|
511
|
+
onFeedback: o,
|
|
512
|
+
onTagClick: S
|
|
513
|
+
},
|
|
514
|
+
r.id
|
|
515
|
+
))
|
|
516
|
+
] })
|
|
517
|
+
] });
|
|
518
|
+
}
|
|
519
|
+
const ge = "#resume-builder-root{height:100vh;overflow-y:auto}.rb-builder{box-sizing:border-box;max-width:1000px;margin:0 auto;padding:0 var(--hdk-space-lg) var(--hdk-space-3xl);color:var(--color-text);font-size:var(--hdk-text-sm)}.rb-builder *,.rb-builder *:before,.rb-builder *:after{box-sizing:border-box}.rb-builder__status{padding:var(--hdk-space-lg);color:var(--color-text-secondary)}.rb-builder__status--error{border-left:3px solid var(--color-danger);padding-left:.5rem;color:var(--color-text)}.rb-builder__toolbar{position:sticky;top:0;z-index:5;background:var(--color-bg);padding-top:var(--hdk-space-lg);margin-bottom:var(--hdk-space-lg);border-bottom:1px solid var(--color-border)}.rb-builder__header{display:flex;align-items:center;gap:var(--hdk-space-md);flex-wrap:wrap;margin-bottom:var(--hdk-space-md)}.rb-builder__header h1{font-size:var(--hdk-text-lg);margin:0;line-height:1.2}.rb-builder__count{color:var(--color-text-secondary);font-variant-numeric:tabular-nums}.rb-builder__whoami{margin-left:auto;color:var(--color-text-secondary);font-size:var(--hdk-text-xs);white-space:nowrap}.rb-builder__whoami-name{color:var(--color-text);font-weight:600}.rb-builder__header-actions{margin-left:auto;display:flex;gap:var(--hdk-space-sm)}.rb-builder__whoami+.rb-builder__header-actions{margin-left:var(--hdk-space-md)}.rb-builder__controls{display:flex;gap:var(--hdk-space-sm);flex-wrap:wrap;align-items:center;margin-bottom:var(--hdk-space-sm)}.rb-builder__search{flex:1 1 220px;min-width:200px}.rb-builder__andmode{display:flex;align-items:center;gap:.4rem;color:var(--color-text-secondary);white-space:nowrap;cursor:pointer;user-select:none}.rb-builder__andmode input{accent-color:var(--color-primary)}.rb-builder__legend{display:flex;flex-wrap:wrap;align-items:center;gap:var(--hdk-space-md);padding:var(--hdk-space-sm) 0;color:var(--color-text-secondary);font-size:var(--hdk-text-xs)}.rb-builder__legend-item{display:inline-flex;align-items:center;gap:.4rem;white-space:nowrap}.rb-builder__legend-dot{width:.7rem;height:.7rem;border-radius:999px;border:1px solid var(--color-neutral);background:var(--color-neutral);flex:none}.rb-builder__legend-dot--tech{border-color:var(--color-success);background:var(--color-success)}.rb-builder__legend-dot--layer{border-color:var(--color-primary);background:var(--color-primary)}.rb-builder__legend-dot--story{border-color:var(--color-warning);background:var(--color-warning)}.rb-builder__search,.rb-builder__select,.rb-block__id-input,.rb-block__title,.rb-block__tags-input,.rb-block__type,.rb-block__prio input,.rb-block__content,.rb-block__feedback textarea{background:var(--color-bg);color:var(--color-text);border:1px solid var(--color-border);border-radius:var(--hdk-radius-sm);padding:.45rem .6rem;font-family:inherit;font-size:var(--hdk-text-sm);line-height:1.4}.rb-builder__search:focus,.rb-builder__select:focus,.rb-block__id-input:focus,.rb-block__title:focus,.rb-block__tags-input:focus,.rb-block__type:focus,.rb-block__prio input:focus,.rb-block__content:focus,.rb-block__feedback textarea:focus{outline:none;border-color:var(--color-primary);box-shadow:var(--hdk-shadow-focus)}.rb-builder__tagbar{display:flex;flex-wrap:wrap;gap:.4rem;max-height:116px;overflow-y:auto;padding:var(--hdk-space-sm) 0 var(--hdk-space-md)}.rb-tag{display:inline-flex;align-items:center;gap:.35rem;padding:.15rem .55rem;border-radius:999px;border:1px solid var(--color-neutral);background:var(--color-neutral-bg);color:var(--color-on-neutral-bg);font-size:var(--hdk-text-xs);line-height:1.5;cursor:pointer;font-family:ui-monospace,monospace;transition:background .12s ease,color .12s ease}.rb-tag:hover{background:color-mix(in srgb,currentcolor 15%,transparent)}.rb-tag--tech{border-color:var(--color-success);background:var(--color-success-bg);color:var(--color-on-success-bg)}.rb-tag--layer{border-color:var(--color-primary);background:var(--color-primary-bg);color:var(--color-on-primary-bg)}.rb-tag--story{border-color:var(--color-warning);background:var(--color-warning-bg);color:var(--color-on-warning-bg)}.rb-tag--active{background:var(--color-neutral);color:var(--color-on-neutral)}.rb-tag--tech.rb-tag--active{background:var(--color-success);color:var(--color-on-success)}.rb-tag--layer.rb-tag--active{background:var(--color-primary);color:var(--color-on-primary)}.rb-tag--story.rb-tag--active{background:var(--color-warning);color:var(--color-on-warning)}.rb-tag--active .rb-tag__n{color:inherit}.rb-tag__n{opacity:.75;font-size:.9em;font-variant-numeric:tabular-nums}.rb-builder__list{display:flex;flex-direction:column;gap:var(--hdk-space-md)}.rb-block{border:1px solid var(--color-border);border-left:3px solid transparent;border-radius:var(--hdk-radius-sm);padding:var(--hdk-space-md);display:flex;flex-direction:column;gap:var(--hdk-space-sm);background:var(--color-bg-card);box-shadow:var(--hdk-shadow-sm)}.rb-block--has-feedback{border-left-color:var(--color-success)}.rb-block--dirty{border-left-color:var(--color-warning)}.rb-block__row{display:flex;align-items:center;gap:var(--hdk-space-sm)}.rb-block__id{font-family:ui-monospace,monospace;color:var(--color-text);font-weight:600;word-break:break-all}.rb-block__id-input{flex:1;font-family:ui-monospace,monospace}.rb-block__type{flex:none}.rb-block__prio{display:flex;align-items:center;gap:.4rem;margin-left:auto;color:var(--color-text-secondary);white-space:nowrap}.rb-block__prio input{width:3.5rem;text-align:center}.rb-block__title{width:100%}.rb-block__content{width:100%;resize:vertical;min-height:8rem;font-family:ui-monospace,monospace;line-height:1.5}.rb-block__chips{display:flex;flex-wrap:wrap;gap:.35rem}.rb-block__chips:empty{display:none}.rb-block__tags-input{width:100%;font-family:ui-monospace,monospace}.rb-block__actions{display:flex;align-items:center;flex-wrap:wrap;gap:var(--hdk-space-sm);margin-top:.15rem}.rb-block__hint{color:var(--color-text-secondary);font-size:var(--hdk-text-xs)}.rb-block__hint--error{border-left:3px solid var(--color-danger);padding-left:.5rem;color:var(--color-text)}.rb-block__feedback{display:flex;align-items:flex-start;gap:var(--hdk-space-sm);padding-top:var(--hdk-space-sm);margin-top:var(--hdk-space-xs);border-top:1px dashed var(--color-border)}.rb-block__feedback textarea{flex:1;resize:vertical}.rb-block__fb-status{color:var(--color-text-secondary);font-size:var(--hdk-text-xs);white-space:nowrap;padding-top:.5rem}.rb-builder__btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.45rem .9rem;border-radius:var(--hdk-radius-sm);border:1px solid var(--color-border);background:var(--color-bg-card);color:var(--color-text);cursor:pointer;font-family:inherit;font-size:var(--hdk-text-sm);font-weight:500;line-height:1.4;white-space:nowrap;transition:background .12s ease,border-color .12s ease,opacity .12s ease}.rb-builder__btn:hover:not(:disabled){background:var(--color-bg-hover);border-color:var(--color-text-secondary)}.rb-builder__btn:focus-visible{outline:none;box-shadow:var(--hdk-shadow-focus)}.rb-builder__btn:disabled{opacity:.45;cursor:not-allowed}.rb-builder__btn--primary{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-on-primary)}.rb-builder__btn--primary:hover:not(:disabled){background:var(--color-primary-dark);border-color:var(--color-primary-dark)}.rb-builder__btn--danger{color:var(--color-text);border-color:var(--color-danger);background:transparent}.rb-builder__btn--danger:hover:not(:disabled){background:var(--color-danger);border-color:var(--color-danger);color:var(--color-on-danger)}";
|
|
520
|
+
function _e() {
|
|
521
|
+
if (document.getElementById("rb-builder-styles")) return;
|
|
522
|
+
const e = document.createElement("style");
|
|
523
|
+
e.id = "rb-builder-styles", e.textContent = ge, document.head.appendChild(e);
|
|
524
|
+
}
|
|
525
|
+
function xe(e, i) {
|
|
526
|
+
_e(), re(i.apiBaseUrl);
|
|
527
|
+
const l = Z(e);
|
|
528
|
+
l.render(/* @__PURE__ */ a(me, {})), e.__root = l, E.info("[resume-builder] Mounted", { apiBaseUrl: i.apiBaseUrl });
|
|
529
|
+
}
|
|
530
|
+
function we(e) {
|
|
531
|
+
e.__root?.unmount(), E.info("[resume-builder] Unmounted");
|
|
532
|
+
}
|
|
533
|
+
export {
|
|
534
|
+
xe as mount,
|
|
535
|
+
we as unmount
|
|
536
|
+
};
|
|
537
|
+
//# sourceMappingURL=builder.js.map
|