@takuhon/ui 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -53,20 +53,59 @@ function CareerTimeline({ careers }) {
53
53
  ] });
54
54
  }
55
55
 
56
+ // src/components/Certifications.tsx
57
+ import styles2 from "./Certifications.module-2NMKPWLM.module.css";
58
+ import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
59
+ function sortCerts(certs) {
60
+ return [...certs].sort((a, b) => {
61
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
62
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
63
+ if (aOrder !== bOrder) return aOrder - bOrder;
64
+ return b.issueDate.localeCompare(a.issueDate);
65
+ });
66
+ }
67
+ function Certifications({ certifications }) {
68
+ if (certifications.length === 0) return null;
69
+ const ordered = sortCerts(certifications);
70
+ return /* @__PURE__ */ jsxs2("section", { className: styles2.section, "aria-labelledby": "takuhon-certifications-heading", children: [
71
+ /* @__PURE__ */ jsx2("h2", { id: "takuhon-certifications-heading", className: styles2.heading, children: "Certifications" }),
72
+ /* @__PURE__ */ jsx2("ul", { className: styles2.list, children: ordered.map((cert) => /* @__PURE__ */ jsxs2("li", { className: styles2.item, children: [
73
+ /* @__PURE__ */ jsx2("p", { className: styles2.title, children: cert.url ? /* @__PURE__ */ jsx2(
74
+ "a",
75
+ {
76
+ className: styles2.link,
77
+ href: cert.url,
78
+ target: "_blank",
79
+ rel: "noopener noreferrer",
80
+ children: cert.title
81
+ }
82
+ ) : cert.title }),
83
+ /* @__PURE__ */ jsx2("p", { className: styles2.issuer, children: cert.issuingOrganization }),
84
+ /* @__PURE__ */ jsxs2("p", { className: styles2.range, children: [
85
+ /* @__PURE__ */ jsx2("time", { dateTime: cert.issueDate, children: cert.issueDate }),
86
+ cert.expirationDate === null ? /* @__PURE__ */ jsx2("span", { className: styles2.tag, children: " \xB7 No expiration" }) : cert.expirationDate !== void 0 ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
87
+ " \u2013 ",
88
+ /* @__PURE__ */ jsx2("time", { dateTime: cert.expirationDate, children: cert.expirationDate })
89
+ ] }) : null
90
+ ] })
91
+ ] }, cert.id)) })
92
+ ] });
93
+ }
94
+
56
95
  // src/components/ContactInfo.tsx
