@leadertechie/personal-site-kit 0.1.0-alpha.3 → 0.1.0-alpha.5

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 (58) hide show
  1. package/dist/api/handlers/auth-handler.d.ts +2 -0
  2. package/dist/api/handlers/auth-handler.d.ts.map +1 -0
  3. package/dist/api/handlers/auth.d.ts +23 -0
  4. package/dist/api/handlers/auth.d.ts.map +1 -0
  5. package/dist/api/handlers/content.d.ts.map +1 -1
  6. package/dist/api/index.d.ts +2 -0
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/website-api.d.ts +1 -1
  9. package/dist/api/website-api.d.ts.map +1 -1
  10. package/dist/api.js +17 -2
  11. package/dist/assets/logo-placeholder.svg +21 -0
  12. package/dist/chunks/index-VimKeB5W.js +1927 -0
  13. package/dist/chunks/{template-gGTkeOcA.js → template-MawmknFQ.js} +13 -4
  14. package/dist/chunks/{website-api-CVsi-OLc.js → website-api-DI3muo2s.js} +335 -23
  15. package/dist/index.js +29 -13
  16. package/dist/shared/router.d.ts.map +1 -1
  17. package/dist/shared.js +1 -1
  18. package/dist/ui/about-me/styles.d.ts.map +1 -1
  19. package/dist/ui/admin/styles.d.ts.map +1 -1
  20. package/dist/ui/banner/styles.d.ts.map +1 -1
  21. package/dist/ui/blog-viewer/__tests__/blogviewer.test.d.ts +2 -0
  22. package/dist/ui/blog-viewer/__tests__/blogviewer.test.d.ts.map +1 -0
  23. package/dist/ui/blog-viewer/index.d.ts +25 -0
  24. package/dist/ui/blog-viewer/index.d.ts.map +1 -0
  25. package/dist/ui/blog-viewer/styles.d.ts +2 -0
  26. package/dist/ui/blog-viewer/styles.d.ts.map +1 -0
  27. package/dist/ui/footer/styles.d.ts.map +1 -1
  28. package/dist/ui/index.d.ts +2 -0
  29. package/dist/ui/index.d.ts.map +1 -1
  30. package/dist/ui/story-viewer/__tests__/storyviewer.test.d.ts +2 -0
  31. package/dist/ui/story-viewer/__tests__/storyviewer.test.d.ts.map +1 -0
  32. package/dist/ui/story-viewer/index.d.ts +25 -0
  33. package/dist/ui/story-viewer/index.d.ts.map +1 -0
  34. package/dist/ui/story-viewer/styles.d.ts +2 -0
  35. package/dist/ui/story-viewer/styles.d.ts.map +1 -0
  36. package/dist/ui.js +4 -2
  37. package/package.json +3 -2
  38. package/public/assets/logo-placeholder.svg +21 -0
  39. package/src/api/handlers/auth-handler.ts +181 -0
  40. package/src/api/handlers/auth.ts +157 -0
  41. package/src/api/handlers/content.ts +81 -14
  42. package/src/api/index.ts +2 -0
  43. package/src/api/website-api.ts +22 -16
  44. package/src/shared/config/index.ts +1 -1
  45. package/src/shared/router.ts +12 -3
  46. package/src/ui/about-me/styles.ts +81 -6
  47. package/src/ui/admin/styles.ts +0 -47
  48. package/src/ui/banner/styles.ts +89 -4
  49. package/src/ui/blog-viewer/__tests__/blogviewer.test.ts +7 -0
  50. package/src/ui/blog-viewer/index.ts +124 -0
  51. package/src/ui/blog-viewer/styles.ts +23 -0
  52. package/src/ui/footer/index.ts +1 -1
  53. package/src/ui/footer/styles.ts +43 -2
  54. package/src/ui/index.ts +2 -0
  55. package/src/ui/story-viewer/__tests__/storyviewer.test.ts +7 -0
  56. package/src/ui/story-viewer/index.ts +120 -0
  57. package/src/ui/story-viewer/styles.ts +54 -0
  58. package/dist/chunks/index-BqixlS-2.js +0 -1157
