@takuhon/ui 0.2.0 → 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
@@ -116,9 +116,44 @@ function ContactInfo({ contact }) {
116
116
  ] });
117
117
  }
118
118
 
119
- // src/components/EducationTimeline.tsx
120
- import styles4 from "./EducationTimeline.module-7YQTH6QU.module.css";
119
+ // src/components/Courses.tsx
120
+ import styles4 from "./Courses.module-EVDSFNGW.module.css";
121
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";
122
157
  function sortEducation(entries) {
123
158
  return [...entries].sort((a, b) => {
124
159
  const aOrder = a.order ?? Number.POSITIVE_INFINITY;
@@ -139,31 +174,31 @@ function composeStudyLine(entry) {
139
174
  function EducationTimeline({ education }) {
140
175
  if (education.length === 0) return null;
141
176
  const ordered = sortEducation(education);
142
- return /* @__PURE__ */ jsxs4("section", { className: styles4.section, "aria-labelledby": "takuhon-education-heading", children: [
143
- /* @__PURE__ */ jsx4("h2", { id: "takuhon-education-heading", className: styles4.heading, children: "Education" }),
144
- /* @__PURE__ */ jsx4("ol", { className: styles4.list, children: ordered.map((entry) => {
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) => {
145
180
  const study = composeStudyLine(entry);
146
- return /* @__PURE__ */ jsxs4("li", { className: styles4.item, children: [
147
- /* @__PURE__ */ jsx4("div", { className: styles4.timelineMarker, "aria-hidden": "true" }),
148
- /* @__PURE__ */ jsxs4("div", { className: styles4.content, children: [
149
- /* @__PURE__ */ jsx4("p", { className: styles4.institution, children: entry.url ? /* @__PURE__ */ jsx4(
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(
150
185
  "a",
151
186
  {
152
- className: styles4.link,
187
+ className: styles5.link,
153
188
  href: entry.url,
154
189
  target: "_blank",
155
190
  rel: "noopener noreferrer",
156
191
  children: entry.institution
157
192
  }
158
193
  ) : entry.institution }),
159
- study ? /* @__PURE__ */ jsx4("p", { className: styles4.study, children: study }) : null,
160
- /* @__PURE__ */ jsxs4("p", { className: styles4.range, children: [
161
- /* @__PURE__ */ jsx4("time", { dateTime: entry.startDate, children: entry.startDate }),
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 }),
162
197
  " \u2013 ",
163
- isOngoing2(entry) ? "Present" : /* @__PURE__ */ jsx4("time", { dateTime: entry.endDate, children: entry.endDate })
198
+ isOngoing2(entry) ? "Present" : /* @__PURE__ */ jsx5("time", { dateTime: entry.endDate, children: entry.endDate })
164
199
  ] }),
165
- entry.grade ? /* @__PURE__ */ jsx4("p", { className: styles4.grade, children: entry.grade }) : null,
166
- entry.description ? /* @__PURE__ */ jsx4("p", { className: styles4.description, children: entry.description }) : null
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
167
202
  ] })
168
203
  ] }, entry.id);
169
204
  }) })
@@ -171,16 +206,16 @@ function EducationTimeline({ education }) {
171
206
  }
172
207
 
173
208
  // src/components/Footer.tsx
174
- import styles5 from "./Footer.module-HLC5GXVI.module.css";
175
- import { jsx as jsx5, jsxs as jsxs5 } 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";
176
211
  function Footer() {
177
- return /* @__PURE__ */ jsx5("footer", { className: styles5.footer, children: /* @__PURE__ */ jsxs5("p", { className: styles5.line, children: [
212
+ return /* @__PURE__ */ jsx6("footer", { className: styles6.footer, children: /* @__PURE__ */ jsxs6("p", { className: styles6.line, children: [
178
213
  "Powered by",
179
214
  " ",
180
- /* @__PURE__ */ jsx5(
215
+ /* @__PURE__ */ jsx6(
181
216
  "a",
182
217
  {
183
- className: styles5.link,
218
+ className: styles6.link,
184
219
  href: "https://github.com/takuhon-dev/takuhon",
185
220
  target: "_blank",
186
221
  rel: "noopener noreferrer",
@@ -191,8 +226,8 @@ function Footer() {
191
226
  }
192
227
 
193
228
  // src/components/HonorsList.tsx
194
- import styles6 from "./HonorsList.module-AQN3CT7O.module.css";
195
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
229
+ import styles7 from "./HonorsList.module-AQN3CT7O.module.css";
230
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
196
231
  function sortHonors(honors) {
197
232
  return [...honors].sort((a, b) => {
198
233
  const aOrder = a.order ?? Number.POSITIVE_INFINITY;
@@ -204,32 +239,32 @@ function sortHonors(honors) {
204
239
  function HonorsList({ honors }) {
205
240
  if (honors.length === 0) return null;
206
241
  const ordered = sortHonors(honors);
207
- return /* @__PURE__ */ jsxs6("section", { className: styles6.section, "aria-labelledby": "takuhon-honors-heading", children: [
208
- /* @__PURE__ */ jsx6("h2", { id: "takuhon-honors-heading", className: styles6.heading, children: "Honors & Awards" }),
209
- /* @__PURE__ */ jsx6("ul", { className: styles6.list, children: ordered.map((honor) => /* @__PURE__ */ jsxs6("li", { className: styles6.item, children: [
210
- /* @__PURE__ */ jsx6("p", { className: styles6.title, children: honor.url ? /* @__PURE__ */ jsx6(
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(
211
246
  "a",
212
247
  {
213
- className: styles6.link,
248
+ className: styles7.link,
214
249
  href: honor.url,
215
250
  target: "_blank",
216
251
  rel: "noopener noreferrer",
217
252
  children: honor.title
218
253
  }
219
254
  ) : honor.title }),
220
- /* @__PURE__ */ jsxs6("p", { className: styles6.meta, children: [
255
+ /* @__PURE__ */ jsxs7("p", { className: styles7.meta, children: [
221
256
  honor.issuer,
222
257
  " \xB7 ",
223
- /* @__PURE__ */ jsx6("time", { dateTime: honor.date, children: honor.date })
258
+ /* @__PURE__ */ jsx7("time", { dateTime: honor.date, children: honor.date })
224
259
  ] }),
225
- honor.description ? /* @__PURE__ */ jsx6("p", { className: styles6.description, children: honor.description }) : null
260
+ honor.description ? /* @__PURE__ */ jsx7("p", { className: styles7.description, children: honor.description }) : null
226
261
  ] }, honor.id)) })
227
262
  ] });
228
263
  }
229
264
 
230
265
  // src/components/Languages.tsx
231
- import styles7 from "./Languages.module-X6RQNFRY.module.css";
232
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
266
+ import styles8 from "./Languages.module-X6RQNFRY.module.css";
267
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
233
268
  var PROFICIENCY_LABEL = {
234
269
  native: "Native",
235
270
  fluent: "Fluent",
@@ -247,18 +282,18 @@ function sortLanguages(languages) {
247
282
  function Languages({ languages }) {
248
283
  if (languages.length === 0) return null;
249
284
  const ordered = sortLanguages(languages);
250
- return /* @__PURE__ */ jsxs7("section", { className: styles7.section, "aria-labelledby": "takuhon-languages-heading", children: [
251
- /* @__PURE__ */ jsx7("h2", { id: "takuhon-languages-heading", className: styles7.heading, children: "Languages" }),
252
- /* @__PURE__ */ jsx7("ul", { className: styles7.list, children: ordered.map((entry) => /* @__PURE__ */ jsxs7("li", { className: styles7.item, children: [
253
- /* @__PURE__ */ jsx7("span", { className: styles7.name, lang: entry.language, children: entry.displayName ?? entry.language }),
254
- /* @__PURE__ */ jsx7("span", { className: styles7.proficiency, children: PROFICIENCY_LABEL[entry.proficiency] })
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] })
255
290
  ] }, entry.id)) })
256
291
  ] });
257
292
  }
258
293
 
259
294
  // src/components/LinksList.tsx
260
- import styles8 from "./LinksList.module-QPSFPOF3.module.css";
261
- import { jsx as jsx8, jsxs as jsxs8 } 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";
262
297
  function sortLinks(links) {
263
298
  return [...links].sort((a, b) => {
264
299
  const aFeatured = a.featured ? 1 : 0;
@@ -277,32 +312,136 @@ function formatLinkLabel(link) {
277
312
  function LinksList({ links }) {
278
313
  if (links.length === 0) return null;
279
314
  const ordered = sortLinks(links);
280
- return /* @__PURE__ */ jsx8("nav", { "aria-label": "Profile links", className: styles8.nav, children: /* @__PURE__ */ jsx8("ul", { className: styles8.list, children: ordered.map((link) => /* @__PURE__ */ jsx8("li", { className: styles8.item, children: /* @__PURE__ */ jsxs8(
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(
281
316
  "a",
282
317
  {
283
- className: styles8.link,
318
+ className: styles9.link,
284
319
  href: link.url,
285
320
  target: "_blank",
286
321
  rel: "noopener noreferrer",
287
322
  "data-featured": link.featured ? "true" : void 0,
288
323
  children: [
289
- link.iconUrl ? /* @__PURE__ */ jsx8("img", { className: styles8.icon, src: link.iconUrl, alt: "" }) : null,
290
- /* @__PURE__ */ jsx8("span", { className: styles8.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) })
291
326
  ]
292
327
  }
293
328
  ) }, link.id)) }) });
294
329
  }
295
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
+
296
435
  // src/components/ProfileHeader.tsx
297
- import styles9 from "./ProfileHeader.module-EK27UTZL.module.css";
298
- import { jsx as jsx9, jsxs as jsxs9 } 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";
299
438
  function ProfileHeader({ profile }) {
300
439
  const locationLabel = profile.location?.display ?? profile.location?.locality;
301
- return /* @__PURE__ */ jsxs9("header", { className: styles9.header, children: [
302
- profile.avatar ? /* @__PURE__ */ jsx9(
440
+ return /* @__PURE__ */ jsxs12("header", { className: styles12.header, children: [
441
+ profile.avatar ? /* @__PURE__ */ jsx12(
303
442
  "img",
304
443
  {
305
- className: styles9.avatar,
444
+ className: styles12.avatar,
306
445
  src: profile.avatar.url,
307
446
  alt: profile.avatar.alt ?? "",
308
447
  width: 128,
@@ -311,16 +450,16 @@ function ProfileHeader({ profile }) {
311
450
  decoding: "async"
312
451
  }
313
452
  ) : null,
314
- /* @__PURE__ */ jsx9("h1", { className: styles9.displayName, children: profile.displayName }),
315
- profile.tagline ? /* @__PURE__ */ jsx9("p", { className: styles9.tagline, children: profile.tagline }) : null,
316
- locationLabel ? /* @__PURE__ */ jsx9("p", { className: styles9.location, children: locationLabel }) : null,
317
- profile.bio ? /* @__PURE__ */ jsx9("p", { className: styles9.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
318
457
  ] });
319
458
  }
320
459
 
321
460
  // src/components/ProjectsList.tsx
322
- import styles10 from "./ProjectsList.module-JKGGZRKO.module.css";
323
- import { jsx as jsx10, jsxs as jsxs10 } 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";
324
463
  function sortProjects(projects) {
325
464
  return [...projects].sort((a, b) => {
326
465
  const aHighlighted = a.highlighted ? 1 : 0;
@@ -334,31 +473,31 @@ function sortProjects(projects) {
334
473
  function ProjectsList({ projects }) {
335
474
  if (projects.length === 0) return null;
336
475
  const ordered = sortProjects(projects);
337
- return /* @__PURE__ */ jsxs10("section", { className: styles10.section, "aria-labelledby": "takuhon-projects-heading", children: [
338
- /* @__PURE__ */ jsx10("h2", { id: "takuhon-projects-heading", className: styles10.heading, children: "Projects" }),
339
- /* @__PURE__ */ jsx10("ul", { className: styles10.list, children: ordered.map((project) => /* @__PURE__ */ jsxs10(
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(
340
479
  "li",
341
480
  {
342
- className: styles10.item,
481
+ className: styles13.item,
343
482
  "data-highlighted": project.highlighted ? "true" : void 0,
344
483
  children: [
345
- /* @__PURE__ */ jsx10("p", { className: styles10.title, children: project.url ? /* @__PURE__ */ jsx10(
484
+ /* @__PURE__ */ jsx13("p", { className: styles13.title, children: project.url ? /* @__PURE__ */ jsx13(
346
485
  "a",
347
486
  {
348
- className: styles10.titleLink,
487
+ className: styles13.titleLink,
349
488
  href: project.url,
350
489
  target: "_blank",
351
490
  rel: "noopener noreferrer",
352
491
  children: project.title
353
492
  }
354
493
  ) : project.title }),
355
- project.startDate !== void 0 ? /* @__PURE__ */ jsxs10("p", { className: styles10.range, children: [
356
- /* @__PURE__ */ jsx10("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 }),
357
496
  " \u2013 ",
358
- project.endDate ? /* @__PURE__ */ jsx10("time", { dateTime: project.endDate, children: project.endDate }) : "Present"
497
+ project.endDate ? /* @__PURE__ */ jsx13("time", { dateTime: project.endDate, children: project.endDate }) : "Present"
359
498
  ] }) : null,
360
- project.description ? /* @__PURE__ */ jsx10("p", { className: styles10.description, children: project.description }) : null,
361
- project.tags && project.tags.length > 0 ? /* @__PURE__ */ jsx10("ul", { className: styles10.tags, "aria-label": "Tags", children: project.tags.map((tag) => /* @__PURE__ */ jsx10("li", { className: styles10.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
362
501
  ]
363
502
  },
364
503
  project.id
@@ -366,9 +505,60 @@ function ProjectsList({ projects }) {
366
505
  ] });
367
506
  }
368
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
+
369
559
  // src/components/SkillsList.tsx
370
- import styles11 from "./SkillsList.module-XIAWE55H.module.css";
371
- import { jsx as jsx11, jsxs as jsxs11 } 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";
372
562
  function groupSkills(skills) {
373
563
  const sorted = [...skills].sort((a, b) => {
374
564
  const aOrder = a.order ?? Number.POSITIVE_INFINITY;
@@ -390,38 +580,95 @@ function groupSkills(skills) {
390
580
  function SkillsList({ skills }) {
391
581
  if (skills.length === 0) return null;
392
582
  const groups = groupSkills(skills);
393
- return /* @__PURE__ */ jsxs11("section", { className: styles11.section, "aria-labelledby": "takuhon-skills-heading", children: [
394
- /* @__PURE__ */ jsx11("h2", { id: "takuhon-skills-heading", className: styles11.heading, children: "Skills" }),
395
- /* @__PURE__ */ jsx11("div", { className: styles11.groups, children: groups.map((group) => /* @__PURE__ */ jsxs11("div", { className: styles11.group, children: [
396
- /* @__PURE__ */ jsx11("h3", { className: styles11.category, children: group.category }),
397
- /* @__PURE__ */ jsx11("ul", { className: styles11.list, "aria-label": `${group.category} skills`, children: group.skills.map((skill) => /* @__PURE__ */ jsx11("li", { className: styles11.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)) })
398
588
  ] }, group.category)) })
399
589
  ] });
400
590
  }
401
591
 
402
592
  // src/components/TakuhonProfile.tsx
403
- import styles12 from "./TakuhonProfile.module-QUEORIHA.module.css";
404
- import { jsx as jsx12, jsxs as jsxs12 } 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";
405
647
  function TakuhonProfile({ data }) {
406
648
  const showFooter = data.settings.showPoweredBy !== false;
407
- return /* @__PURE__ */ jsxs12("article", { className: styles12.root, children: [
408
- /* @__PURE__ */ jsx12(ProfileHeader, { profile: data.profile }),
409
- /* @__PURE__ */ jsx12(LinksList, { links: data.links }),
410
- /* @__PURE__ */ jsx12(EducationTimeline, { education: data.education }),
411
- /* @__PURE__ */ jsx12(CareerTimeline, { careers: data.careers }),
412
- /* @__PURE__ */ jsx12(Certifications, { certifications: data.certifications }),
413
- /* @__PURE__ */ jsx12(ProjectsList, { projects: data.projects }),
414
- /* @__PURE__ */ jsx12(HonorsList, { honors: data.honors }),
415
- /* @__PURE__ */ jsx12(SkillsList, { skills: data.skills }),
416
- /* @__PURE__ */ jsx12(Languages, { languages: data.languages }),
417
- /* @__PURE__ */ jsx12(ContactInfo, { contact: data.contact }),
418
- showFooter ? /* @__PURE__ */ jsx12(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
419
666
  ] });
420
667
  }
421
668
 
422
669
  // src/components/LocaleSwitcher.tsx
423
- import styles13 from "./LocaleSwitcher.module-QVLPVGLG.module.css";
424
- import { jsx as jsx13 } from "react/jsx-runtime";
670
+ import styles18 from "./LocaleSwitcher.module-QVLPVGLG.module.css";
671
+ import { jsx as jsx18 } from "react/jsx-runtime";
425
672
  var DEFAULT_ARIA_LABEL = "Select language";
426
673
  function LocaleSwitcher({
427
674
  availableLocales,
@@ -432,16 +679,16 @@ function LocaleSwitcher({
432
679
  }) {
433
680
  const label = ariaLabel ?? DEFAULT_ARIA_LABEL;
434
681
  const format = formatLocale ?? ((locale) => locale);
435
- return /* @__PURE__ */ jsx13("div", { className: styles13.wrapper, children: /* @__PURE__ */ jsx13(
682
+ return /* @__PURE__ */ jsx18("div", { className: styles18.wrapper, children: /* @__PURE__ */ jsx18(
436
683
  "select",
437
684
  {
438
- className: styles13.select,
685
+ className: styles18.select,
439
686
  "aria-label": label,
440
687
  value: currentLocale,
441
688
  onChange: (event) => {
442
689
  onSelect(event.target.value);
443
690
  },
444
- children: availableLocales.map((locale) => /* @__PURE__ */ jsx13("option", { value: locale, children: format(locale) }, locale))
691
+ children: availableLocales.map((locale) => /* @__PURE__ */ jsx18("option", { value: locale, children: format(locale) }, locale))
445
692
  }
446
693
  ) });
447
694
  }
@@ -449,7 +696,7 @@ function LocaleSwitcher({
449
696
  // src/components/TakuhonHead.tsx
450
697
  import { generateJsonLd } from "@takuhon/core";
451
698
  import { useEffect } from "react";
452
- import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
699
+ import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
453
700
  function buildLocaleUrl(pageUrl, locale) {
454
701
  try {
455
702
  const url = new URL(pageUrl);
@@ -516,36 +763,41 @@ function TakuhonHead({ data, siteUrl, pageUrl }) {
516
763
  script.remove();
517
764
  };
518
765
  }, [jsonLdPayload]);
519
- return /* @__PURE__ */ jsxs13(Fragment3, { children: [
520
- /* @__PURE__ */ jsx14("title", { children: profile.displayName }),
521
- description ? /* @__PURE__ */ jsx14("meta", { name: "description", content: description }) : null,
522
- canonical ? /* @__PURE__ */ jsx14("link", { rel: "canonical", href: canonical }) : null,
523
- /* @__PURE__ */ jsx14("meta", { property: "og:title", content: profile.displayName }),
524
- ogDescription ? /* @__PURE__ */ jsx14("meta", { property: "og:description", content: ogDescription }) : null,
525
- canonical ? /* @__PURE__ */ jsx14("meta", { property: "og:url", content: canonical }) : null,
526
- ogImage ? /* @__PURE__ */ jsx14("meta", { property: "og:image", content: ogImage }) : null,
527
- /* @__PURE__ */ jsx14("meta", { property: "og:type", content: "profile" }),
528
- /* @__PURE__ */ jsx14("meta", { property: "og:locale", content: resolvedLocale }),
529
- ogAlternates.map((loc) => /* @__PURE__ */ jsx14("meta", { property: "og:locale:alternate", content: loc }, loc)),
530
- /* @__PURE__ */ jsx14("meta", { name: "twitter:card", content: twitterCard }),
531
- alternates.map(({ locale, href }) => /* @__PURE__ */ jsx14("link", { rel: "alternate", hrefLang: locale, href }, locale)),
532
- xDefaultHref ? /* @__PURE__ */ jsx14("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
533
780
  ] });
534
781
  }
535
782
  export {
536
783
  CareerTimeline,
537
784
  Certifications,
538
785
  ContactInfo,
786
+ Courses,
539
787
  EducationTimeline,
540
788
  Footer,
541
789
  HonorsList,
542
790
  Languages,
543
791
  LinksList,
544
792
  LocaleSwitcher,
793
+ Memberships,
794
+ Patents,
545
795
  ProfileHeader,
546
796
  ProjectsList,
797
+ Publications,
547
798
  SkillsList,
548
799
  TakuhonHead,
549
- TakuhonProfile
800
+ TakuhonProfile,
801
+ Volunteering
550
802
  };
551
803
  //# sourceMappingURL=index.js.map