57
- import styles2 from "./ContactInfo.module-7SO24KHC.module.css";
58
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
96
+ import styles3 from "./ContactInfo.module-7SO24KHC.module.css";
97
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
59
98
  function ContactInfo({ contact }) {
60
99
  const showEmail = contact.showEmail === true && contact.email !== void 0;
61
100
  if (!showEmail && contact.formUrl === void 0) return null;
62
- return /* @__PURE__ */ jsxs2("section", { className: styles2.section, "aria-labelledby": "takuhon-contact-heading", children: [
63
- /* @__PURE__ */ jsx2("h2", { id: "takuhon-contact-heading", className: styles2.heading, children: "Contact" }),
64
- /* @__PURE__ */ jsxs2("ul", { className: styles2.list, children: [
65
- showEmail && contact.email !== void 0 ? /* @__PURE__ */ jsx2("li", { className: styles2.item, children: /* @__PURE__ */ jsx2("a", { className: styles2.link, href: `mailto:${contact.email}`, children: contact.email }) }) : null,
66
- contact.formUrl !== void 0 ? /* @__PURE__ */ jsx2("li", { className: styles2.item, children: /* @__PURE__ */ jsx2(
101
+ return /* @__PURE__ */ jsxs3("section", { className: styles3.section, "aria-labelledby": "takuhon-contact-heading", children: [
102
+ /* @__PURE__ */ jsx3("h2", { id: "takuhon-contact-heading", className: styles3.heading, children: "Contact" }),
103
+ /* @__PURE__ */ jsxs3("ul", { className: styles3.list, children: [
104
+ showEmail && contact.email !== void 0 ? /* @__PURE__ */ jsx3("li", { className: styles3.item, children: /* @__PURE__ */ jsx3("a", { className: styles3.link, href: `mailto:${contact.email}`, children: contact.email }) }) : null,
105
+ contact.formUrl !== void 0 ? /* @__PURE__ */ jsx3("li", { className: styles3.item, children: /* @__PURE__ */ jsx3(
67
106
  "a",
68
107
  {
69
- className: styles2.link,
108
+ className: styles3.link,
70
109
  href: contact.formUrl,
71
110
  target: "_blank",
72
111
  rel: "noopener noreferrer",
@@ -77,17 +116,106 @@ function ContactInfo({ contact }) {
77
116
  ] });
78
117
  }
79
118
 
119
+ // src/components/Courses.tsx
120
+ import styles4 from "./Courses.module-EVDSFNGW.module.css";
121
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
122
+ function sortCourses(entries) {
123
+ return [...entries].sort((a, b) => {
124
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
125
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
126
+ if (aOrder !== bOrder) return aOrder - bOrder;
127
+ return (b.completionDate ?? "").localeCompare(a.completionDate ?? "");
128
+ });
129
+ }
130
+ function Courses({ courses }) {
131
+ if (courses.length === 0) return null;
132
+ const ordered = sortCourses(courses);
133
+ return /* @__PURE__ */ jsxs4("section", { className: styles4.section, "aria-labelledby": "takuhon-courses-heading", children: [
134
+ /* @__PURE__ */ jsx4("h2", { id: "takuhon-courses-heading", className: styles4.heading, children: "Courses" }),
135
+ /* @__PURE__ */ jsx4("ul", { className: styles4.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs4("li", { className: styles4.item, children: [
136
+ /* @__PURE__ */ jsx4("p", { className: styles4.title, children: entry.certificateUrl ? /* @__PURE__ */ jsx4(
137
+ "a",
138
+ {
139
+ className: styles4.link,
140
+ href: entry.certificateUrl,
141
+ target: "_blank",
142
+ rel: "noopener noreferrer",
143
+ children: entry.title
144
+ }
145
+ ) : entry.title }),
146
+ entry.provider ? /* @__PURE__ */ jsx4("p", { className: styles4.provider, children: entry.provider }) : null,
147
+ entry.courseNumber ? /* @__PURE__ */ jsx4("p", { className: styles4.courseNumber, children: entry.courseNumber }) : null,
148
+ entry.completionDate ? /* @__PURE__ */ jsx4("p", { className: styles4.date, children: /* @__PURE__ */ jsx4("time", { dateTime: entry.completionDate, children: entry.completionDate }) }) : null,
149
+ entry.description ? /* @__PURE__ */ jsx4("p", { className: styles4.description, children: entry.description }) : null
150
+ ] }, entry.id)) })
151
+ ] });
152
+ }
153
+
154
+ // src/components/EducationTimeline.tsx
155
+ import styles5 from "./EducationTimeline.module-7YQTH6QU.module.css";
156
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
157
+ function sortEducation(entries) {
158
+ return [...entries].sort((a, b) => {
159
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
160
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
161
+ if (aOrder !== bOrder) return aOrder - bOrder;
162
+ return b.startDate.localeCompare(a.startDate);
163
+ });
164
+ }
165
+ function isOngoing2(entry) {
166
+ return entry.isCurrent === true || entry.endDate === null || entry.endDate === void 0;
167
+ }
168
+ function composeStudyLine(entry) {
169
+ if (entry.degree !== void 0 && entry.fieldOfStudy !== void 0) {
170
+ return `${entry.degree} \xB7 ${entry.fieldOfStudy}`;
171
+ }
172
+ return entry.degree ?? entry.fieldOfStudy;
173
+ }
174
+ function EducationTimeline({ education }) {
175
+ if (education.length === 0) return null;
176
+ const ordered = sortEducation(education);
177
+ return /* @__PURE__ */ jsxs5("section", { className: styles5.section, "aria-labelledby": "takuhon-education-heading", children: [
178
+ /* @__PURE__ */ jsx5("h2", { id: "takuhon-education-heading", className: styles5.heading, children: "Education" }),
179
+ /* @__PURE__ */ jsx5("ol", { className: styles5.list, children: ordered.map((entry) => {
180
+ const study = composeStudyLine(entry);
181
+ return /* @__PURE__ */ jsxs5("li", { className: styles5.item, children: [
182
+ /* @__PURE__ */ jsx5("div", { className: styles5.timelineMarker, "aria-hidden": "true" }),
183
+ /* @__PURE__ */ jsxs5("div", { className: styles5.content, children: [
184
+ /* @__PURE__ */ jsx5("p", { className: styles5.institution, children: entry.url ? /* @__PURE__ */ jsx5(
185
+ "a",
186
+ {
187
+ className: styles5.link,
188
+ href: entry.url,
189
+ target: "_blank",
190
+ rel: "noopener noreferrer",
191
+ children: entry.institution
192
+ }
193
+ ) : entry.institution }),
194
+ study ? /* @__PURE__ */ jsx5("p", { className: styles5.study, children: study }) : null,
195
+ /* @__PURE__ */ jsxs5("p", { className: styles5.range, children: [
196
+ /* @__PURE__ */ jsx5("time", { dateTime: entry.startDate, children: entry.startDate }),
197
+ " \u2013 ",
198
+ isOngoing2(entry) ? "Present" : /* @__PURE__ */ jsx5("time", { dateTime: entry.endDate, children: entry.endDate })
199
+ ] }),
200
+ entry.grade ? /* @__PURE__ */ jsx5("p", { className: styles5.grade, children: entry.grade }) : null,
201
+ entry.description ? /* @__PURE__ */ jsx5("p", { className: styles5.description, children: entry.description }) : null
202
+ ] })
203
+ ] }, entry.id);
204
+ }) })
205
+ ] });
206
+ }
207
+
80
208
  // src/components/Footer.tsx
81
- import styles3 from "./Footer.module-HLC5GXVI.module.css";
82
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
209
+ import styles6 from "./Footer.module-HLC5GXVI.module.css";
210
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
83
211
  function Footer() {
84
- return /* @__PURE__ */ jsx3("footer", { className: styles3.footer, children: /* @__PURE__ */ jsxs3("p", { className: styles3.line, children: [
212
+ return /* @__PURE__ */ jsx6("footer", { className: styles6.footer, children: /* @__PURE__ */ jsxs6("p", { className: styles6.line, children: [
85
213
  "Powered by",
86
214
  " ",
87
- /* @__PURE__ */ jsx3(
215
+ /* @__PURE__ */ jsx6(
88
216
  "a",
89
217
  {
90
- className: styles3.link,
218
+ className: styles6.link,
91
219
  href: "https://github.com/takuhon-dev/takuhon",
92
220
  target: "_blank",
93
221
  rel: "noopener noreferrer",
@@ -97,9 +225,75 @@ function Footer() {
97
225
  ] }) });
98
226
  }
99
227
 
228
+ // src/components/HonorsList.tsx
229
+ import styles7 from "./HonorsList.module-AQN3CT7O.module.css";
230
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
231
+ function sortHonors(honors) {
232
+ return [...honors].sort((a, b) => {
233
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
234
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
235
+ if (aOrder !== bOrder) return aOrder - bOrder;
236
+ return b.date.localeCompare(a.date);
237
+ });
238
+ }
239
+ function HonorsList({ honors }) {
240
+ if (honors.length === 0) return null;
241
+ const ordered = sortHonors(honors);
242
+ return /* @__PURE__ */ jsxs7("section", { className: styles7.section, "aria-labelledby": "takuhon-honors-heading", children: [
243
+ /* @__PURE__ */ jsx7("h2", { id: "takuhon-honors-heading", className: styles7.heading, children: "Honors & Awards" }),
244
+ /* @__PURE__ */ jsx7("ul", { className: styles7.list, children: ordered.map((honor) => /* @__PURE__ */ jsxs7("li", { className: styles7.item, children: [
245
+ /* @__PURE__ */ jsx7("p", { className: styles7.title, children: honor.url ? /* @__PURE__ */ jsx7(
246
+ "a",
247
+ {
248
+ className: styles7.link,
249
+ href: honor.url,
250
+ target: "_blank",
251
+ rel: "noopener noreferrer",
252
+ children: honor.title
253
+ }
254
+ ) : honor.title }),
255
+ /* @__PURE__ */ jsxs7("p", { className: styles7.meta, children: [
256
+ honor.issuer,
257
+ " \xB7 ",
258
+ /* @__PURE__ */ jsx7("time", { dateTime: honor.date, children: honor.date })
259
+ ] }),
260
+ honor.description ? /* @__PURE__ */ jsx7("p", { className: styles7.description, children: honor.description }) : null
261
+ ] }, honor.id)) })
262
+ ] });
263
+ }
264
+
265
+ // src/components/Languages.tsx
266
+ import styles8 from "./Languages.module-X6RQNFRY.module.css";
267
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
268
+ var PROFICIENCY_LABEL = {
269
+ native: "Native",
270
+ fluent: "Fluent",
271
+ professional: "Professional working",
272
+ intermediate: "Intermediate",
273
+ basic: "Basic"
274
+ };
275
+ function sortLanguages(languages) {
276
+ return [...languages].sort((a, b) => {
277
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
278
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
279
+ return aOrder - bOrder;
280
+ });
281
+ }
282
+ function Languages({ languages }) {
283
+ if (languages.length === 0) return null;
284
+ const ordered = sortLanguages(languages);
285
+ return /* @__PURE__ */ jsxs8("section", { className: styles8.section, "aria-labelledby": "takuhon-languages-heading", children: [
286
+ /* @__PURE__ */ jsx8("h2", { id: "takuhon-languages-heading", className: styles8.heading, children: "Languages" }),
287
+ /* @__PURE__ */ jsx8("ul", { className: styles8.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs8("li", { className: styles8.item, children: [
288
+ /* @__PURE__ */ jsx8("span", { className: styles8.name, lang: entry.language, children: entry.displayName ?? entry.language }),
289
+ /* @__PURE__ */ jsx8("span", { className: styles8.proficiency, children: PROFICIENCY_LABEL[entry.proficiency] })
290
+ ] }, entry.id)) })
291
+ ] });
292
+ }
293
+
100
294
  // src/components/LinksList.tsx
101
- import styles4 from "./LinksList.module-QPSFPOF3.module.css";
102
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
295
+ import styles9 from "./LinksList.module-QPSFPOF3.module.css";
296
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
103
297
  function sortLinks(links) {
104
298
  return [...links].sort((a, b) => {
105
299
  const aFeatured = a.featured ? 1 : 0;
@@ -118,32 +312,136 @@ function formatLinkLabel(link) {
118
312
  function LinksList({ links }) {
119
313
  if (links.length === 0) return null;
120
314
  const ordered = sortLinks(links);
121
- return /* @__PURE__ */ jsx4("nav", { "aria-label": "Profile links", className: styles4.nav, children: /* @__PURE__ */ jsx4("ul", { className: styles4.list, children: ordered.map((link) => /* @__PURE__ */ jsx4("li", { className: styles4.item, children: /* @__PURE__ */ jsxs4(
315
+ return /* @__PURE__ */ jsx9("nav", { "aria-label": "Profile links", className: styles9.nav, children: /* @__PURE__ */ jsx9("ul", { className: styles9.list, children: ordered.map((link) => /* @__PURE__ */ jsx9("li", { className: styles9.item, children: /* @__PURE__ */ jsxs9(
122
316
  "a",
123
317
  {
124
- className: styles4.link,
318
+ className: styles9.link,
125
319
  href: link.url,
126
320
  target: "_blank",
127
321
  rel: "noopener noreferrer",
128
322
  "data-featured": link.featured ? "true" : void 0,
129
323
  children: [
130
- link.iconUrl ? /* @__PURE__ */ jsx4("img", { className: styles4.icon, src: link.iconUrl, alt: "" }) : null,
131
- /* @__PURE__ */ jsx4("span", { className: styles4.label, children: formatLinkLabel(link) })
324
+ link.iconUrl ? /* @__PURE__ */ jsx9("img", { className: styles9.icon, src: link.iconUrl, alt: "" }) : null,
325
+ /* @__PURE__ */ jsx9("span", { className: styles9.label, children: formatLinkLabel(link) })
132
326
  ]
133
327
  }
134
328
  ) }, link.id)) }) });
135
329
  }
136
330
 
331
+ // src/components/Memberships.tsx
332
+ import styles10 from "./Memberships.module-SMJBJFA2.module.css";
333
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
334
+ function sortMemberships(entries) {
335
+ return [...entries].sort((a, b) => {
336
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
337
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
338
+ if (aOrder !== bOrder) return aOrder - bOrder;
339
+ return b.startDate.localeCompare(a.startDate);
340
+ });
341
+ }
342
+ function isOngoing3(entry) {
343
+ return entry.isCurrent === true || entry.endDate === null || entry.endDate === void 0;
344
+ }
345
+ function Memberships({ memberships }) {
346
+ if (memberships.length === 0) return null;
347
+ const ordered = sortMemberships(memberships);
348
+ return /* @__PURE__ */ jsxs10("section", { className: styles10.section, "aria-labelledby": "takuhon-memberships-heading", children: [
349
+ /* @__PURE__ */ jsx10("h2", { id: "takuhon-memberships-heading", className: styles10.heading, children: "Memberships" }),
350
+ /* @__PURE__ */ jsx10("ol", { className: styles10.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs10("li", { className: styles10.item, children: [
351
+ /* @__PURE__ */ jsx10("div", { className: styles10.timelineMarker, "aria-hidden": "true" }),
352
+ /* @__PURE__ */ jsxs10("div", { className: styles10.content, children: [
353
+ /* @__PURE__ */ jsx10("p", { className: styles10.organization, children: entry.url ? /* @__PURE__ */ jsx10(
354
+ "a",
355
+ {
356
+ className: styles10.link,
357
+ href: entry.url,
358
+ target: "_blank",
359
+ rel: "noopener noreferrer",
360
+ children: entry.organization
361
+ }
362
+ ) : entry.organization }),
363
+ entry.role ? /* @__PURE__ */ jsx10("p", { className: styles10.role, children: entry.role }) : null,
364
+ /* @__PURE__ */ jsxs10("p", { className: styles10.range, children: [
365
+ /* @__PURE__ */ jsx10("time", { dateTime: entry.startDate, children: entry.startDate }),
366
+ " \u2013 ",
367
+ isOngoing3(entry) ? "Present" : /* @__PURE__ */ jsx10("time", { dateTime: entry.endDate, children: entry.endDate })
368
+ ] }),
369
+ entry.description ? /* @__PURE__ */ jsx10("p", { className: styles10.description, children: entry.description }) : null
370
+ ] })
371
+ ] }, entry.id)) })
372
+ ] });
373
+ }
374
+
375
+ // src/components/Patents.tsx
376
+ import styles11 from "./Patents.module-L3GWPB3V.module.css";
377
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
378
+ var STATUS_LABEL = {
379
+ pending: "Pending",
380
+ issued: "Issued",
381
+ expired: "Expired",
382
+ abandoned: "Abandoned"
383
+ };
384
+ function sortPatents(entries) {
385
+ return [...entries].sort((a, b) => {
386
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
387
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
388
+ if (aOrder !== bOrder) return aOrder - bOrder;
389
+ const aDate = a.grantDate ?? a.filingDate ?? "";
390
+ const bDate = b.grantDate ?? b.filingDate ?? "";
391
+ return bDate.localeCompare(aDate);
392
+ });
393
+ }
394
+ function Patents({ patents }) {
395
+ if (patents.length === 0) return null;
396
+ const ordered = sortPatents(patents);
397
+ return /* @__PURE__ */ jsxs11("section", { className: styles11.section, "aria-labelledby": "takuhon-patents-heading", children: [
398
+ /* @__PURE__ */ jsx11("h2", { id: "takuhon-patents-heading", className: styles11.heading, children: "Patents" }),
399
+ /* @__PURE__ */ jsx11("ul", { className: styles11.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs11("li", { className: styles11.item, children: [
400
+ /* @__PURE__ */ jsxs11("p", { className: styles11.title, children: [
401
+ entry.url ? /* @__PURE__ */ jsx11(
402
+ "a",
403
+ {
404
+ className: styles11.link,
405
+ href: entry.url,
406
+ target: "_blank",
407
+ rel: "noopener noreferrer",
408
+ children: entry.title
409
+ }
410
+ ) : entry.title,
411
+ /* @__PURE__ */ jsxs11("span", { className: styles11.statusBadge, "data-status": entry.status, children: [
412
+ /* @__PURE__ */ jsx11("span", { className: styles11.srOnly, children: "Status: " }),
413
+ STATUS_LABEL[entry.status]
414
+ ] })
415
+ ] }),
416
+ /* @__PURE__ */ jsx11("p", { className: styles11.patentNumber, children: entry.patentNumber }),
417
+ entry.office ? /* @__PURE__ */ jsx11("p", { className: styles11.office, children: entry.office }) : null,
418
+ entry.filingDate !== void 0 || entry.grantDate !== void 0 ? /* @__PURE__ */ jsxs11("p", { className: styles11.dates, children: [
419
+ entry.filingDate ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
420
+ "Filed ",
421
+ /* @__PURE__ */ jsx11("time", { dateTime: entry.filingDate, children: entry.filingDate })
422
+ ] }) : null,
423
+ entry.filingDate && entry.grantDate ? " \xB7 " : null,
424
+ entry.grantDate ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
425
+ "Granted ",
426
+ /* @__PURE__ */ jsx11("time", { dateTime: entry.grantDate, children: entry.grantDate })
427
+ ] }) : null
428
+ ] }) : null,
429
+ entry.coInventors && entry.coInventors.length > 0 ? /* @__PURE__ */ jsx11("p", { className: styles11.coInventors, children: `with ${entry.coInventors.join(", ")}` }) : null,
430
+ entry.description ? /* @__PURE__ */ jsx11("p", { className: styles11.description, children: entry.description }) : null
431
+ ] }, entry.id)) })
432
+ ] });
433
+ }
434
+
137
435
  // src/components/ProfileHeader.tsx
138
- import styles5 from "./ProfileHeader.module-EK27UTZL.module.css";
139
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
436
+ import styles12 from "./ProfileHeader.module-EK27UTZL.module.css";
437
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
140
438
  function ProfileHeader({ profile }) {
141
439
  const locationLabel = profile.location?.display ?? profile.location?.locality;
142
- return /* @__PURE__ */ jsxs5("header", { className: styles5.header, children: [
143
- profile.avatar ? /* @__PURE__ */ jsx5(
440
+ return /* @__PURE__ */ jsxs12("header", { className: styles12.header, children: [
441
+ profile.avatar ? /* @__PURE__ */ jsx12(
144
442
  "img",
145
443
  {
146
- className: styles5.avatar,
444
+ className: styles12.avatar,
147
445
  src: profile.avatar.url,
148
446
  alt: profile.avatar.alt ?? "",
149
447
  width: 128,
@@ -152,16 +450,16 @@ function ProfileHeader({ profile }) {
152
450
  decoding: "async"
153
451
  }
154
452
  ) : null,
155
- /* @__PURE__ */ jsx5("h1", { className: styles5.displayName, children: profile.displayName }),
156
- profile.tagline ? /* @__PURE__ */ jsx5("p", { className: styles5.tagline, children: profile.tagline }) : null,
157
- locationLabel ? /* @__PURE__ */ jsx5("p", { className: styles5.location, children: locationLabel }) : null,
158
- profile.bio ? /* @__PURE__ */ jsx5("p", { className: styles5.bio, children: profile.bio }) : null
453
+ /* @__PURE__ */ jsx12("h1", { className: styles12.displayName, children: profile.displayName }),
454
+ profile.tagline ? /* @__PURE__ */ jsx12("p", { className: styles12.tagline, children: profile.tagline }) : null,
455
+ locationLabel ? /* @__PURE__ */ jsx12("p", { className: styles12.location, children: locationLabel }) : null,
456
+ profile.bio ? /* @__PURE__ */ jsx12("p", { className: styles12.bio, children: profile.bio }) : null
159
457
  ] });
160
458
  }
161
459
 
162
460
  // src/components/ProjectsList.tsx
163
- import styles6 from "./ProjectsList.module-JKGGZRKO.module.css";
164
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
461
+ import styles13 from "./ProjectsList.module-JKGGZRKO.module.css";
462
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
165
463
  function sortProjects(projects) {
166
464
  return [...projects].sort((a, b) => {
167
465
  const aHighlighted = a.highlighted ? 1 : 0;
@@ -175,31 +473,31 @@ function sortProjects(projects) {
175
473
  function ProjectsList({ projects }) {
176
474
  if (projects.length === 0) return null;
177
475
  const ordered = sortProjects(projects);
178
- return /* @__PURE__ */ jsxs6("section", { className: styles6.section, "aria-labelledby": "takuhon-projects-heading", children: [
179
- /* @__PURE__ */ jsx6("h2", { id: "takuhon-projects-heading", className: styles6.heading, children: "Projects" }),
180
- /* @__PURE__ */ jsx6("ul", { className: styles6.list, children: ordered.map((project) => /* @__PURE__ */ jsxs6(
476
+ return /* @__PURE__ */ jsxs13("section", { className: styles13.section, "aria-labelledby": "takuhon-projects-heading", children: [
477
+ /* @__PURE__ */ jsx13("h2", { id: "takuhon-projects-heading", className: styles13.heading, children: "Projects" }),
478
+ /* @__PURE__ */ jsx13("ul", { className: styles13.list, children: ordered.map((project) => /* @__PURE__ */ jsxs13(
181
479
  "li",
182
480
  {
183
- className: styles6.item,
481
+ className: styles13.item,
184
482
  "data-highlighted": project.highlighted ? "true" : void 0,
185
483
  children: [
186
- /* @__PURE__ */ jsx6("p", { className: styles6.title, children: project.url ? /* @__PURE__ */ jsx6(
484
+ /* @__PURE__ */ jsx13("p", { className: styles13.title, children: project.url ? /* @__PURE__ */ jsx13(
187
485
  "a",
188
486
  {
189
- className: styles6.titleLink,
487
+ className: styles13.titleLink,
190
488
  href: project.url,
191
489
  target: "_blank",
192
490
  rel: "noopener noreferrer",
193
491
  children: project.title
194
492
  }
195
493
  ) : project.title }),
196
- project.startDate !== void 0 ? /* @__PURE__ */ jsxs6("p", { className: styles6.range, children: [
197
- /* @__PURE__ */ jsx6("time", { dateTime: project.startDate, children: project.startDate }),
494
+ project.startDate !== void 0 ? /* @__PURE__ */ jsxs13("p", { className: styles13.range, children: [
495
+ /* @__PURE__ */ jsx13("time", { dateTime: project.startDate, children: project.startDate }),
198
496
  " \u2013 ",
199
- project.endDate ? /* @__PURE__ */ jsx6("time", { dateTime: project.endDate, children: project.endDate }) : "Present"
497
+ project.endDate ? /* @__PURE__ */ jsx13("time", { dateTime: project.endDate, children: project.endDate }) : "Present"
200
498
  ] }) : null,
201
- project.description ? /* @__PURE__ */ jsx6("p", { className: styles6.description, children: project.description }) : null,
202
- project.tags && project.tags.length > 0 ? /* @__PURE__ */ jsx6("ul", { className: styles6.tags, "aria-label": "Tags", children: project.tags.map((tag) => /* @__PURE__ */ jsx6("li", { className: styles6.tag, children: tag }, tag)) }) : null
499
+ project.description ? /* @__PURE__ */ jsx13("p", { className: styles13.description, children: project.description }) : null,
500
+ project.tags && project.tags.length > 0 ? /* @__PURE__ */ jsx13("ul", { className: styles13.tags, "aria-label": "Tags", children: project.tags.map((tag) => /* @__PURE__ */ jsx13("li", { className: styles13.tag, children: tag }, tag)) }) : null
203
501
  ]
204
502
  },
205
503
  project.id
@@ -207,9 +505,60 @@ function ProjectsList({ projects }) {
207
505
  ] });
208
506
  }
209
507
 
508
+ // src/components/Publications.tsx
509
+ import styles14 from "./Publications.module-INRTHJMO.module.css";
510
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
511
+ function sortPublications(entries) {
512
+ return [...entries].sort((a, b) => {
513
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
514
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
515
+ if (aOrder !== bOrder) return aOrder - bOrder;
516
+ return b.date.localeCompare(a.date);
517
+ });
518
+ }
519
+ function normalizeDoi(doi) {
520
+ return doi.replace(/^https?:\/\/(?:dx\.)?doi\.org\//i, "");
521
+ }
522
+ function Publications({ publications }) {
523
+ if (publications.length === 0) return null;
524
+ const ordered = sortPublications(publications);
525
+ return /* @__PURE__ */ jsxs14("section", { className: styles14.section, "aria-labelledby": "takuhon-publications-heading", children: [
526
+ /* @__PURE__ */ jsx14("h2", { id: "takuhon-publications-heading", className: styles14.heading, children: "Publications" }),
527
+ /* @__PURE__ */ jsx14("ul", { className: styles14.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs14("li", { className: styles14.item, children: [
528
+ /* @__PURE__ */ jsx14("p", { className: styles14.title, children: entry.url ? /* @__PURE__ */ jsx14(
529
+ "a",
530
+ {
531
+ className: styles14.link,
532
+ href: entry.url,
533
+ target: "_blank",
534
+ rel: "noopener noreferrer",
535
+ children: entry.title
536
+ }
537
+ ) : entry.title }),
538
+ entry.publisher ? /* @__PURE__ */ jsx14("p", { className: styles14.publisher, children: entry.publisher }) : null,
539
+ /* @__PURE__ */ jsx14("p", { className: styles14.date, children: /* @__PURE__ */ jsx14("time", { dateTime: entry.date, children: entry.date }) }),
540
+ entry.coAuthors && entry.coAuthors.length > 0 ? /* @__PURE__ */ jsx14("p", { className: styles14.coAuthors, children: `with ${entry.coAuthors.join(", ")}` }) : null,
541
+ entry.doi ? (() => {
542
+ const bare = normalizeDoi(entry.doi);
543
+ return /* @__PURE__ */ jsx14("p", { className: styles14.doi, children: /* @__PURE__ */ jsx14(
544
+ "a",
545
+ {
546
+ className: styles14.link,
547
+ href: `https://doi.org/${bare}`,
548
+ target: "_blank",
549
+ rel: "noopener noreferrer",
550
+ children: `doi:${bare}`
551
+ }
552
+ ) });
553
+ })() : null,
554
+ entry.description ? /* @__PURE__ */ jsx14("p", { className: styles14.description, children: entry.description }) : null
555
+ ] }, entry.id)) })
556
+ ] });
557
+ }
558
+
210
559
  // src/components/SkillsList.tsx
211
- import styles7 from "./SkillsList.module-XIAWE55H.module.css";
212
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
560
+ import styles15 from "./SkillsList.module-XIAWE55H.module.css";
561
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
213
562
  function groupSkills(skills) {
214
563
  const sorted = [...skills].sort((a, b) => {
215
564
  const aOrder = a.order ?? Number.POSITIVE_INFINITY;
@@ -231,34 +580,95 @@ function groupSkills(skills) {
231
580
  function SkillsList({ skills }) {
232
581
  if (skills.length === 0) return null;
233
582
  const groups = groupSkills(skills);
234
- return /* @__PURE__ */ jsxs7("section", { className: styles7.section, "aria-labelledby": "takuhon-skills-heading", children: [
235
- /* @__PURE__ */ jsx7("h2", { id: "takuhon-skills-heading", className: styles7.heading, children: "Skills" }),
236
- /* @__PURE__ */ jsx7("div", { className: styles7.groups, children: groups.map((group) => /* @__PURE__ */ jsxs7("div", { className: styles7.group, children: [
237
- /* @__PURE__ */ jsx7("h3", { className: styles7.category, children: group.category }),
238
- /* @__PURE__ */ jsx7("ul", { className: styles7.list, "aria-label": `${group.category} skills`, children: group.skills.map((skill) => /* @__PURE__ */ jsx7("li", { className: styles7.item, children: skill.label }, skill.id)) })
583
+ return /* @__PURE__ */ jsxs15("section", { className: styles15.section, "aria-labelledby": "takuhon-skills-heading", children: [
584
+ /* @__PURE__ */ jsx15("h2", { id: "takuhon-skills-heading", className: styles15.heading, children: "Skills" }),
585
+ /* @__PURE__ */ jsx15("div", { className: styles15.groups, children: groups.map((group) => /* @__PURE__ */ jsxs15("div", { className: styles15.group, children: [
586
+ /* @__PURE__ */ jsx15("h3", { className: styles15.category, children: group.category }),
587
+ /* @__PURE__ */ jsx15("ul", { className: styles15.list, "aria-label": `${group.category} skills`, children: group.skills.map((skill) => /* @__PURE__ */ jsx15("li", { className: styles15.item, children: skill.label }, skill.id)) })
239
588
  ] }, group.category)) })
240
589
  ] });
241
590
  }
242
591
 
243
592
  // src/components/TakuhonProfile.tsx
244
- import styles8 from "./TakuhonProfile.module-QUEORIHA.module.css";
245
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
593
+ import styles17 from "./TakuhonProfile.module-QUEORIHA.module.css";
594
+
595
+ // src/components/Volunteering.tsx
596
+ import styles16 from "./Volunteering.module-TDRC6QVK.module.css";
597
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
598
+ function sortVolunteering(entries) {
599
+ return [...entries].sort((a, b) => {
600
+ const aOrder = a.order ?? Number.POSITIVE_INFINITY;
601
+ const bOrder = b.order ?? Number.POSITIVE_INFINITY;
602
+ if (aOrder !== bOrder) return aOrder - bOrder;
603
+ return b.startDate.localeCompare(a.startDate);
604
+ });
605
+ }
606
+ function isOngoing4(entry) {
607
+ return entry.isCurrent === true || entry.endDate === null || entry.endDate === void 0;
608
+ }
609
+ function Volunteering({ volunteering }) {
610
+ if (volunteering.length === 0) return null;
611
+ const ordered = sortVolunteering(volunteering);
612
+ return /* @__PURE__ */ jsxs16("section", { className: styles16.section, "aria-labelledby": "takuhon-volunteering-heading", children: [
613
+ /* @__PURE__ */ jsx16("h2", { id: "takuhon-volunteering-heading", className: styles16.heading, children: "Volunteering" }),
614
+ /* @__PURE__ */ jsx16("ol", { className: styles16.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs16("li", { className: styles16.item, children: [
615
+ /* @__PURE__ */ jsx16("div", { className: styles16.timelineMarker, "aria-hidden": "true" }),
616
+ /* @__PURE__ */ jsxs16("div", { className: styles16.content, children: [
617
+ /* @__PURE__ */ jsx16("p", { className: styles16.organization, children: entry.url ? /* @__PURE__ */ jsx16(
618
+ "a",
619
+ {
620
+ className: styles16.link,
621
+ href: entry.url,
622
+ target: "_blank",
623
+ rel: "noopener noreferrer",
624
+ children: entry.organization
625
+ }
626
+ ) : entry.organization }),
627
+ /* @__PURE__ */ jsxs16("p", { className: styles16.role, children: [
628
+ entry.role,
629
+ entry.cause ? /* @__PURE__ */ jsxs16("span", { className: styles16.cause, children: [
630
+ /* @__PURE__ */ jsx16("span", { className: styles16.srOnly, children: "Cause: " }),
631
+ entry.cause
632
+ ] }) : null
633
+ ] }),
634
+ /* @__PURE__ */ jsxs16("p", { className: styles16.range, children: [
635
+ /* @__PURE__ */ jsx16("time", { dateTime: entry.startDate, children: entry.startDate }),
636
+ " \u2013 ",
637
+ isOngoing4(entry) ? "Present" : /* @__PURE__ */ jsx16("time", { dateTime: entry.endDate, children: entry.endDate })
638
+ ] }),
639
+ entry.description ? /* @__PURE__ */ jsx16("p", { className: styles16.description, children: entry.description }) : null
640
+ ] })
641
+ ] }, entry.id)) })
642
+ ] });
643
+ }
644
+
645
+ // src/components/TakuhonProfile.tsx
646
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
246
647
  function TakuhonProfile({ data }) {
247
648
  const showFooter = data.settings.showPoweredBy !== false;
248
- return /* @__PURE__ */ jsxs8("article", { className: styles8.root, children: [
249
- /* @__PURE__ */ jsx8(ProfileHeader, { profile: data.profile }),
250
- /* @__PURE__ */ jsx8(LinksList, { links: data.links }),
251
- /* @__PURE__ */ jsx8(CareerTimeline, { careers: data.careers }),
252
- /* @__PURE__ */ jsx8(ProjectsList, { projects: data.projects }),
253
- /* @__PURE__ */ jsx8(SkillsList, { skills: data.skills }),
254
- /* @__PURE__ */ jsx8(ContactInfo, { contact: data.contact }),
255
- showFooter ? /* @__PURE__ */ jsx8(Footer, {}) : null
649
+ return /* @__PURE__ */ jsxs17("article", { className: styles17.root, children: [
650
+ /* @__PURE__ */ jsx17(ProfileHeader, { profile: data.profile }),
651
+ /* @__PURE__ */ jsx17(LinksList, { links: data.links }),
652
+ /* @__PURE__ */ jsx17(EducationTimeline, { education: data.education }),
653
+ /* @__PURE__ */ jsx17(Courses, { courses: data.courses }),
654
+ /* @__PURE__ */ jsx17(CareerTimeline, { careers: data.careers }),
655
+ /* @__PURE__ */ jsx17(Memberships, { memberships: data.memberships }),
656
+ /* @__PURE__ */ jsx17(Certifications, { certifications: data.certifications }),
657
+ /* @__PURE__ */ jsx17(Patents, { patents: data.patents }),
658
+ /* @__PURE__ */ jsx17(ProjectsList, { projects: data.projects }),
659
+ /* @__PURE__ */ jsx17(Publications, { publications: data.publications }),
660
+ /* @__PURE__ */ jsx17(HonorsList, { honors: data.honors }),
661
+ /* @__PURE__ */ jsx17(Volunteering, { volunteering: data.volunteering }),
662
+ /* @__PURE__ */ jsx17(SkillsList, { skills: data.skills }),
663
+ /* @__PURE__ */ jsx17(Languages, { languages: data.languages }),
664
+ /* @__PURE__ */ jsx17(ContactInfo, { contact: data.contact }),
665
+ showFooter ? /* @__PURE__ */ jsx17(Footer, {}) : null
256
666
  ] });
257
667
  }
258
668
 
259
669
  // src/components/LocaleSwitcher.tsx
260
- import styles9 from "./LocaleSwitcher.module-QVLPVGLG.module.css";
261
- import { jsx as jsx9 } from "react/jsx-runtime";
670
+ import styles18 from "./LocaleSwitcher.module-QVLPVGLG.module.css";
671
+ import { jsx as jsx18 } from "react/jsx-runtime";
262
672
  var DEFAULT_ARIA_LABEL = "Select language";
263
673
  function LocaleSwitcher({
264
674
  availableLocales,
@@ -269,16 +679,16 @@ function LocaleSwitcher({
269
679
  }) {
270
680
  const label = ariaLabel ?? DEFAULT_ARIA_LABEL;
271
681
  const format = formatLocale ?? ((locale) => locale);
272
- return /* @__PURE__ */ jsx9("div", { className: styles9.wrapper, children: /* @__PURE__ */ jsx9(
682
+ return /* @__PURE__ */ jsx18("div", { className: styles18.wrapper, children: /* @__PURE__ */ jsx18(
273
683
  "select",
274
684
  {
275
- className: styles9.select,
685
+ className: styles18.select,
276
686
  "aria-label": label,
277
687
  value: currentLocale,
278
688
  onChange: (event) => {
279
689
  onSelect(event.target.value);
280
690
  },
281
- children: availableLocales.map((locale) => /* @__PURE__ */ jsx9("option", { value: locale, children: format(locale) }, locale))
691
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx18("option", { value: locale, children: format(locale) }, locale))
282
692
  }
283
693
  ) });
284
694
  }
@@ -286,7 +696,7 @@ function LocaleSwitcher({
286
696
  // src/components/TakuhonHead.tsx
287
697
  import { generateJsonLd } from "@takuhon/core";
288
698
  import { useEffect } from "react";
289
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
699
+ import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
290
700
  function buildLocaleUrl(pageUrl, locale) {
291
701
  try {
292
702
  const url = new URL(pageUrl);
@@ -353,32 +763,41 @@ function TakuhonHead({ data, siteUrl, pageUrl }) {
353
763
  script.remove();
354
764
  };
355
765
  }, [jsonLdPayload]);
356
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
357
- /* @__PURE__ */ jsx10("title", { children: profile.displayName }),
358
- description ? /* @__PURE__ */ jsx10("meta", { name: "description", content: description }) : null,
359
- canonical ? /* @__PURE__ */ jsx10("link", { rel: "canonical", href: canonical }) : null,
360
- /* @__PURE__ */ jsx10("meta", { property: "og:title", content: profile.displayName }),
361
- ogDescription ? /* @__PURE__ */ jsx10("meta", { property: "og:description", content: ogDescription }) : null,
362
- canonical ? /* @__PURE__ */ jsx10("meta", { property: "og:url", content: canonical }) : null,
363
- ogImage ? /* @__PURE__ */ jsx10("meta", { property: "og:image", content: ogImage }) : null,
364
- /* @__PURE__ */ jsx10("meta", { property: "og:type", content: "profile" }),
365
- /* @__PURE__ */ jsx10("meta", { property: "og:locale", content: resolvedLocale }),
366
- ogAlternates.map((loc) => /* @__PURE__ */ jsx10("meta", { property: "og:locale:alternate", content: loc }, loc)),
367
- /* @__PURE__ */ jsx10("meta", { name: "twitter:card", content: twitterCard }),
368
- alternates.map(({ locale, href }) => /* @__PURE__ */ jsx10("link", { rel: "alternate", hrefLang: locale, href }, locale)),
369
- xDefaultHref ? /* @__PURE__ */ jsx10("link", { rel: "alternate", hrefLang: "x-default", href: xDefaultHref }) : null
766
+ return /* @__PURE__ */ jsxs18(Fragment4, { children: [
767
+ /* @__PURE__ */ jsx19("title", { children: profile.displayName }),
768
+ description ? /* @__PURE__ */ jsx19("meta", { name: "description", content: description }) : null,
769
+ canonical ? /* @__PURE__ */ jsx19("link", { rel: "canonical", href: canonical }) : null,
770
+ /* @__PURE__ */ jsx19("meta", { property: "og:title", content: profile.displayName }),
771
+ ogDescription ? /* @__PURE__ */ jsx19("meta", { property: "og:description", content: ogDescription }) : null,
772
+ canonical ? /* @__PURE__ */ jsx19("meta", { property: "og:url", content: canonical }) : null,
773
+ ogImage ? /* @__PURE__ */ jsx19("meta", { property: "og:image", content: ogImage }) : null,
774
+ /* @__PURE__ */ jsx19("meta", { property: "og:type", content: "profile" }),
775
+ /* @__PURE__ */ jsx19("meta", { property: "og:locale", content: resolvedLocale }),
776
+ ogAlternates.map((loc) => /* @__PURE__ */ jsx19("meta", { property: "og:locale:alternate", content: loc }, loc)),
777
+ /* @__PURE__ */ jsx19("meta", { name: "twitter:card", content: twitterCard }),
778
+ alternates.map(({ locale, href }) => /* @__PURE__ */ jsx19("link", { rel: "alternate", hrefLang: locale, href }, locale)),
779
+ xDefaultHref ? /* @__PURE__ */ jsx19("link", { rel: "alternate", hrefLang: "x-default", href: xDefaultHref }) : null
370
780
  ] });
371
781
  }
372
782
  export {
373
783
  CareerTimeline,
784
+ Certifications,
374
785
  ContactInfo,
786
+ Courses,
787
+ EducationTimeline,
375
788
  Footer,
789
+ HonorsList,
790
+ Languages,
376
791
  LinksList,
377
792
  LocaleSwitcher,
793
+ Memberships,
794
+ Patents,
378
795
  ProfileHeader,
379
796
  ProjectsList,
797
+ Publications,
380
798
  SkillsList,
381
799
  TakuhonHead,
382
- TakuhonProfile
800
+ TakuhonProfile,
801
+ Volunteering
383
802
  };
384
803
  //# sourceMappingURL=index.js.map