@@ -0,0 +1,1927 @@
1
+ import { css, html, LitElement } from "lit";
2
+ import { customElement, property, state } from "lit/decorators.js";
3
+ import { MarkdownPipeline } from "@leadertechie/md2html";
4
+ const aboutmeStyles = css`
5
+ :host {
6
+ display: block;
7
+ }
8
+
9
+ .aboutme {
10
+ display: block;
11
+ padding: 20px;
12
+ max-width: 800px;
13
+ margin: 0 auto;
14
+ line-height: 1.6;
15
+ }
16
+
17
+ .aboutme h2 {
18
+ color: var(--link-color);
19
+ margin-bottom: 15px;
20
+ font-size: 2em;
21
+ }
22
+
23
+ .aboutme h3 {
24
+ color: var(--link-color);
25
+ margin-bottom: 10px;
26
+ }
27
+
28
+ .aboutme p {
29
+ margin-bottom: 10px;
30
+ text-align: left;
31
+ }
32
+
33
+ .aboutme ul {
34
+ list-style-type: disc;
35
+ margin-left: 20px;
36
+ text-align: left;
37
+ }
38
+
39
+ .aboutme li {
40
+ margin-bottom: 5px;
41
+ }
42
+
43
+ .aboutme .profile-picture {
44
+ width: 150px;
45
+ height: 150px;
46
+ border-radius: 50%;
47
+ object-fit: cover;
48
+ margin-bottom: 20px;
49
+ border: 3px solid var(--link-color);
50
+ box-shadow:
51
+ 0 0 0 4px var(--link-color),
52
+ 0 8px 16px rgba(0, 0, 0, 0.2),
53
+ 0 12px 24px rgba(0, 0, 0, 0.15);
54
+ }
55
+
56
+ .aboutme .profile-section {
57
+ text-align: center;
58
+ background: var(--card-bg, var(--background-color, #fff));
59
+ border-radius: 16px;
60
+ padding: 2rem;
61
+ box-shadow:
62
+ 0 4px 6px rgba(0, 0, 0, 0.07),
63
+ 0 10px 20px rgba(0, 0, 0, 0.05);
64
+ margin-bottom: 2rem;
65
+ }
66
+
67
+ .aboutme .profile-title {
68
+ color: var(--secondary-text, #666);
69
+ margin-bottom: 0;
70
+ text-align: center;
71
+ }
72
+
73
+ .aboutme h1 {
74
+ margin-bottom: 0.5rem;
75
+ }
76
+
77
+ .aboutme .loading {
78
+ text-align: center;
79
+ padding: 20px;
80
+ color: var(--text-color);
81
+ }
82
+
83
+ .aboutme .content-section {
84
+ font-family: Arial, sans-serif;
85
+ }
86
+ `;
87
+ class AboutMeRenderer {
88
+ renderContent(nodes) {
89
+ return nodes;
90
+ }
91
+ }
92
+ async function fetchAboutMe(url) {
93
+ const res = await fetch(`${url}/api/aboutme`);
94
+ if (!res.ok) throw new Error("Failed to fetch");
95
+ return res.json();
96
+ }
97
+ var __create$5 = Object.create;
98
+ var __defProp$5 = Object.defineProperty;
99
+ var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
100
+ var __knownSymbol$5 = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
101
+ var __typeError$5 = (msg) => {
102
+ throw TypeError(msg);
103
+ };
104
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
105
+ var __name$5 = (target, value) => __defProp$5(target, "name", { value, configurable: true });
106
+ var __decoratorStart$5 = (base) => [, , , __create$5(base?.[__knownSymbol$5("metadata")] ?? null)];
107
+ var __decoratorStrings$5 = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
108
+ var __expectFn$5 = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError$5("Function expected") : fn;
109
+ var __decoratorContext$5 = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings$5[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError$5("Already initialized") : fns.push(__expectFn$5(fn || null)) });
110
+ var __decoratorMetadata$5 = (array, target) => __defNormalProp$5(target, __knownSymbol$5("metadata"), array[3]);
111
+ var __runInitializers$5 = (array, flags, self, value) => {
112
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) flags & 1 ? fns[i2].call(self) : value = fns[i2].call(self, value);
113
+ return value;
114
+ };
115
+ var __decorateElement$5 = (array, flags, name, decorators, target, extra) => {
116
+ var fn, it, done, ctx, access, k2 = flags & 7, s2 = !!(flags & 8), p2 = !!(flags & 16);
117
+ var j = k2 > 3 ? array.length + 1 : k2 ? s2 ? 1 : 2 : 0, key = __decoratorStrings$5[k2 + 5];
118
+ var initializers = k2 > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
119
+ var desc = k2 && (!p2 && !s2 && (target = target.prototype), k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc$5(k2 < 4 ? target : { get [name]() {
120
+ return __privateGet$4(this, extra);
121
+ }, set [name](x) {
122
+ return __privateSet$4(this, extra, x);
123
+ } }, name));
124
+ k2 ? p2 && k2 < 4 && __name$5(extra, (k2 > 2 ? "set " : k2 > 1 ? "get " : "") + name) : __name$5(target, name);
125
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
126
+ ctx = __decoratorContext$5(k2, name, done = {}, array[3], extraInitializers);
127
+ if (k2) {
128
+ ctx.static = s2, ctx.private = p2, access = ctx.access = { has: p2 ? (x) => __privateIn$4(target, x) : (x) => name in x };
129
+ if (k2 ^ 3) access.get = p2 ? (x) => (k2 ^ 1 ? __privateGet$4 : __privateMethod$4)(x, target, k2 ^ 4 ? extra : desc.get) : (x) => x[name];
130
+ if (k2 > 2) access.set = p2 ? (x, y2) => __privateSet$4(x, target, y2, k2 ^ 4 ? extra : desc.set) : (x, y2) => x[name] = y2;
131
+ }
132
+ it = (0, decorators[i2])(k2 ? k2 < 4 ? p2 ? extra : desc[key] : k2 > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
133
+ if (k2 ^ 4 || it === void 0) __expectFn$5(it) && (k2 > 4 ? initializers.unshift(it) : k2 ? p2 ? extra = it : desc[key] = it : target = it);
134
+ else if (typeof it !== "object" || it === null) __typeError$5("Object expected");
135
+ else __expectFn$5(fn = it.get) && (desc.get = fn), __expectFn$5(fn = it.set) && (desc.set = fn), __expectFn$5(fn = it.init) && initializers.unshift(fn);
136
+ }
137
+ return k2 || __decoratorMetadata$5(array, target), desc && __defProp$5(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
138
+ };
139
+ var __accessCheck$4 = (obj, member, msg) => member.has(obj) || __typeError$5("Cannot " + msg);
140
+ var __privateIn$4 = (member, obj) => Object(obj) !== obj ? __typeError$5('Cannot use the "in" operator on this value') : member.has(obj);
141
+ var __privateGet$4 = (obj, member, getter) => (__accessCheck$4(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
142
+ var __privateAdd$4 = (obj, member, value) => member.has(obj) ? __typeError$5("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
143
+ var __privateSet$4 = (obj, member, value, setter) => (__accessCheck$4(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
144
+ var __privateMethod$4 = (obj, member, method) => (__accessCheck$4(obj, member, "access private method"), method);
145
+ var _loading_dec$2, _contentNodes_dec, _profile_dec, _baseUrl_dec, _a$5, _MyAboutme_decorators, _init$5, _baseUrl, _profile, _contentNodes, _loading$2;
146
+ _MyAboutme_decorators = [customElement("my-aboutme")];
147
+ class MyAboutme extends (_a$5 = LitElement, _baseUrl_dec = [property({ type: String })], _profile_dec = [state()], _contentNodes_dec = [state()], _loading_dec$2 = [state()], _a$5) {
148
+ constructor(renderer) {
149
+ super();
150
+ __privateAdd$4(this, _baseUrl, __runInitializers$5(_init$5, 8, this, "")), __runInitializers$5(_init$5, 11, this);
151
+ __privateAdd$4(this, _profile, __runInitializers$5(_init$5, 12, this, null)), __runInitializers$5(_init$5, 15, this);
152
+ __privateAdd$4(this, _contentNodes, __runInitializers$5(_init$5, 16, this, [])), __runInitializers$5(_init$5, 19, this);
153
+ __privateAdd$4(this, _loading$2, __runInitializers$5(_init$5, 20, this, true)), __runInitializers$5(_init$5, 23, this);
154
+ this.renderer = void 0;
155
+ this.fetcher = fetchAboutMe;
156
+ this.renderer = renderer || new AboutMeRenderer();
157
+ }
158
+ get apiBaseUrl() {
159
+ return this.baseUrl || this.getAttribute("base-url") || "";
160
+ }
161
+ async connectedCallback() {
162
+ super.connectedCallback();
163
+ if (typeof window !== "undefined" && window.__HYDRATION_DATA__) {
164
+ const hydrationData = window.__HYDRATION_DATA__;
165
+ this.profile = hydrationData.profile;
166
+ this.contentNodes = hydrationData.contentNodes;
167
+ this.loading = false;
168
+ return;
169
+ }
170
+ const url = this.apiBaseUrl;
171
+ if (url) {
172
+ this.loadContent();
173
+ }
174
+ }
175
+ updated(changedProperties) {
176
+ super.updated(changedProperties);
177
+ if (this.loading === false && this.profile && this.contentNodes.length > 0) {
178
+ return;
179
+ }
180
+ if (changedProperties.has("baseUrl") || changedProperties.has("base-url")) {
181
+ const url = this.apiBaseUrl;
182
+ if (url) {
183
+ this.loadContent();
184
+ }
185
+ }
186
+ }
187
+ async loadContent() {
188
+ try {
189
+ this.loading = true;
190
+ const url = this.apiBaseUrl;
191
+ const data = await this.fetcher(url);
192
+ this.profile = data.profile;
193
+ this.contentNodes = data.contentNodes;
194
+ this.loading = false;
195
+ await this.updateComplete;
196
+ } catch (error) {
197
+ this.loading = false;
198
+ this.setFallbackContent();
199
+ await this.updateComplete;
200
+ }
201
+ }
202
+ setFallbackContent() {
203
+ this.profile = null;
204
+ this.contentNodes = [
205
+ {
206
+ type: "paragraph",
207
+ content: "Unable to Load Content"
208
+ }
209
+ ];
210
+ }
211
+ render() {
212
+ if (this.loading) {
213
+ return html`<div class="aboutme"><div class="loading">Loading...</div></div>`;
214
+ }
215
+ if (!this.profile) {
216
+ if (this.contentNodes && this.contentNodes.length > 0) {
217
+ return html`<div class="aboutme">${this.renderer.renderContent(this.contentNodes)}</div>`;
218
+ }
219
+ return html`<div class="aboutme"><div class="loading">Failed to load content</div></div>`;
220
+ }
221
+ const profileImageUrl = this.profile.profileImageUrl ? this.profile.profileImageUrl.startsWith("http") || this.profile.profileImageUrl.startsWith("/") ? this.profile.profileImageUrl : `images/${this.profile.profileImageUrl}` : "";
222
+ return html`
223
+ <div class="aboutme">
224
+ <div class="profile-section">
225
+ ${profileImageUrl ? html`
226
+ <img src="${profileImageUrl}" alt="${this.profile.name}"
227
+ class="profile-picture">
228
+ ` : ""}
229
+ <h1>${this.profile.name}</h1>
230
+ <p class="profile-title">${this.profile.title} • ${this.profile.experience}</p>
231
+ </div>
232
+ <div class="content-section">
233
+ ${this.renderer.renderContent(this.contentNodes)}
234
+ </div>
235
+ </div>
236
+ `;
237
+ }
238
+ }
239
+ _init$5 = __decoratorStart$5(_a$5);
240
+ _baseUrl = /* @__PURE__ */ new WeakMap();
241
+ _profile = /* @__PURE__ */ new WeakMap();
242
+ _contentNodes = /* @__PURE__ */ new WeakMap();
243
+ _loading$2 = /* @__PURE__ */ new WeakMap();
244
+ __decorateElement$5(_init$5, 4, "baseUrl", _baseUrl_dec, MyAboutme, _baseUrl);
245
+ __decorateElement$5(_init$5, 4, "profile", _profile_dec, MyAboutme, _profile);
246
+ __decorateElement$5(_init$5, 4, "contentNodes", _contentNodes_dec, MyAboutme, _contentNodes);
247
+ __decorateElement$5(_init$5, 4, "loading", _loading_dec$2, MyAboutme, _loading$2);
248
+ MyAboutme = __decorateElement$5(_init$5, 0, "MyAboutme", _MyAboutme_decorators, MyAboutme);
249
+ MyAboutme.styles = aboutmeStyles;
250
+ __runInitializers$5(_init$5, 1, MyAboutme);
251
+ const adminStyles = css`
252
+ :host {
253
+ display: block;
254
+ width: 100%;
255
+ max-width: 100%;
256
+ padding: 20px;
257
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
258
+ color: var(--text-color, #213547);
259
+ background-color: var(--background-color, #fff);
260
+ min-height: 100vh;
261
+ box-sizing: border-box;
262
+ }
263
+
264
+ *, *::before, *::after {
265
+ box-sizing: border-box;
266
+ }
267
+
268
+ .container {
269
+ width: 100%;
270
+ max-width: 900px;
271
+ margin: 0 auto;
272
+ padding: 1rem;
273
+ }
274
+
275
+ .login-box {
276
+ border: 1px solid var(--border-color, #e0e0e0);
277
+ padding: 3rem 2.5rem;
278
+ border-radius: 16px;
279
+ width: 100%;
280
+ max-width: 420px;
281
+ margin: 80px auto;
282
+ text-align: center;
283
+ background: var(--card-bg, #fff);
284
+ box-shadow: 0 4px 6px rgba(0,0,0,0.07), 0 10px 20px rgba(0,0,0,0.05);
285
+ }
286
+
287
+ .login-box h2 {
288
+ margin: 0 0 0.5rem 0;
289
+ font-size: 1.75rem;
290
+ font-weight: 600;
291
+ color: var(--text-color, #213547);
292
+ }
293
+
294
+ .login-box p {
295
+ color: var(--secondary-text, #666);
296
+ margin-bottom: 1.5rem;
297
+ }
298
+
299
+ .nav-tabs {
300
+ display: flex;
301
+ gap: 8px;
302
+ margin-bottom: 24px;
303
+ flex-wrap: wrap;
304
+ padding: 0.5rem;
305
+ background: var(--card-bg, #fff);
306
+ border-radius: 12px;
307
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
308
+ width: 100%;
309
+ }
310
+
311
+ .nav-tab {
312
+ padding: 0.6rem 1.25rem;
313
+ border: none;
314
+ border-radius: 8px;
315
+ cursor: pointer;
316
+ background: transparent;
317
+ color: var(--text-color, #213547);
318
+ font-size: 0.95rem;
319
+ font-weight: 500;
320
+ transition: all 0.2s ease;
321
+ }
322
+
323
+ .nav-tab:hover {
324
+ background: var(--nav-link-hover-bg, #f0f0f0);
325
+ color: var(--link-color, #646cff);
326
+ }
327
+
328
+ .nav-tab.active {
329
+ background: var(--link-color, #646cff);
330
+ color: white;
331
+ box-shadow: 0 2px 8px rgba(100, 108, 255, 0.3);
332
+ }
333
+
334
+ .section {
335
+ width: 100%;
336
+ border: none;
337
+ padding: 24px;
338
+ border-radius: 16px;
339
+ background: var(--card-bg, #fff);
340
+ box-shadow: 0 4px 6px rgba(0,0,0,0.07), 0 10px 20px rgba(0,0,0,0.05);
341
+ margin-bottom: 20px;
342
+ min-height: 450px;
343
+ box-sizing: border-box;
344
+ }
345
+
346
+ .section h3 {
347
+ margin: 0 0 0.5rem 0;
348
+ font-size: 1.25rem;
349
+ font-weight: 600;
350
+ color: var(--text-color, #213547);
351
+ display: flex;
352
+ align-items: center;
353
+ gap: 0.5rem;
354
+ }
355
+
356
+ .file-list {
357
+ margin-top: 20px;
358
+ }
359
+
360
+ .file-item {
361
+ display: flex;
362
+ justify-content: space-between;
363
+ align-items: center;
364
+ padding: 12px 16px;
365
+ border-bottom: 1px solid var(--border-color, #eee);
366
+ border-radius: 8px;
367
+ transition: background 0.15s ease;
368
+ }
369
+
370
+ .file-item:hover {
371
+ background: var(--nav-link-hover-bg, #f8f9fa);
372
+ }
373
+
374
+ .file-item:last-child {
375
+ border-bottom: none;
376
+ }
377
+
378
+ button {
379
+ cursor: pointer;
380
+ padding: 10px 20px;
381
+ border-radius: 8px;
382
+ font-weight: 500;
383
+ font-size: 0.95rem;
384
+ transition: all 0.2s ease;
385
+ border: none;
386
+ }
387
+
388
+ .btn-primary {
389
+ background: var(--link-color, #646cff);
390
+ color: white;
391
+ box-shadow: 0 2px 4px rgba(100, 108, 255, 0.25);
392
+ }
393
+
394
+ .btn-primary:hover {
395
+ background: var(--link-hover-color, #535bf2);
396
+ transform: translateY(-1px);
397
+ box-shadow: 0 4px 8px rgba(100, 108, 255, 0.3);
398
+ }
399
+
400
+ .btn-danger {
401
+ color: #dc3545;
402
+ background: transparent;
403
+ border: 1px solid #dc3545;
404
+ padding: 6px 12px;
405
+ font-size: 0.85rem;
406
+ }
407
+
408
+ .btn-danger:hover {
409
+ background: #dc3545;
410
+ color: white;
411
+ }
412
+
413
+ .btn-secondary {
414
+ background: var(--nav-link-hover-bg, #f0f0f0);
415
+ color: var(--text-color, #333);
416
+ border: none;
417
+ font-size: 0.85rem;
418
+ padding: 8px 16px;
419
+ }
420
+
421
+ .btn-secondary:hover {
422
+ background: #e0e0e0;
423
+ }
424
+
425
+ input[type="text"], input[type="password"], input[type="file"] {
426
+ padding: 12px 14px;
427
+ width: 100%;
428
+ box-sizing: border-box;
429
+ margin-bottom: 12px;
430
+ border: 2px solid var(--border-color, #e0e0e0);
431
+ border-radius: 10px;
432
+ background-color: var(--background-color, #fff);
433
+ color: var(--text-color, #213547);
434
+ font-size: 0.95rem;
435
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
436
+ }
437
+
438
+ input[type="text"]:focus, input[type="password"]:focus {
439
+ outline: none;
440
+ border-color: var(--link-color, #646cff);
441
+ box-shadow: 0 0 0 3px rgba(100, 108, 255, 0.15);
442
+ }
443
+
444
+ input[type="file"] {
445
+ padding: 10px;
446
+ border-style: dashed;
447
+ cursor: pointer;
448
+ }
449
+
450
+ input[type="file"]:hover {
451
+ border-color: var(--link-color, #646cff);
452
+ background: rgba(100, 108, 255, 0.03);
453
+ }
454
+
455
+ .help-text {
456
+ color: var(--secondary-text, #666);
457
+ font-size: 0.9rem;
458
+ margin-bottom: 16px;
459
+ line-height: 1.5;
460
+ }
461
+
462
+ .status-message {
463
+ padding: 12px 16px;
464
+ border-radius: 8px;
465
+ margin-bottom: 16px;
466
+ font-size: 0.9rem;
467
+ background: var(--nav-link-hover-bg, #f5f5f5);
468
+ color: var(--text-color, #333);
469
+ }
470
+
471
+ .status-message.success {
472
+ background: linear-gradient(135deg, #e8f5e9, #c8e6c9);
473
+ color: #2e7d32;
474
+ border: 1px solid #a5d6a7;
475
+ }
476
+
477
+ .status-message.error {
478
+ background: linear-gradient(135deg, #ffebee, #ffcdd2);
479
+ color: #c62828;
480
+ border: 1px solid #ef9a9a;
481
+ }
482
+
483
+ .header {
484
+ display: flex;
485
+ justify-content: space-between;
486
+ align-items: center;
487
+ margin-bottom: 24px;
488
+ padding-bottom: 16px;
489
+ border-bottom: 2px solid var(--border-color, #eee);
490
+ }
491
+
492
+ .header h1 {
493
+ margin: 0;
494
+ font-size: 1.5rem;
495
+ font-weight: 600;
496
+ color: var(--text-color, #213547);
497
+ }
498
+
499
+ .mt-1 { margin-top: 12px; }
500
+ .mb-1 { margin-bottom: 1rem; }
501
+
502
+ @media (max-width: 600px) {
503
+ .container {
504
+ padding: 0.5rem;
505
+ }
506
+ .section {
507
+ padding: 16px;
508
+ }
509
+ .nav-tabs {
510
+ gap: 4px;
511
+ padding: 8px;
512
+ }
513
+ .nav-tab {
514
+ padding: 8px 12px;
515
+ font-size: 0.85rem;
516
+ }
517
+ }
518
+ `;
519
+ var __create$4 = Object.create;
520
+ var __defProp$4 = Object.defineProperty;
521
+ var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
522
+ var __knownSymbol$4 = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
523
+ var __typeError$4 = (msg) => {
524
+ throw TypeError(msg);
525
+ };
526
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
527
+ var __name$4 = (target, value) => __defProp$4(target, "name", { value, configurable: true });
528
+ var __decoratorStart$4 = (base) => [, , , __create$4(base?.[__knownSymbol$4("metadata")] ?? null)];
529
+ var __decoratorStrings$4 = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
530
+ var __expectFn$4 = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError$4("Function expected") : fn;
531
+ var __decoratorContext$4 = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings$4[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError$4("Already initialized") : fns.push(__expectFn$4(fn || null)) });
532
+ var __decoratorMetadata$4 = (array, target) => __defNormalProp$4(target, __knownSymbol$4("metadata"), array[3]);
533
+ var __runInitializers$4 = (array, flags, self, value) => {
534
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) flags & 1 ? fns[i2].call(self) : value = fns[i2].call(self, value);
535
+ return value;
536
+ };
537
+ var __decorateElement$4 = (array, flags, name, decorators, target, extra) => {
538
+ var fn, it, done, ctx, access, k2 = flags & 7, s2 = !!(flags & 8), p2 = !!(flags & 16);
539
+ var j = k2 > 3 ? array.length + 1 : k2 ? s2 ? 1 : 2 : 0, key = __decoratorStrings$4[k2 + 5];
540
+ var initializers = k2 > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
541
+ var desc = k2 && (!p2 && !s2 && (target = target.prototype), k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc$4(k2 < 4 ? target : { get [name]() {
542
+ return __privateGet$3(this, extra);
543
+ }, set [name](x) {
544
+ return __privateSet$3(this, extra, x);
545
+ } }, name));
546
+ k2 ? p2 && k2 < 4 && __name$4(extra, (k2 > 2 ? "set " : k2 > 1 ? "get " : "") + name) : __name$4(target, name);
547
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
548
+ ctx = __decoratorContext$4(k2, name, done = {}, array[3], extraInitializers);
549
+ if (k2) {
550
+ ctx.static = s2, ctx.private = p2, access = ctx.access = { has: p2 ? (x) => __privateIn$3(target, x) : (x) => name in x };
551
+ if (k2 ^ 3) access.get = p2 ? (x) => (k2 ^ 1 ? __privateGet$3 : __privateMethod$3)(x, target, k2 ^ 4 ? extra : desc.get) : (x) => x[name];
552
+ if (k2 > 2) access.set = p2 ? (x, y2) => __privateSet$3(x, target, y2, k2 ^ 4 ? extra : desc.set) : (x, y2) => x[name] = y2;
553
+ }
554
+ it = (0, decorators[i2])(k2 ? k2 < 4 ? p2 ? extra : desc[key] : k2 > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
555
+ if (k2 ^ 4 || it === void 0) __expectFn$4(it) && (k2 > 4 ? initializers.unshift(it) : k2 ? p2 ? extra = it : desc[key] = it : target = it);
556
+ else if (typeof it !== "object" || it === null) __typeError$4("Object expected");
557
+ else __expectFn$4(fn = it.get) && (desc.get = fn), __expectFn$4(fn = it.set) && (desc.set = fn), __expectFn$4(fn = it.init) && initializers.unshift(fn);
558
+ }
559
+ return k2 || __decoratorMetadata$4(array, target), desc && __defProp$4(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
560
+ };
561
+ var __accessCheck$3 = (obj, member, msg) => member.has(obj) || __typeError$4("Cannot " + msg);
562
+ var __privateIn$3 = (member, obj) => Object(obj) !== obj ? __typeError$4('Cannot use the "in" operator on this value') : member.has(obj);
563
+ var __privateGet$3 = (obj, member, getter) => (__accessCheck$3(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
564
+ var __privateAdd$3 = (obj, member, value) => member.has(obj) ? __typeError$4("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
565
+ var __privateSet$3 = (obj, member, value, setter) => (__accessCheck$3(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
566
+ var __privateMethod$3 = (obj, member, method) => (__accessCheck$3(obj, member, "access private method"), method);
567
+ var _staticDetails_dec, _activeSection_dec, _statusMessage_dec, _contentList_dec, _isAuthenticated_dec, _apiKey_dec, _a$4, _AdminPortal_decorators, _init$4, _apiKey, _isAuthenticated, _contentList, _statusMessage, _activeSection, _staticDetails;
568
+ console.log("[AdminPortal] Module loading");
569
+ console.log("[AdminPortal] About to define custom element");
570
+ _AdminPortal_decorators = [customElement("admin-portal")];
571
+ class AdminPortal extends (_a$4 = LitElement, _apiKey_dec = [state()], _isAuthenticated_dec = [state()], _contentList_dec = [state()], _statusMessage_dec = [state()], _activeSection_dec = [state()], _staticDetails_dec = [state()], _a$4) {
572
+ constructor() {
573
+ super(...arguments);
574
+ __privateAdd$3(this, _apiKey, __runInitializers$4(_init$4, 8, this, "")), __runInitializers$4(_init$4, 11, this);
575
+ __privateAdd$3(this, _isAuthenticated, __runInitializers$4(_init$4, 12, this, false)), __runInitializers$4(_init$4, 15, this);
576
+ __privateAdd$3(this, _contentList, __runInitializers$4(_init$4, 16, this, [])), __runInitializers$4(_init$4, 19, this);
577
+ __privateAdd$3(this, _statusMessage, __runInitializers$4(_init$4, 20, this, "")), __runInitializers$4(_init$4, 23, this);
578
+ __privateAdd$3(this, _activeSection, __runInitializers$4(_init$4, 24, this, "profile")), __runInitializers$4(_init$4, 27, this);
579
+ __privateAdd$3(this, _staticDetails, __runInitializers$4(_init$4, 28, this, {})), __runInitializers$4(_init$4, 31, this);
580
+ }
581
+ get apiUrl() {
582
+ return window.__VITE_API_URL__ || void 0 || "http://localhost:8787";
583
+ }
584
+ handleLogin(e2) {
585
+ e2.preventDefault();
586
+ const input = this.shadowRoot?.querySelector("#apiKey");
587
+ if (input.value) {
588
+ this.apiKey = input.value;
589
+ this.isAuthenticated = true;
590
+ this.fetchContent();
591
+ }
592
+ }
593
+ async fetchContent() {
594
+ try {
595
+ const res = await fetch(`${this.apiUrl}/content`, {
596
+ headers: {
597
+ "Authorization": `Bearer ${this.apiKey}`
598
+ }
599
+ });
600
+ if (res.ok) {
601
+ this.contentList = await res.json();
602
+ } else {
603
+ this.statusMessage = "Failed to fetch content.";
604
+ }
605
+ } catch (e2) {
606
+ this.statusMessage = "Error fetching content.";
607
+ }
608
+ }
609
+ async fetchStaticDetails() {
610
+ try {
611
+ const res = await fetch(`${this.apiUrl}/api/static`);
612
+ if (res.ok) {
613
+ this.staticDetails = await res.json();
614
+ }
615
+ } catch (e2) {
616
+ }
617
+ }
618
+ async handleUpload(key, file) {
619
+ try {
620
+ this.statusMessage = "Uploading...";
621
+ const res = await fetch(`${this.apiUrl}/content/${key}`, {
622
+ method: "PUT",
623
+ headers: {
624
+ "Authorization": `Bearer ${this.apiKey}`
625
+ },
626
+ body: file
627
+ });
628
+ if (res.ok) {
629
+ this.statusMessage = "Upload successful!";
630
+ this.fetchContent();
631
+ } else {
632
+ this.statusMessage = "Upload failed.";
633
+ }
634
+ } catch (e2) {
635
+ this.statusMessage = "Error uploading.";
636
+ }
637
+ }
638
+ async handleClearCache() {
639
+ try {
640
+ this.statusMessage = "Clearing cache...";
641
+ const res = await fetch(`${this.apiUrl}/cache-clear`, {
642
+ method: "POST",
643
+ headers: {
644
+ "Authorization": `Bearer ${this.apiKey}`
645
+ }
646
+ });
647
+ if (res.ok) {
648
+ this.statusMessage = "Cache cleared!";
649
+ } else {
650
+ this.statusMessage = "Failed to clear cache.";
651
+ }
652
+ } catch (e2) {
653
+ this.statusMessage = "Error clearing cache.";
654
+ }
655
+ }
656
+ async handleDelete(key) {
657
+ if (!confirm(`Delete ${key}?`)) return;
658
+ try {
659
+ const res = await fetch(`${this.apiUrl}/content/${key}`, {
660
+ method: "DELETE",
661
+ headers: {
662
+ "Authorization": `Bearer ${this.apiKey}`
663
+ }
664
+ });
665
+ if (res.ok) {
666
+ this.fetchContent();
667
+ } else {
668
+ this.statusMessage = "Delete failed.";
669
+ }
670
+ } catch (e2) {
671
+ this.statusMessage = "Error deleting.";
672
+ }
673
+ }
674
+ getContent(key) {
675
+ return this.contentList.find((c2) => c2.key === key);
676
+ }
677
+ getSectionFiles(prefix) {
678
+ return this.contentList.filter((c2) => c2.key.startsWith(prefix));
679
+ }
680
+ renderHomeSection() {
681
+ const home = this.getContent("home.md");
682
+ return html`
683
+ <div class="section">
684
+ <h3>Home Page</h3>
685
+ <p class="help-text">Content for your home page. Upload home.md with your main content.</p>
686
+
687
+ ${home ? html`
688
+ <div class="current-file">
689
+ <strong>Current:</strong> home.md (${home.size} bytes)
690
+ <button class="btn-danger" @click=${() => this.handleDelete("home.md")}>Delete</button>
691
+ </div>
692
+ ` : ""}
693
+
694
+ <input type="file" id="homeFile" accept=".md" />
695
+ <button class="btn-primary" @click=${() => {
696
+ const input = this.shadowRoot?.querySelector("#homeFile");
697
+ if (input.files?.[0]) this.handleUpload("home.md", input.files[0]);
698
+ }}>Upload home.md</button>
699
+ </div>
700
+ `;
701
+ }
702
+ renderProfileSection() {
703
+ const profile = this.getContent("profile.json");
704
+ return html`
705
+ <div class="section">
706
+ <h3>Profile <span class="required-badge">Required</span></h3>
707
+ <p class="help-text">This file contains your profile information (name, title, experience).</p>
708
+
709
+ ${profile ? html`
710
+ <div class="current-file">
711
+ <strong>Current:</strong> profile.json (${profile.size} bytes)
712
+ <button class="btn-danger" @click=${() => this.handleDelete("profile.json")}>Delete</button>
713
+ </div>
714
+ ` : ""}
715
+
716
+ <input type="file" id="profileFile" accept=".json" />
717
+ <button class="btn-primary" @click=${() => {
718
+ const input = this.shadowRoot?.querySelector("#profileFile");
719
+ if (input.files?.[0]) this.handleUpload("profile.json", input.files[0]);
720
+ }}>Upload profile.json</button>
721
+ </div>
722
+ `;
723
+ }
724
+ renderAboutMeSection() {
725
+ const aboutMe = this.getContent("about-me.md");
726
+ return html`
727
+ <div class="section">
728
+ <h3>About Me Page <span class="required-badge">Required</span></h3>
729
+ <p class="help-text">Content for your About Me page. Supports Markdown with frontmatter.</p>
730
+
731
+ ${aboutMe ? html`
732
+ <div class="current-file">
733
+ <strong>Current:</strong> about-me.md (${aboutMe.size} bytes)
734
+ <button class="btn-danger" @click=${() => this.handleDelete("about-me.md")}>Delete</button>
735
+ </div>
736
+ ` : ""}
737
+
738
+ <input type="file" id="aboutFile" accept=".md" />
739
+ <button class="btn-primary" @click=${() => {
740
+ const input = this.shadowRoot?.querySelector("#aboutFile");
741
+ if (input.files?.[0]) this.handleUpload("about-me.md", input.files[0]);
742
+ }}>Upload about-me.md</button>
743
+ </div>
744
+ `;
745
+ }
746
+ renderBlogsSection() {
747
+ const blogs = this.getSectionFiles("blogs/").filter((b) => b.key.endsWith(".json"));
748
+ return html`
749
+ <div class="section">
750
+ <h3>Blog Posts</h3>
751
+ <p class="help-text">Each blog needs 2 files: a JSON (metadata) and MD (content) file.</p>
752
+
753
+ <h4>Upload New Blog</h4>
754
+ <input type="file" id="blogMetaFile" accept=".json" />
755
+ <input type="file" id="blogContentFile" accept=".md" />
756
+ <input type="text" id="blogSlug" placeholder="Slug (e.g., my-new-post)" class="mt-1" />
757
+ <button class="btn-primary" @click=${() => {
758
+ const metaInput = this.shadowRoot?.querySelector("#blogMetaFile");
759
+ const contentInput = this.shadowRoot?.querySelector("#blogContentFile");
760
+ const slugInput = this.shadowRoot?.querySelector("#blogSlug");
761
+ if (metaInput.files?.[0] && contentInput.files?.[0] && slugInput.value) {
762
+ this.handleUpload(`blogs/${slugInput.value}.json`, metaInput.files[0]);
763
+ this.handleUpload(`blogs/${slugInput.value}.md`, contentInput.files[0]);
764
+ }
765
+ }}>Upload Blog (JSON + MD)</button>
766
+
767
+ <div class="file-list">
768
+ <h4>Current Blogs (${blogs.length})</h4>
769
+ ${blogs.map((b) => html`
770
+ <div class="file-item">
771
+ <span>${b.key.replace(".json", "")}</span>
772
+ <button class="btn-danger" @click=${() => {
773
+ const slug = b.key.replace("blogs/", "").replace(".json", "");
774
+ this.handleDelete(`blogs/${slug}.json`);
775
+ this.handleDelete(`blogs/${slug}.md`);
776
+ }}>Delete</button>
777
+ </div>
778
+ `)}
779
+ ${blogs.length === 0 ? html`<p>No blogs yet.</p>` : ""}
780
+ </div>
781
+ </div>
782
+ `;
783
+ }
784
+ renderStoriesSection() {
785
+ const stories = this.getSectionFiles("stories/").filter((s2) => s2.key.endsWith(".json"));
786
+ return html`
787
+ <div class="section">
788
+ <h3>Stories</h3>
789
+ <p class="help-text">Each story needs 2 files: a JSON (metadata) and MD (content) file.</p>
790
+
791
+ <h4>Upload New Story</h4>
792
+ <input type="file" id="storyMetaFile" accept=".json" />
793
+ <input type="file" id="storyContentFile" accept=".md" />
794
+ <input type="text" id="storySlug" placeholder="Slug (e.g., my-story)" class="mt-1" />
795
+ <button class="btn-primary" @click=${() => {
796
+ const metaInput = this.shadowRoot?.querySelector("#storyMetaFile");
797
+ const contentInput = this.shadowRoot?.querySelector("#storyContentFile");
798
+ const slugInput = this.shadowRoot?.querySelector("#storySlug");
799
+ if (metaInput.files?.[0] && contentInput.files?.[0] && slugInput.value) {
800
+ this.handleUpload(`stories/${slugInput.value}.json`, metaInput.files[0]);
801
+ this.handleUpload(`stories/${slugInput.value}.md`, contentInput.files[0]);
802
+ }
803
+ }}>Upload Story (JSON + MD)</button>
804
+
805
+ <div class="file-list">
806
+ <h4>Current Stories (${stories.length})</h4>
807
+ ${stories.map((s2) => html`
808
+ <div class="file-item">
809
+ <span>${s2.key.replace(".json", "")}</span>
810
+ <button class="btn-danger" @click=${() => {
811
+ const slug = s2.key.replace("stories/", "").replace(".json", "");
812
+ this.handleDelete(`stories/${slug}.json`);
813
+ this.handleDelete(`stories/${slug}.md`);
814
+ }}>Delete</button>
815
+ </div>
816
+ `)}
817
+ ${stories.length === 0 ? html`<p>No stories yet.</p>` : ""}
818
+ </div>
819
+ </div>
820
+ `;
821
+ }
822
+ renderImagesSection() {
823
+ const images = this.getSectionFiles("images/");
824
+ return html`
825
+ <div class="section">
826
+ <h3>Images</h3>
827
+ <p class="help-text">Upload images for use in your content. In markdown, reference images by filename only (e.g., use <code>my-photo.jpg</code> not <code>/images/my-photo.jpg</code>). The renderer automatically prepends <code>images/</code>.</p>
828
+
829
+ <input type="file" id="imageFile" accept="image/*" />
830
+ <input type="text" id="imagePath" placeholder="Image name (e.g., profile-photo.jpg)" class="mt-1" />
831
+ <button class="btn-primary" @click=${() => {
832
+ const fileInput = this.shadowRoot?.querySelector("#imageFile");
833
+ const pathInput = this.shadowRoot?.querySelector("#imagePath");
834
+ if (fileInput.files?.[0] && pathInput.value) {
835
+ this.handleUpload(`images/${pathInput.value}`, fileInput.files[0]);
836
+ }
837
+ }}>Upload to images/</button>
838
+
839
+ <div class="file-list">
840
+ <h4>Current Images (${images.length})</h4>
841
+ ${images.map((img) => html`
842
+ <div class="file-item">
843
+ <span>${img.key} (${img.size} bytes)</span>
844
+ <button class="btn-danger" @click=${() => this.handleDelete(img.key)}>Delete</button>
845
+ </div>
846
+ `)}
847
+ ${images.length === 0 ? html`<p>No images yet.</p>` : ""}
848
+ </div>
849
+ </div>
850
+ `;
851
+ }
852
+ renderLogoSection() {
853
+ const logo = this.getContent("logo.svg");
854
+ return html`
855
+ <div class="section">
856
+ <h3>Site Logo</h3>
857
+ <p class="help-text">Upload your site logo (SVG format recommended). This appears in the header of your site.</p>
858
+
859
+ ${logo ? html`
860
+ <div class="current-file">
861
+ <strong>Current:</strong> logo.svg (${logo.size} bytes)
862
+ <button class="btn-danger" @click=${() => this.handleDelete("logo.svg")}>Delete</button>
863
+ </div>
864
+ ` : ""}
865
+
866
+ <input type="file" id="logoFile" accept=".svg,image/svg+xml" />
867
+ <button class="btn-primary mt-1 mb-1" @click=${() => {
868
+ const input = this.shadowRoot?.querySelector("#logoFile");
869
+ if (input.files?.[0]) this.handleUpload("logo.svg", input.files[0]);
870
+ }}>Upload logo.svg</button>
871
+
872
+ <div class="info-box">
873
+ <strong>Tip:</strong> Use an SVG with transparent background. The logo will automatically adapt to light/dark themes.
874
+ </div>
875
+ </div>
876
+ `;
877
+ }
878
+ render() {
879
+ if (!this.isAuthenticated) {
880
+ return html`
881
+ <div class="container">
882
+ <div class="login-box">
883
+ <h2>Admin Login</h2>
884
+ <p>Enter your API key to manage content</p>
885
+ <form @submit=${this.handleLogin}>
886
+ <input type="password" id="apiKey" placeholder="API Key" />
887
+ <button type="submit" class="btn-primary">Login</button>
888
+ </form>
889
+ </div>
890
+ </div>
891
+ `;
892
+ }
893
+ return html`
894
+ <div class="container">
895
+ <div class="header">
896
+ <h1>Content Manager</h1>
897
+ <button class="btn-secondary" @click=${() => this.handleClearCache()}>Clear Cache</button>
898
+ </div>
899
+
900
+ <div class="nav-tabs">
901
+ <button class="nav-tab ${this.activeSection === "home" ? "active" : ""}"
902
+ @click=${() => this.activeSection = "home"}>Home</button>
903
+ <button class="nav-tab ${this.activeSection === "profile" ? "active" : ""}"
904
+ @click=${() => this.activeSection = "profile"}>Profile</button>
905
+ <button class="nav-tab ${this.activeSection === "aboutme" ? "active" : ""}"
906
+ @click=${() => this.activeSection = "aboutme"}>About Me</button>
907
+ <button class="nav-tab ${this.activeSection === "blogs" ? "active" : ""}"
908
+ @click=${() => this.activeSection = "blogs"}>Blogs</button>
909
+ <button class="nav-tab ${this.activeSection === "stories" ? "active" : ""}"
910
+ @click=${() => this.activeSection = "stories"}>Stories</button>
911
+ <button class="nav-tab ${this.activeSection === "images" ? "active" : ""}"
912
+ @click=${() => this.activeSection = "images"}>Images</button>
913
+ <button class="nav-tab ${this.activeSection === "logo" ? "active" : ""}"
914
+ @click=${() => this.activeSection = "logo"}>Logo</button>
915
+ <button class="nav-tab ${this.activeSection === "static" ? "active" : ""}"
916
+ @click=${() => {
917
+ this.activeSection = "static";
918
+ this.fetchStaticDetails();
919
+ }}>Site Settings</button>
920
+ </div>
921
+
922
+ ${this.statusMessage ? html`
923
+ <div class="status-message ${this.statusMessage.includes("successful") || this.statusMessage.includes("cleared") ? "success" : this.statusMessage.includes("failed") || this.statusMessage.includes("Error") ? "error" : ""}">
924
+ ${this.statusMessage}
925
+ </div>
926
+ ` : ""}
927
+
928
+ ${this.activeSection === "home" ? this.renderHomeSection() : ""}
929
+ ${this.activeSection === "profile" ? this.renderProfileSection() : ""}
930
+ ${this.activeSection === "aboutme" ? this.renderAboutMeSection() : ""}
931
+ ${this.activeSection === "blogs" ? this.renderBlogsSection() : ""}
932
+ ${this.activeSection === "stories" ? this.renderStoriesSection() : ""}
933
+ ${this.activeSection === "images" ? this.renderImagesSection() : ""}
934
+ ${this.activeSection === "logo" ? this.renderLogoSection() : ""}
935
+ ${this.activeSection === "static" ? this.renderStaticSection() : ""}
936
+ </div>
937
+ `;
938
+ }
939
+ renderStaticSection() {
940
+ return html`
941
+ <div class="section">
942
+ <h3>Site Settings</h3>
943
+ <p class="help-text">Manage your site's static details like title, footer links, etc.</p>
944
+
945
+ <div class="mb-1">
946
+ <label style="display:block;margin-bottom:4px;font-weight:500">Site Title</label>
947
+ <input type="text" id="siteTitle" .value=${this.staticDetails?.siteTitle || ""} />
948
+ </div>
949
+
950
+ <div class="mb-1">
951
+ <label style="display:block;margin-bottom:4px;font-weight:500">Copyright Text</label>
952
+ <input type="text" id="copyright" .value=${this.staticDetails?.copyright || ""} />
953
+ </div>
954
+
955
+ <div class="mb-1">
956
+ <label style="display:block;margin-bottom:4px;font-weight:500">LinkedIn URL</label>
957
+ <input type="text" id="linkedin" .value=${this.staticDetails?.linkedin || ""} />
958
+ </div>
959
+
960
+ <div class="mb-1">
961
+ <label style="display:block;margin-bottom:4px;font-weight:500">GitHub URL</label>
962
+ <input type="text" id="github" .value=${this.staticDetails?.github || ""} />
963
+ </div>
964
+
965
+ <div class="mb-1">
966
+ <label style="display:block;margin-bottom:4px;font-weight:500">Email</label>
967
+ <input type="text" id="email" .value=${this.staticDetails?.email || ""} />
968
+ </div>
969
+
970
+ <button class="btn-primary" @click=${async () => {
971
+ const siteTitle = this.shadowRoot?.querySelector("#siteTitle")?.value;
972
+ const copyright = this.shadowRoot?.querySelector("#copyright")?.value;
973
+ const linkedin = this.shadowRoot?.querySelector("#linkedin")?.value;
974
+ const github = this.shadowRoot?.querySelector("#github")?.value;
975
+ const email = this.shadowRoot?.querySelector("#email")?.value;
976
+ const data = {};
977
+ if (siteTitle) data.siteTitle = siteTitle;
978
+ if (copyright) data.copyright = copyright;
979
+ if (linkedin) data.linkedin = linkedin;
980
+ if (github) data.github = github;
981
+ if (email) data.email = email;
982
+ try {
983
+ const url = `${this.apiUrl}/content/staticdetails.json`;
984
+ const res = await fetch(url, {
985
+ method: "PUT",
986
+ headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
987
+ body: JSON.stringify(data)
988
+ });
989
+ if (res.ok) {
990
+ this.statusMessage = "Settings saved!";
991
+ this.fetchContent();
992
+ } else {
993
+ this.statusMessage = "Failed to save settings.";
994
+ }
995
+ } catch (e2) {
996
+ this.statusMessage = "Error saving settings.";
997
+ }
998
+ }}>Save Settings</button>
999
+ </div>
1000
+ `;
1001
+ }
1002
+ }
1003
+ _init$4 = __decoratorStart$4(_a$4);
1004
+ _apiKey = /* @__PURE__ */ new WeakMap();
1005
+ _isAuthenticated = /* @__PURE__ */ new WeakMap();
1006
+ _contentList = /* @__PURE__ */ new WeakMap();
1007
+ _statusMessage = /* @__PURE__ */ new WeakMap();
1008
+ _activeSection = /* @__PURE__ */ new WeakMap();
1009
+ _staticDetails = /* @__PURE__ */ new WeakMap();
1010
+ __decorateElement$4(_init$4, 4, "apiKey", _apiKey_dec, AdminPortal, _apiKey);
1011
+ __decorateElement$4(_init$4, 4, "isAuthenticated", _isAuthenticated_dec, AdminPortal, _isAuthenticated);
1012
+ __decorateElement$4(_init$4, 4, "contentList", _contentList_dec, AdminPortal, _contentList);
1013
+ __decorateElement$4(_init$4, 4, "statusMessage", _statusMessage_dec, AdminPortal, _statusMessage);
1014
+ __decorateElement$4(_init$4, 4, "activeSection", _activeSection_dec, AdminPortal, _activeSection);
1015
+ __decorateElement$4(_init$4, 4, "staticDetails", _staticDetails_dec, AdminPortal, _staticDetails);
1016
+ AdminPortal = __decorateElement$4(_init$4, 0, "AdminPortal", _AdminPortal_decorators, AdminPortal);
1017
+ AdminPortal.styles = adminStyles;
1018
+ __runInitializers$4(_init$4, 1, AdminPortal);
1019
+ const bannerStyles = css`
1020
+ :host {
1021
+ display: block;
1022
+ width: 100%;
1023
+ box-sizing: border-box;
1024
+ font-family: Arial, sans-serif;
1025
+ color: var(--text-color);
1026
+ background-color: var(--background-color);
1027
+ }
1028
+
1029
+ .banner,
1030
+ .banner-component {
1031
+ display: flex;
1032
+ flex-direction: row;
1033
+ justify-content: space-between;
1034
+ align-items: center;
1035
+ padding: 1rem 2rem;
1036
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1037
+ transition: background-color 0.3s, color 0.3s;
1038
+ background-color: var(--background-color);
1039
+ color: var(--text-color);
1040
+ }
1041
+
1042
+ .header-content {
1043
+ display: flex;
1044
+ align-items: center;
1045
+ margin-bottom: 0;
1046
+ margin-right: auto;
1047
+ }
1048
+
1049
+ .logo {
1050
+ height: 50px;
1051
+ margin-right: 1rem;
1052
+ width: auto;
1053
+ }
1054
+
1055
+ /* Logo dark mode - invert colors for better contrast */
1056
+ [data-theme="dark"] .logo {
1057
+ filter: brightness(0.85) invert(1);
1058
+ }
1059
+
1060
+ h1 {
1061
+ margin: 0;
1062
+ font-size: 1.8em;
1063
+ font-weight: 600;
1064
+ color: var(--text-color);
1065
+ }
1066
+
1067
+ .nav-and-theme {
1068
+ display: flex;
1069
+ align-items: center;
1070
+ gap: 1rem;
1071
+ }
1072
+
1073
+ nav {
1074
+ display: flex;
1075
+ align-items: center;
1076
+ padding: 0 1rem;
1077
+ gap: 10px;
1078
+ }
1079
+
1080
+ nav a {
1081
+ text-decoration: none;
1082
+ color: var(--nav-link-color, #333);
1083
+ padding: 0.5rem 1rem;
1084
+ border-radius: 5px;
1085
+ transition: background-color 0.3s ease, color 0.3s ease;
1086
+ }
1087
+
1088
+ nav a:hover {
1089
+ background-color: var(--nav-link-hover-bg, #e2e6ea);
1090
+ text-decoration: none;
1091
+ }
1092
+
1093
+ @media (max-width: 768px) {
1094
+ .banner,
1095
+ .banner-component {
1096
+ flex-direction: column;
1097
+ gap: 1rem;
1098
+ padding: 1rem;
1099
+ }
1100
+
1101
+ .header-content {
1102
+ margin-right: 0;
1103
+ justify-content: center;
1104
+ }
1105
+
1106
+ nav {
1107
+ flex-wrap: wrap;
1108
+ justify-content: center;
1109
+ }
1110
+ }
1111
+ `;
1112
+ var __create$3 = Object.create;
1113
+ var __defProp$3 = Object.defineProperty;
1114
+ var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
1115
+ var __knownSymbol$3 = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
1116
+ var __typeError$3 = (msg) => {
1117
+ throw TypeError(msg);
1118
+ };
1119
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1120
+ var __name$3 = (target, value) => __defProp$3(target, "name", { value, configurable: true });
1121
+ var __decoratorStart$3 = (base) => [, , , __create$3(base?.[__knownSymbol$3("metadata")] ?? null)];
1122
+ var __decoratorStrings$3 = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
1123
+ var __expectFn$3 = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError$3("Function expected") : fn;
1124
+ var __decoratorContext$3 = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings$3[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError$3("Already initialized") : fns.push(__expectFn$3(fn || null)) });
1125
+ var __decoratorMetadata$3 = (array, target) => __defNormalProp$3(target, __knownSymbol$3("metadata"), array[3]);
1126
+ var __runInitializers$3 = (array, flags, self, value) => {
1127
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) fns[i2].call(self);
1128
+ return value;
1129
+ };
1130
+ var __decorateElement$3 = (array, flags, name, decorators, target, extra) => {
1131
+ var it, done, ctx, k2 = flags & 7, p2 = false;
1132
+ var j = 0;
1133
+ var extraInitializers = array[j] || (array[j] = []);
1134
+ var desc = k2 && (target = target.prototype, k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc$3(target, name));
1135
+ __name$3(target, name);
1136
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
1137
+ ctx = __decoratorContext$3(k2, name, done = {}, array[3], extraInitializers);
1138
+ it = (0, decorators[i2])(target, ctx), done._ = 1;
1139
+ __expectFn$3(it) && (target = it);
1140
+ }
1141
+ return __decoratorMetadata$3(array, target), desc && __defProp$3(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
1142
+ };
1143
+ var _MyBanner_decorators, _init$3, _a$3;
1144
+ _MyBanner_decorators = [customElement("my-banner")];
1145
+ const _MyBanner = class _MyBanner extends (_a$3 = LitElement) {
1146
+ constructor() {
1147
+ super();
1148
+ this.header = "My App";
1149
+ this.logo = "";
1150
+ }
1151
+ render() {
1152
+ return html`
1153
+ <header class="banner banner-component">
1154
+ <div class="header-content">
1155
+ ${this.logo ? html`<img src="${this.logo}" alt="Logo" class="logo" />` : ""}
1156
+ <h1>${this.header}</h1>
1157
+ </div>
1158
+ <div class="nav-and-theme">
1159
+ <slot name="nav-links"></slot>
1160
+ <slot name="theme-switcher"></slot>
1161
+ </div>
1162
+ </header>
1163
+ `;
1164
+ }
1165
+ };
1166
+ _MyBanner.styles = bannerStyles;
1167
+ _MyBanner.properties = {
1168
+ header: { type: String },
1169
+ logo: { type: String }
1170
+ };
1171
+ let MyBanner = _MyBanner;
1172
+ _init$3 = __decoratorStart$3(_a$3);
1173
+ MyBanner = __decorateElement$3(_init$3, 0, "MyBanner", _MyBanner_decorators, MyBanner);
1174
+ __runInitializers$3(_init$3, 1, MyBanner);
1175
+ const footerStyles = css`
1176
+ :host {
1177
+ display: flex;
1178
+ align-items: center;
1179
+ justify-content: space-between;
1180
+ padding: 1rem 2rem;
1181
+ background: var(--background-color);
1182
+ color: var(--text-color);
1183
+ border-top: 1px solid var(--nav-link-hover-bg);
1184
+ flex-wrap: wrap;
1185
+ }
1186
+
1187
+ .footer-content {
1188
+ display: flex;
1189
+ flex-direction: column;
1190
+ align-items: flex-start;
1191
+ }
1192
+
1193
+ .links {
1194
+ display: flex;
1195
+ gap: 1rem;
1196
+ margin-top: 0.5rem;
1197
+ }
1198
+
1199
+ .links a {
1200
+ color: inherit;
1201
+ text-decoration: none;
1202
+ padding: 0.25rem 0.5rem;
1203
+ border-radius: 4px;
1204
+ transition: background-color 0.3s ease;
1205
+ }
1206
+
1207
+ .links a:hover {
1208
+ background-color: rgba(0, 0, 0, 0.1);
1209
+ }
1210
+
1211
+ @media (min-width: 768px) {
1212
+ .footer-content {
1213
+ flex-direction: row;
1214
+ align-items: center;
1215
+ width: 100%;
1216
+ justify-content: space-between;
1217
+ }
1218
+ .links {
1219
+ margin-top: 0;
1220
+ }
1221
+ }
1222
+ `;
1223
+ var __create$2 = Object.create;
1224
+ var __defProp$2 = Object.defineProperty;
1225
+ var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
1226
+ var __knownSymbol$2 = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
1227
+ var __typeError$2 = (msg) => {
1228
+ throw TypeError(msg);
1229
+ };
1230
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1231
+ var __name$2 = (target, value) => __defProp$2(target, "name", { value, configurable: true });
1232
+ var __decoratorStart$2 = (base) => [, , , __create$2(base?.[__knownSymbol$2("metadata")] ?? null)];
1233
+ var __decoratorStrings$2 = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
1234
+ var __expectFn$2 = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError$2("Function expected") : fn;
1235
+ var __decoratorContext$2 = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings$2[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError$2("Already initialized") : fns.push(__expectFn$2(fn || null)) });
1236
+ var __decoratorMetadata$2 = (array, target) => __defNormalProp$2(target, __knownSymbol$2("metadata"), array[3]);
1237
+ var __runInitializers$2 = (array, flags, self, value) => {
1238
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) flags & 1 ? fns[i2].call(self) : value = fns[i2].call(self, value);
1239
+ return value;
1240
+ };
1241
+ var __decorateElement$2 = (array, flags, name, decorators, target, extra) => {
1242
+ var fn, it, done, ctx, access, k2 = flags & 7, s2 = !!(flags & 8), p2 = !!(flags & 16);
1243
+ var j = k2 > 3 ? array.length + 1 : k2 ? s2 ? 1 : 2 : 0, key = __decoratorStrings$2[k2 + 5];
1244
+ var initializers = k2 > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
1245
+ var desc = k2 && (!p2 && !s2 && (target = target.prototype), k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc$2(k2 < 4 ? target : { get [name]() {
1246
+ return __privateGet$2(this, extra);
1247
+ }, set [name](x) {
1248
+ return __privateSet$2(this, extra, x);
1249
+ } }, name));
1250
+ k2 ? p2 && k2 < 4 && __name$2(extra, (k2 > 2 ? "set " : k2 > 1 ? "get " : "") + name) : __name$2(target, name);
1251
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
1252
+ ctx = __decoratorContext$2(k2, name, done = {}, array[3], extraInitializers);
1253
+ if (k2) {
1254
+ ctx.static = s2, ctx.private = p2, access = ctx.access = { has: p2 ? (x) => __privateIn$2(target, x) : (x) => name in x };
1255
+ if (k2 ^ 3) access.get = p2 ? (x) => (k2 ^ 1 ? __privateGet$2 : __privateMethod$2)(x, target, k2 ^ 4 ? extra : desc.get) : (x) => x[name];
1256
+ if (k2 > 2) access.set = p2 ? (x, y2) => __privateSet$2(x, target, y2, k2 ^ 4 ? extra : desc.set) : (x, y2) => x[name] = y2;
1257
+ }
1258
+ it = (0, decorators[i2])(k2 ? k2 < 4 ? p2 ? extra : desc[key] : k2 > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
1259
+ if (k2 ^ 4 || it === void 0) __expectFn$2(it) && (k2 > 4 ? initializers.unshift(it) : k2 ? p2 ? extra = it : desc[key] = it : target = it);
1260
+ else if (typeof it !== "object" || it === null) __typeError$2("Object expected");
1261
+ else __expectFn$2(fn = it.get) && (desc.get = fn), __expectFn$2(fn = it.set) && (desc.set = fn), __expectFn$2(fn = it.init) && initializers.unshift(fn);
1262
+ }
1263
+ return k2 || __decoratorMetadata$2(array, target), desc && __defProp$2(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
1264
+ };
1265
+ var __accessCheck$2 = (obj, member, msg) => member.has(obj) || __typeError$2("Cannot " + msg);
1266
+ var __privateIn$2 = (member, obj) => Object(obj) !== obj ? __typeError$2('Cannot use the "in" operator on this value') : member.has(obj);
1267
+ var __privateGet$2 = (obj, member, getter) => (__accessCheck$2(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1268
+ var __privateAdd$2 = (obj, member, value) => member.has(obj) ? __typeError$2("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1269
+ var __privateSet$2 = (obj, member, value, setter) => (__accessCheck$2(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
1270
+ var __privateMethod$2 = (obj, member, method) => (__accessCheck$2(obj, member, "access private method"), method);
1271
+ var _footerLinks_dec, _copyright_dec, _a$2, _FooterComponent_decorators, _init$2, _copyright, _footerLinks;
1272
+ _FooterComponent_decorators = [customElement("my-footer")];
1273
+ class FooterComponent extends (_a$2 = LitElement, _copyright_dec = [property({ type: String })], _footerLinks_dec = [property({ type: Array })], _a$2) {
1274
+ constructor() {
1275
+ super(...arguments);
1276
+ __privateAdd$2(this, _copyright, __runInitializers$2(_init$2, 8, this, "")), __runInitializers$2(_init$2, 11, this);
1277
+ __privateAdd$2(this, _footerLinks, __runInitializers$2(_init$2, 12, this, [])), __runInitializers$2(_init$2, 15, this);
1278
+ }
1279
+ render() {
1280
+ return html`
1281
+ <div class="footer-content">
1282
+ <span>&copy; ${this.copyright}</span>
1283
+ <span class="links">
1284
+ ${(this.footerLinks || []).map(
1285
+ (link) => {
1286
+ const isExternal = link.link.startsWith("http") || link.link.startsWith("mailto:");
1287
+ return html`<a
1288
+ href="${link.link}"
1289
+ target="${isExternal ? "_blank" : "_self"}"
1290
+ rel="${isExternal ? "noopener noreferrer" : ""}"
1291
+ >${link.text}</a>`;
1292
+ }
1293
+ )}
1294
+ </span>
1295
+ </div>
1296
+ `;
1297
+ }
1298
+ }
1299
+ _init$2 = __decoratorStart$2(_a$2);
1300
+ _copyright = /* @__PURE__ */ new WeakMap();
1301
+ _footerLinks = /* @__PURE__ */ new WeakMap();
1302
+ __decorateElement$2(_init$2, 4, "copyright", _copyright_dec, FooterComponent, _copyright);
1303
+ __decorateElement$2(_init$2, 4, "footerLinks", _footerLinks_dec, FooterComponent, _footerLinks);
1304
+ FooterComponent = __decorateElement$2(_init$2, 0, "FooterComponent", _FooterComponent_decorators, FooterComponent);
1305
+ FooterComponent.styles = footerStyles;
1306
+ __runInitializers$2(_init$2, 1, FooterComponent);
1307
+ const t$1 = globalThis, i$1 = (t2) => t2, s = t$1.trustedTypes, e$2 = s ? s.createPolicy("lit-html", { createHTML: (t2) => t2 }) : void 0, h = "$lit$", o$1 = `lit$${Math.random().toFixed(9).slice(2)}$`, n = "?" + o$1, r = `<${n}>`, l = document, c = () => l.createComment(""), a = (t2) => null === t2 || "object" != typeof t2 && "function" != typeof t2, u = Array.isArray, d = (t2) => u(t2) || "function" == typeof t2?.[Symbol.iterator], f = "[ \n\f\r]", v = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, _ = /-->/g, m = />/g, p = RegExp(`>|${f}(?:([^\\s"'>=/]+)(${f}*=${f}*(?:[^
1308
+ \f\r"'\`<>=]|("|')|))|$)`, "g"), g = /'/g, $ = /"/g, y = /^(?:script|style|textarea|title)$/i, E = /* @__PURE__ */ Symbol.for("lit-noChange"), A = /* @__PURE__ */ Symbol.for("lit-nothing"), C = /* @__PURE__ */ new WeakMap(), P = l.createTreeWalker(l, 129);
1309
+ function V(t2, i2) {
1310
+ if (!u(t2) || !t2.hasOwnProperty("raw")) throw Error("invalid template strings array");
1311
+ return void 0 !== e$2 ? e$2.createHTML(i2) : i2;
1312
+ }
1313
+ const N = (t2, i2) => {
1314
+ const s2 = t2.length - 1, e2 = [];
1315
+ let n2, l2 = 2 === i2 ? "<svg>" : 3 === i2 ? "<math>" : "", c2 = v;
1316
+ for (let i3 = 0; i3 < s2; i3++) {
1317
+ const s3 = t2[i3];
1318
+ let a2, u2, d2 = -1, f2 = 0;
1319
+ for (; f2 < s3.length && (c2.lastIndex = f2, u2 = c2.exec(s3), null !== u2); ) f2 = c2.lastIndex, c2 === v ? "!--" === u2[1] ? c2 = _ : void 0 !== u2[1] ? c2 = m : void 0 !== u2[2] ? (y.test(u2[2]) && (n2 = RegExp("</" + u2[2], "g")), c2 = p) : void 0 !== u2[3] && (c2 = p) : c2 === p ? ">" === u2[0] ? (c2 = n2 ?? v, d2 = -1) : void 0 === u2[1] ? d2 = -2 : (d2 = c2.lastIndex - u2[2].length, a2 = u2[1], c2 = void 0 === u2[3] ? p : '"' === u2[3] ? $ : g) : c2 === $ || c2 === g ? c2 = p : c2 === _ || c2 === m ? c2 = v : (c2 = p, n2 = void 0);
1320
+ const x = c2 === p && t2[i3 + 1].startsWith("/>") ? " " : "";
1321
+ l2 += c2 === v ? s3 + r : d2 >= 0 ? (e2.push(a2), s3.slice(0, d2) + h + s3.slice(d2) + o$1 + x) : s3 + o$1 + (-2 === d2 ? i3 : x);
1322
+ }
1323
+ return [V(t2, l2 + (t2[s2] || "<?>") + (2 === i2 ? "</svg>" : 3 === i2 ? "</math>" : "")), e2];
1324
+ };
1325
+ class S {
1326
+ constructor({ strings: t2, _$litType$: i2 }, e2) {
1327
+ let r2;
1328
+ this.parts = [];
1329
+ let l2 = 0, a2 = 0;
1330
+ const u2 = t2.length - 1, d2 = this.parts, [f2, v2] = N(t2, i2);
1331
+ if (this.el = S.createElement(f2, e2), P.currentNode = this.el.content, 2 === i2 || 3 === i2) {
1332
+ const t3 = this.el.content.firstChild;
1333
+ t3.replaceWith(...t3.childNodes);
1334
+ }
1335
+ for (; null !== (r2 = P.nextNode()) && d2.length < u2; ) {
1336
+ if (1 === r2.nodeType) {
1337
+ if (r2.hasAttributes()) for (const t3 of r2.getAttributeNames()) if (t3.endsWith(h)) {
1338
+ const i3 = v2[a2++], s2 = r2.getAttribute(t3).split(o$1), e3 = /([.?@])?(.*)/.exec(i3);
1339
+ d2.push({ type: 1, index: l2, name: e3[2], strings: s2, ctor: "." === e3[1] ? I : "?" === e3[1] ? L : "@" === e3[1] ? z : H }), r2.removeAttribute(t3);
1340
+ } else t3.startsWith(o$1) && (d2.push({ type: 6, index: l2 }), r2.removeAttribute(t3));
1341
+ if (y.test(r2.tagName)) {
1342
+ const t3 = r2.textContent.split(o$1), i3 = t3.length - 1;
1343
+ if (i3 > 0) {
1344
+ r2.textContent = s ? s.emptyScript : "";
1345
+ for (let s2 = 0; s2 < i3; s2++) r2.append(t3[s2], c()), P.nextNode(), d2.push({ type: 2, index: ++l2 });
1346
+ r2.append(t3[i3], c());
1347
+ }
1348
+ }
1349
+ } else if (8 === r2.nodeType) if (r2.data === n) d2.push({ type: 2, index: l2 });
1350
+ else {
1351
+ let t3 = -1;
1352
+ for (; -1 !== (t3 = r2.data.indexOf(o$1, t3 + 1)); ) d2.push({ type: 7, index: l2 }), t3 += o$1.length - 1;
1353
+ }
1354
+ l2++;
1355
+ }
1356
+ }
1357
+ static createElement(t2, i2) {
1358
+ const s2 = l.createElement("template");
1359
+ return s2.innerHTML = t2, s2;
1360
+ }
1361
+ }
1362
+ function M(t2, i2, s2 = t2, e2) {
1363
+ if (i2 === E) return i2;
1364
+ let h2 = void 0 !== e2 ? s2._$Co?.[e2] : s2._$Cl;
1365
+ const o2 = a(i2) ? void 0 : i2._$litDirective$;
1366
+ return h2?.constructor !== o2 && (h2?._$AO?.(false), void 0 === o2 ? h2 = void 0 : (h2 = new o2(t2), h2._$AT(t2, s2, e2)), void 0 !== e2 ? (s2._$Co ??= [])[e2] = h2 : s2._$Cl = h2), void 0 !== h2 && (i2 = M(t2, h2._$AS(t2, i2.values), h2, e2)), i2;
1367
+ }
1368
+ class R {
1369
+ constructor(t2, i2) {
1370
+ this._$AV = [], this._$AN = void 0, this._$AD = t2, this._$AM = i2;
1371
+ }
1372
+ get parentNode() {
1373
+ return this._$AM.parentNode;
1374
+ }
1375
+ get _$AU() {
1376
+ return this._$AM._$AU;
1377
+ }
1378
+ u(t2) {
1379
+ const { el: { content: i2 }, parts: s2 } = this._$AD, e2 = (t2?.creationScope ?? l).importNode(i2, true);
1380
+ P.currentNode = e2;
1381
+ let h2 = P.nextNode(), o2 = 0, n2 = 0, r2 = s2[0];
1382
+ for (; void 0 !== r2; ) {
1383
+ if (o2 === r2.index) {
1384
+ let i3;
1385
+ 2 === r2.type ? i3 = new k(h2, h2.nextSibling, this, t2) : 1 === r2.type ? i3 = new r2.ctor(h2, r2.name, r2.strings, this, t2) : 6 === r2.type && (i3 = new Z(h2, this, t2)), this._$AV.push(i3), r2 = s2[++n2];
1386
+ }
1387
+ o2 !== r2?.index && (h2 = P.nextNode(), o2++);
1388
+ }
1389
+ return P.currentNode = l, e2;
1390
+ }
1391
+ p(t2) {
1392
+ let i2 = 0;
1393
+ for (const s2 of this._$AV) void 0 !== s2 && (void 0 !== s2.strings ? (s2._$AI(t2, s2, i2), i2 += s2.strings.length - 2) : s2._$AI(t2[i2])), i2++;
1394
+ }
1395
+ }
1396
+ class k {
1397
+ get _$AU() {
1398
+ return this._$AM?._$AU ?? this._$Cv;
1399
+ }
1400
+ constructor(t2, i2, s2, e2) {
1401
+ this.type = 2, this._$AH = A, this._$AN = void 0, this._$AA = t2, this._$AB = i2, this._$AM = s2, this.options = e2, this._$Cv = e2?.isConnected ?? true;
1402
+ }
1403
+ get parentNode() {
1404
+ let t2 = this._$AA.parentNode;
1405
+ const i2 = this._$AM;
1406
+ return void 0 !== i2 && 11 === t2?.nodeType && (t2 = i2.parentNode), t2;
1407
+ }
1408
+ get startNode() {
1409
+ return this._$AA;
1410
+ }
1411
+ get endNode() {
1412
+ return this._$AB;
1413
+ }
1414
+ _$AI(t2, i2 = this) {
1415
+ t2 = M(this, t2, i2), a(t2) ? t2 === A || null == t2 || "" === t2 ? (this._$AH !== A && this._$AR(), this._$AH = A) : t2 !== this._$AH && t2 !== E && this._(t2) : void 0 !== t2._$litType$ ? this.$(t2) : void 0 !== t2.nodeType ? this.T(t2) : d(t2) ? this.k(t2) : this._(t2);
1416
+ }
1417
+ O(t2) {
1418
+ return this._$AA.parentNode.insertBefore(t2, this._$AB);
1419
+ }
1420
+ T(t2) {
1421
+ this._$AH !== t2 && (this._$AR(), this._$AH = this.O(t2));
1422
+ }
1423
+ _(t2) {
1424
+ this._$AH !== A && a(this._$AH) ? this._$AA.nextSibling.data = t2 : this.T(l.createTextNode(t2)), this._$AH = t2;
1425
+ }
1426
+ $(t2) {
1427
+ const { values: i2, _$litType$: s2 } = t2, e2 = "number" == typeof s2 ? this._$AC(t2) : (void 0 === s2.el && (s2.el = S.createElement(V(s2.h, s2.h[0]), this.options)), s2);
1428
+ if (this._$AH?._$AD === e2) this._$AH.p(i2);
1429
+ else {
1430
+ const t3 = new R(e2, this), s3 = t3.u(this.options);
1431
+ t3.p(i2), this.T(s3), this._$AH = t3;
1432
+ }
1433
+ }
1434
+ _$AC(t2) {
1435
+ let i2 = C.get(t2.strings);
1436
+ return void 0 === i2 && C.set(t2.strings, i2 = new S(t2)), i2;
1437
+ }
1438
+ k(t2) {
1439
+ u(this._$AH) || (this._$AH = [], this._$AR());
1440
+ const i2 = this._$AH;
1441
+ let s2, e2 = 0;
1442
+ for (const h2 of t2) e2 === i2.length ? i2.push(s2 = new k(this.O(c()), this.O(c()), this, this.options)) : s2 = i2[e2], s2._$AI(h2), e2++;
1443
+ e2 < i2.length && (this._$AR(s2 && s2._$AB.nextSibling, e2), i2.length = e2);
1444
+ }
1445
+ _$AR(t2 = this._$AA.nextSibling, s2) {
1446
+ for (this._$AP?.(false, true, s2); t2 !== this._$AB; ) {
1447
+ const s3 = i$1(t2).nextSibling;
1448
+ i$1(t2).remove(), t2 = s3;
1449
+ }
1450
+ }
1451
+ setConnected(t2) {
1452
+ void 0 === this._$AM && (this._$Cv = t2, this._$AP?.(t2));
1453
+ }
1454
+ }
1455
+ class H {
1456
+ get tagName() {
1457
+ return this.element.tagName;
1458
+ }
1459
+ get _$AU() {
1460
+ return this._$AM._$AU;
1461
+ }
1462
+ constructor(t2, i2, s2, e2, h2) {
1463
+ this.type = 1, this._$AH = A, this._$AN = void 0, this.element = t2, this.name = i2, this._$AM = e2, this.options = h2, s2.length > 2 || "" !== s2[0] || "" !== s2[1] ? (this._$AH = Array(s2.length - 1).fill(new String()), this.strings = s2) : this._$AH = A;
1464
+ }
1465
+ _$AI(t2, i2 = this, s2, e2) {
1466
+ const h2 = this.strings;
1467
+ let o2 = false;
1468
+ if (void 0 === h2) t2 = M(this, t2, i2, 0), o2 = !a(t2) || t2 !== this._$AH && t2 !== E, o2 && (this._$AH = t2);
1469
+ else {
1470
+ const e3 = t2;
1471
+ let n2, r2;
1472
+ for (t2 = h2[0], n2 = 0; n2 < h2.length - 1; n2++) r2 = M(this, e3[s2 + n2], i2, n2), r2 === E && (r2 = this._$AH[n2]), o2 ||= !a(r2) || r2 !== this._$AH[n2], r2 === A ? t2 = A : t2 !== A && (t2 += (r2 ?? "") + h2[n2 + 1]), this._$AH[n2] = r2;
1473
+ }
1474
+ o2 && !e2 && this.j(t2);
1475
+ }
1476
+ j(t2) {
1477
+ t2 === A ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, t2 ?? "");
1478
+ }
1479
+ }
1480
+ class I extends H {
1481
+ constructor() {
1482
+ super(...arguments), this.type = 3;
1483
+ }
1484
+ j(t2) {
1485
+ this.element[this.name] = t2 === A ? void 0 : t2;
1486
+ }
1487
+ }
1488
+ class L extends H {
1489
+ constructor() {
1490
+ super(...arguments), this.type = 4;
1491
+ }
1492
+ j(t2) {
1493
+ this.element.toggleAttribute(this.name, !!t2 && t2 !== A);
1494
+ }
1495
+ }
1496
+ class z extends H {
1497
+ constructor(t2, i2, s2, e2, h2) {
1498
+ super(t2, i2, s2, e2, h2), this.type = 5;
1499
+ }
1500
+ _$AI(t2, i2 = this) {
1501
+ if ((t2 = M(this, t2, i2, 0) ?? A) === E) return;
1502
+ const s2 = this._$AH, e2 = t2 === A && s2 !== A || t2.capture !== s2.capture || t2.once !== s2.once || t2.passive !== s2.passive, h2 = t2 !== A && (s2 === A || e2);
1503
+ e2 && this.element.removeEventListener(this.name, this, s2), h2 && this.element.addEventListener(this.name, this, t2), this._$AH = t2;
1504
+ }
1505
+ handleEvent(t2) {
1506
+ "function" == typeof this._$AH ? this._$AH.call(this.options?.host ?? this.element, t2) : this._$AH.handleEvent(t2);
1507
+ }
1508
+ }
1509
+ class Z {
1510
+ constructor(t2, i2, s2) {
1511
+ this.element = t2, this.type = 6, this._$AN = void 0, this._$AM = i2, this.options = s2;
1512
+ }
1513
+ get _$AU() {
1514
+ return this._$AM._$AU;
1515
+ }
1516
+ _$AI(t2) {
1517
+ M(this, t2);
1518
+ }
1519
+ }
1520
+ const B = t$1.litHtmlPolyfillSupport;
1521
+ B?.(S, k), (t$1.litHtmlVersions ??= []).push("3.3.2");
1522
+ const t = { CHILD: 2 }, e$1 = (t2) => (...e2) => ({ _$litDirective$: t2, values: e2 });
1523
+ class i {
1524
+ constructor(t2) {
1525
+ }
1526
+ get _$AU() {
1527
+ return this._$AM._$AU;
1528
+ }
1529
+ _$AT(t2, e2, i2) {
1530
+ this._$Ct = t2, this._$AM = e2, this._$Ci = i2;
1531
+ }
1532
+ _$AS(t2, e2) {
1533
+ return this.update(t2, e2);
1534
+ }
1535
+ update(t2, e2) {
1536
+ return this.render(...e2);
1537
+ }
1538
+ }
1539
+ class e extends i {
1540
+ constructor(i2) {
1541
+ if (super(i2), this.it = A, i2.type !== t.CHILD) throw Error(this.constructor.directiveName + "() can only be used in child bindings");
1542
+ }
1543
+ render(r2) {
1544
+ if (r2 === A || null == r2) return this._t = void 0, this.it = r2;
1545
+ if (r2 === E) return r2;
1546
+ if ("string" != typeof r2) throw Error(this.constructor.directiveName + "() called with a non-string value");
1547
+ if (r2 === this.it) return this._t;
1548
+ this.it = r2;
1549
+ const s2 = [r2];
1550
+ return s2.raw = s2, this._t = { _$litType$: this.constructor.resultType, strings: s2, values: [] };
1551
+ }
1552
+ }
1553
+ e.directiveName = "unsafeHTML", e.resultType = 1;
1554
+ const o = e$1(e);
1555
+ const blogviewerStyles = css`
1556
+ :host {
1557
+ display: block;
1558
+ }
1559
+
1560
+ .tags {
1561
+ display: flex;
1562
+ gap: 0.5rem;
1563
+ flex-wrap: wrap;
1564
+ margin-top: 1rem;
1565
+ }
1566
+
1567
+ .tag {
1568
+ background: var(--nav-link-hover-bg, #f0f0f0);
1569
+ color: var(--text-color, #333);
1570
+ padding: 0.25rem 0.5rem;
1571
+ border-radius: 4px;
1572
+ font-size: 0.875rem;
1573
+ border: 1px solid var(--border-color, transparent);
1574
+ }
1575
+ `;
1576
+ var __create$1 = Object.create;
1577
+ var __defProp$1 = Object.defineProperty;
1578
+ var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
1579
+ var __knownSymbol$1 = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
1580
+ var __typeError$1 = (msg) => {
1581
+ throw TypeError(msg);
1582
+ };
1583
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1584
+ var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true });
1585
+ var __decoratorStart$1 = (base) => [, , , __create$1(base?.[__knownSymbol$1("metadata")] ?? null)];
1586
+ var __decoratorStrings$1 = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
1587
+ var __expectFn$1 = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError$1("Function expected") : fn;
1588
+ var __decoratorContext$1 = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings$1[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError$1("Already initialized") : fns.push(__expectFn$1(fn || null)) });
1589
+ var __decoratorMetadata$1 = (array, target) => __defNormalProp$1(target, __knownSymbol$1("metadata"), array[3]);
1590
+ var __runInitializers$1 = (array, flags, self, value) => {
1591
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) flags & 1 ? fns[i2].call(self) : value = fns[i2].call(self, value);
1592
+ return value;
1593
+ };
1594
+ var __decorateElement$1 = (array, flags, name, decorators, target, extra) => {
1595
+ var fn, it, done, ctx, access, k2 = flags & 7, s2 = !!(flags & 8), p2 = !!(flags & 16);
1596
+ var j = k2 > 3 ? array.length + 1 : k2 ? s2 ? 1 : 2 : 0, key = __decoratorStrings$1[k2 + 5];
1597
+ var initializers = k2 > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
1598
+ var desc = k2 && (!p2 && !s2 && (target = target.prototype), k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc$1(k2 < 4 ? target : { get [name]() {
1599
+ return __privateGet$1(this, extra);
1600
+ }, set [name](x) {
1601
+ return __privateSet$1(this, extra, x);
1602
+ } }, name));
1603
+ k2 ? p2 && k2 < 4 && __name$1(extra, (k2 > 2 ? "set " : k2 > 1 ? "get " : "") + name) : __name$1(target, name);
1604
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
1605
+ ctx = __decoratorContext$1(k2, name, done = {}, array[3], extraInitializers);
1606
+ if (k2) {
1607
+ ctx.static = s2, ctx.private = p2, access = ctx.access = { has: p2 ? (x) => __privateIn$1(target, x) : (x) => name in x };
1608
+ if (k2 ^ 3) access.get = p2 ? (x) => (k2 ^ 1 ? __privateGet$1 : __privateMethod$1)(x, target, k2 ^ 4 ? extra : desc.get) : (x) => x[name];
1609
+ if (k2 > 2) access.set = p2 ? (x, y2) => __privateSet$1(x, target, y2, k2 ^ 4 ? extra : desc.set) : (x, y2) => x[name] = y2;
1610
+ }
1611
+ it = (0, decorators[i2])(k2 ? k2 < 4 ? p2 ? extra : desc[key] : k2 > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
1612
+ if (k2 ^ 4 || it === void 0) __expectFn$1(it) && (k2 > 4 ? initializers.unshift(it) : k2 ? p2 ? extra = it : desc[key] = it : target = it);
1613
+ else if (typeof it !== "object" || it === null) __typeError$1("Object expected");
1614
+ else __expectFn$1(fn = it.get) && (desc.get = fn), __expectFn$1(fn = it.set) && (desc.set = fn), __expectFn$1(fn = it.init) && initializers.unshift(fn);
1615
+ }
1616
+ return k2 || __decoratorMetadata$1(array, target), desc && __defProp$1(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
1617
+ };
1618
+ var __accessCheck$1 = (obj, member, msg) => member.has(obj) || __typeError$1("Cannot " + msg);
1619
+ var __privateIn$1 = (member, obj) => Object(obj) !== obj ? __typeError$1('Cannot use the "in" operator on this value') : member.has(obj);
1620
+ var __privateGet$1 = (obj, member, getter) => (__accessCheck$1(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1621
+ var __privateAdd$1 = (obj, member, value) => member.has(obj) ? __typeError$1("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1622
+ var __privateSet$1 = (obj, member, value, setter) => (__accessCheck$1(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
1623
+ var __privateMethod$1 = (obj, member, method) => (__accessCheck$1(obj, member, "access private method"), method);
1624
+ var _error_dec$1, _loading_dec$1, _blogPost_dec, _slug_dec$1, _a$1, _BlogViewer_decorators, _init$1, _slug$1, _blogPost, _loading$1, _error$1;
1625
+ const pipeline$1 = new MarkdownPipeline({
1626
+ imagePathPrefix: "images/",
1627
+ styleOptions: {
1628
+ classPrefix: "md-",
1629
+ addHeadingIds: true
1630
+ }
1631
+ });
1632
+ _BlogViewer_decorators = [customElement("my-blog-viewer")];
1633
+ class BlogViewer extends (_a$1 = LitElement, _slug_dec$1 = [property({ type: String })], _blogPost_dec = [state()], _loading_dec$1 = [state()], _error_dec$1 = [state()], _a$1) {
1634
+ constructor() {
1635
+ super(...arguments);
1636
+ __privateAdd$1(this, _slug$1, __runInitializers$1(_init$1, 8, this, "")), __runInitializers$1(_init$1, 11, this);
1637
+ __privateAdd$1(this, _blogPost, __runInitializers$1(_init$1, 12, this, null)), __runInitializers$1(_init$1, 15, this);
1638
+ __privateAdd$1(this, _loading$1, __runInitializers$1(_init$1, 16, this, true)), __runInitializers$1(_init$1, 19, this);
1639
+ __privateAdd$1(this, _error$1, __runInitializers$1(_init$1, 20, this, "")), __runInitializers$1(_init$1, 23, this);
1640
+ }
1641
+ get apiBaseUrl() {
1642
+ return "https://api.techieleader.com";
1643
+ }
1644
+ connectedCallback() {
1645
+ super.connectedCallback();
1646
+ if (this.slug) {
1647
+ this.loadBlog();
1648
+ }
1649
+ }
1650
+ updated(changedProperties) {
1651
+ if (changedProperties.has("slug") && this.slug) {
1652
+ this.loadBlog();
1653
+ }
1654
+ }
1655
+ loadBlog() {
1656
+ this.loading = true;
1657
+ this.error = "";
1658
+ console.log("[BlogViewer] Loading blog:", this.slug);
1659
+ fetch(`${this.apiBaseUrl}/api/blogs/${this.slug}`).then((res) => {
1660
+ console.log("[BlogViewer] Response status:", res.status);
1661
+ if (res.ok) return res.json();
1662
+ throw new Error("Failed to load blog");
1663
+ }).then((blog) => {
1664
+ console.log("[BlogViewer] Found blog:", blog?.title, "slug:", blog?.slug);
1665
+ if (blog && blog.content) {
1666
+ this.blogPost = blog;
1667
+ } else {
1668
+ this.error = "Blog content not found";
1669
+ }
1670
+ this.loading = false;
1671
+ }).catch((e2) => {
1672
+ console.error("[BlogViewer] Failed to load blog:", e2);
1673
+ this.error = "Failed to load blog";
1674
+ this.loading = false;
1675
+ });
1676
+ }
1677
+ render() {
1678
+ if (this.loading) {
1679
+ return html`<div class="blog-viewer"><div class="loading">Loading...</div></div>`;
1680
+ }
1681
+ if (this.error) {
1682
+ return html`<div class="blog-viewer"><div class="error">${this.error}</div></div>`;
1683
+ }
1684
+ if (!this.blogPost) {
1685
+ return html`<div class="blog-viewer"><div class="error">Blog not found</div></div>`;
1686
+ }
1687
+ const { title, date, tags, content } = this.blogPost;
1688
+ return html`
1689
+ <article class="blog-viewer">
1690
+ <h1>${title}</h1>
1691
+ <div class="meta">
1692
+ <span>${date}</span>
1693
+ </div>
1694
+ ${tags?.length ? html`
1695
+ <div class="tags">
1696
+ ${tags.map((tag) => html`<span class="tag">${tag}</span>`)}
1697
+ </div>
1698
+ ` : ""}
1699
+ <div class="content">
1700
+ ${o(this.renderMarkdown(content))}
1701
+ </div>
1702
+ </article>
1703
+ `;
1704
+ }
1705
+ renderMarkdown(content) {
1706
+ if (!content) return "";
1707
+ const nodes = pipeline$1.parse(content);
1708
+ return pipeline$1.render(nodes);
1709
+ }
1710
+ }
1711
+ _init$1 = __decoratorStart$1(_a$1);
1712
+ _slug$1 = /* @__PURE__ */ new WeakMap();
1713
+ _blogPost = /* @__PURE__ */ new WeakMap();
1714
+ _loading$1 = /* @__PURE__ */ new WeakMap();
1715
+ _error$1 = /* @__PURE__ */ new WeakMap();
1716
+ __decorateElement$1(_init$1, 4, "slug", _slug_dec$1, BlogViewer, _slug$1);
1717
+ __decorateElement$1(_init$1, 4, "blogPost", _blogPost_dec, BlogViewer, _blogPost);
1718
+ __decorateElement$1(_init$1, 4, "loading", _loading_dec$1, BlogViewer, _loading$1);
1719
+ __decorateElement$1(_init$1, 4, "error", _error_dec$1, BlogViewer, _error$1);
1720
+ BlogViewer = __decorateElement$1(_init$1, 0, "BlogViewer", _BlogViewer_decorators, BlogViewer);
1721
+ BlogViewer.styles = blogviewerStyles;
1722
+ __runInitializers$1(_init$1, 1, BlogViewer);
1723
+ const storyviewerStyles = css`
1724
+ :host {
1725
+ display: block;
1726
+ max-width: 800px;
1727
+ margin: 0 auto;
1728
+ }
1729
+
1730
+ .loading {
1731
+ text-align: center;
1732
+ padding: 2rem;
1733
+ }
1734
+
1735
+ .error {
1736
+ color: red;
1737
+ text-align: center;
1738
+ padding: 2rem;
1739
+ }
1740
+
1741
+ h1 {
1742
+ margin-bottom: 0.5rem;
1743
+ }
1744
+
1745
+ .meta {
1746
+ color: #666;
1747
+ margin-bottom: 2rem;
1748
+ }
1749
+
1750
+ .tags {
1751
+ display: flex;
1752
+ gap: 0.5rem;
1753
+ flex-wrap: wrap;
1754
+ margin-top: 1rem;
1755
+ }
1756
+
1757
+ .tag {
1758
+ background: var(--nav-link-hover-bg, #f0f0f0);
1759
+ color: var(--text-color, #333);
1760
+ padding: 0.25rem 0.5rem;
1761
+ border-radius: 4px;
1762
+ font-size: 0.875rem;
1763
+ border: 1px solid var(--border-color, transparent);
1764
+ }
1765
+
1766
+ .content {
1767
+ line-height: 1.8;
1768
+ text-align: left;
1769
+ }
1770
+
1771
+ .content h1, .content h2, .content h3 {
1772
+ margin-top: 1.5rem;
1773
+ }
1774
+ `;
1775
+ var __create = Object.create;
1776
+ var __defProp = Object.defineProperty;
1777
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
1778
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
1779
+ var __typeError = (msg) => {
1780
+ throw TypeError(msg);
1781
+ };
1782
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1783
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
1784
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
1785
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
1786
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
1787
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
1788
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
1789
+ var __runInitializers = (array, flags, self, value) => {
1790
+ for (var i2 = 0, fns = array[flags >> 1], n2 = fns && fns.length; i2 < n2; i2++) flags & 1 ? fns[i2].call(self) : value = fns[i2].call(self, value);
1791
+ return value;
1792
+ };
1793
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
1794
+ var fn, it, done, ctx, access, k2 = flags & 7, s2 = !!(flags & 8), p2 = !!(flags & 16);
1795
+ var j = k2 > 3 ? array.length + 1 : k2 ? s2 ? 1 : 2 : 0, key = __decoratorStrings[k2 + 5];
1796
+ var initializers = k2 > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
1797
+ var desc = k2 && (!p2 && !s2 && (target = target.prototype), k2 < 5 && (k2 > 3 || !p2) && __getOwnPropDesc(k2 < 4 ? target : { get [name]() {
1798
+ return __privateGet(this, extra);
1799
+ }, set [name](x) {
1800
+ return __privateSet(this, extra, x);
1801
+ } }, name));
1802
+ k2 ? p2 && k2 < 4 && __name(extra, (k2 > 2 ? "set " : k2 > 1 ? "get " : "") + name) : __name(target, name);
1803
+ for (var i2 = decorators.length - 1; i2 >= 0; i2--) {
1804
+ ctx = __decoratorContext(k2, name, done = {}, array[3], extraInitializers);
1805
+ if (k2) {
1806
+ ctx.static = s2, ctx.private = p2, access = ctx.access = { has: p2 ? (x) => __privateIn(target, x) : (x) => name in x };
1807
+ if (k2 ^ 3) access.get = p2 ? (x) => (k2 ^ 1 ? __privateGet : __privateMethod)(x, target, k2 ^ 4 ? extra : desc.get) : (x) => x[name];
1808
+ if (k2 > 2) access.set = p2 ? (x, y2) => __privateSet(x, target, y2, k2 ^ 4 ? extra : desc.set) : (x, y2) => x[name] = y2;
1809
+ }
1810
+ it = (0, decorators[i2])(k2 ? k2 < 4 ? p2 ? extra : desc[key] : k2 > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
1811
+ if (k2 ^ 4 || it === void 0) __expectFn(it) && (k2 > 4 ? initializers.unshift(it) : k2 ? p2 ? extra = it : desc[key] = it : target = it);
1812
+ else if (typeof it !== "object" || it === null) __typeError("Object expected");
1813
+ else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
1814
+ }
1815
+ return k2 || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p2 ? k2 ^ 4 ? extra : desc : target;
1816
+ };
1817
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
1818
+ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
1819
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
1820
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
1821
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
1822
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
1823
+ var _error_dec, _loading_dec, _storyPost_dec, _slug_dec, _a, _StoryViewer_decorators, _init, _slug, _storyPost, _loading, _error;
1824
+ const pipeline = new MarkdownPipeline({
1825
+ imagePathPrefix: "images/",
1826
+ styleOptions: {
1827
+ classPrefix: "md-",
1828
+ addHeadingIds: true
1829
+ }
1830
+ });
1831
+ _StoryViewer_decorators = [customElement("my-story-viewer")];
1832
+ class StoryViewer extends (_a = LitElement, _slug_dec = [property({ type: String })], _storyPost_dec = [state()], _loading_dec = [state()], _error_dec = [state()], _a) {
1833
+ constructor() {
1834
+ super(...arguments);
1835
+ __privateAdd(this, _slug, __runInitializers(_init, 8, this, "")), __runInitializers(_init, 11, this);
1836
+ __privateAdd(this, _storyPost, __runInitializers(_init, 12, this, null)), __runInitializers(_init, 15, this);
1837
+ __privateAdd(this, _loading, __runInitializers(_init, 16, this, true)), __runInitializers(_init, 19, this);
1838
+ __privateAdd(this, _error, __runInitializers(_init, 20, this, "")), __runInitializers(_init, 23, this);
1839
+ }
1840
+ get apiBaseUrl() {
1841
+ return "https://api.techieleader.com";
1842
+ }
1843
+ async connectedCallback() {
1844
+ super.connectedCallback();
1845
+ if (this.slug) {
1846
+ await this.loadStory();
1847
+ }
1848
+ }
1849
+ updated(changedProperties) {
1850
+ if (changedProperties.has("slug") && this.slug) {
1851
+ this.loadStory();
1852
+ }
1853
+ }
1854
+ async loadStory() {
1855
+ this.loading = true;
1856
+ this.error = "";
1857
+ try {
1858
+ const res = await fetch(`${this.apiBaseUrl}/api/stories/${this.slug}`);
1859
+ if (res.ok) {
1860
+ const story = await res.json();
1861
+ if (story && story.content) {
1862
+ this.storyPost = story;
1863
+ } else {
1864
+ this.error = "Story content not found";
1865
+ }
1866
+ } else {
1867
+ this.error = "Story not found";
1868
+ }
1869
+ } catch (e2) {
1870
+ this.error = "Failed to load story";
1871
+ }
1872
+ this.loading = false;
1873
+ }
1874
+ render() {
1875
+ if (this.loading) {
1876
+ return html`<div class="loading">Loading...</div>`;
1877
+ }
1878
+ if (this.error) {
1879
+ return html`<div class="error">${this.error}</div>`;
1880
+ }
1881
+ if (!this.storyPost) {
1882
+ return html`<div class="error">Story not found</div>`;
1883
+ }
1884
+ const { title, date, tags, content } = this.storyPost;
1885
+ return html`
1886
+ <article>
1887
+ <h1>${title}</h1>
1888
+ <div class="meta">
1889
+ <span>${date}</span>
1890
+ </div>
1891
+ ${tags?.length ? html`
1892
+ <div class="tags">
1893
+ ${tags.map((tag) => html`<span class="tag">${tag}</span>`)}
1894
+ </div>
1895
+ ` : ""}
1896
+ <div class="content">
1897
+ ${o(this.renderMarkdown(content))}
1898
+ </div>
1899
+ </article>
1900
+ `;
1901
+ }
1902
+ renderMarkdown(content) {
1903
+ if (!content) return "";
1904
+ const nodes = pipeline.parse(content);
1905
+ return pipeline.render(nodes);
1906
+ }
1907
+ }
1908
+ _init = __decoratorStart(_a);
1909
+ _slug = /* @__PURE__ */ new WeakMap();
1910
+ _storyPost = /* @__PURE__ */ new WeakMap();
1911
+ _loading = /* @__PURE__ */ new WeakMap();
1912
+ _error = /* @__PURE__ */ new WeakMap();
1913
+ __decorateElement(_init, 4, "slug", _slug_dec, StoryViewer, _slug);
1914
+ __decorateElement(_init, 4, "storyPost", _storyPost_dec, StoryViewer, _storyPost);
1915
+ __decorateElement(_init, 4, "loading", _loading_dec, StoryViewer, _loading);
1916
+ __decorateElement(_init, 4, "error", _error_dec, StoryViewer, _error);
1917
+ StoryViewer = __decorateElement(_init, 0, "StoryViewer", _StoryViewer_decorators, StoryViewer);
1918
+ StoryViewer.styles = storyviewerStyles;
1919
+ __runInitializers(_init, 1, StoryViewer);
1920
+ export {
1921
+ AdminPortal as A,
1922
+ BlogViewer as B,
1923
+ FooterComponent as F,
1924
+ MyAboutme as M,
1925
+ StoryViewer as S,
1926
+ MyBanner as a
1927
+ };