@takuhon/ui 0.12.0 → 0.13.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/CvView.module-4V6YB2ID.module.css +143 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.js +234 -20
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* A4 single-column résumé. On screen the article is a centered "sheet" on a
|
|
2
|
+
neutral backdrop; @media print drops the backdrop and margins so the page
|
|
3
|
+
fills the sheet, and break-inside:avoid keeps entries from splitting across
|
|
4
|
+
pages. Mirrors the CLI's renderCvHtml so the two surfaces match. */
|
|
5
|
+
|
|
6
|
+
.cv {
|
|
7
|
+
display: block;
|
|
8
|
+
width: 210mm;
|
|
9
|
+
min-height: 297mm;
|
|
10
|
+
margin: 1.5rem auto;
|
|
11
|
+
padding: 18mm 16mm;
|
|
12
|
+
background: #fff;
|
|
13
|
+
color: var(--takuhon-color-text, #1a1a1a);
|
|
14
|
+
font-size: 13px;
|
|
15
|
+
line-height: 1.5;
|
|
16
|
+
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.header {
|
|
20
|
+
border-bottom: 2px solid var(--takuhon-color-text, #1a1a1a);
|
|
21
|
+
padding-bottom: 0.6rem;
|
|
22
|
+
margin-bottom: 0.4rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.name {
|
|
26
|
+
font-size: 1.7rem;
|
|
27
|
+
margin: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.tagline {
|
|
31
|
+
font-size: 1.05rem;
|
|
32
|
+
color: var(--takuhon-color-text-muted, #555);
|
|
33
|
+
margin: 0.15rem 0 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.contact {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-wrap: wrap;
|
|
39
|
+
gap: 0.25rem 1rem;
|
|
40
|
+
color: var(--takuhon-color-text-muted, #555);
|
|
41
|
+
font-size: 0.85rem;
|
|
42
|
+
margin: 0.4rem 0 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.contact a {
|
|
46
|
+
color: var(--takuhon-color-accent, #0b5fff);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.bio {
|
|
50
|
+
margin: 0.75rem 0 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.section {
|
|
54
|
+
margin-top: 1.1rem;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.heading {
|
|
58
|
+
font-size: 0.95rem;
|
|
59
|
+
text-transform: uppercase;
|
|
60
|
+
letter-spacing: 0.05em;
|
|
61
|
+
color: var(--takuhon-color-accent, #0b5fff);
|
|
62
|
+
border-bottom: 1px solid var(--takuhon-color-border, #d9d9d9);
|
|
63
|
+
margin: 0 0 0.5rem;
|
|
64
|
+
padding-bottom: 0.15rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.list {
|
|
68
|
+
list-style: none;
|
|
69
|
+
margin: 0;
|
|
70
|
+
padding: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.entry {
|
|
74
|
+
margin: 0 0 0.7rem;
|
|
75
|
+
break-inside: avoid;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.row {
|
|
79
|
+
display: flex;
|
|
80
|
+
justify-content: space-between;
|
|
81
|
+
gap: 1rem;
|
|
82
|
+
align-items: baseline;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.entryHeading {
|
|
86
|
+
font-size: 0.95rem;
|
|
87
|
+
margin: 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.entryHeading a {
|
|
91
|
+
color: var(--takuhon-color-accent, #0b5fff);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.dates {
|
|
95
|
+
color: var(--takuhon-color-text-muted, #555);
|
|
96
|
+
font-size: 0.8rem;
|
|
97
|
+
white-space: nowrap;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.sub {
|
|
101
|
+
color: var(--takuhon-color-text-muted, #555);
|
|
102
|
+
margin: 0.05rem 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.body {
|
|
106
|
+
margin: 0.2rem 0 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.chips {
|
|
110
|
+
list-style: none;
|
|
111
|
+
margin: 0;
|
|
112
|
+
padding: 0;
|
|
113
|
+
display: flex;
|
|
114
|
+
flex-wrap: wrap;
|
|
115
|
+
gap: 0.3rem;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.chip {
|
|
119
|
+
border: 1px solid var(--takuhon-color-border, #d9d9d9);
|
|
120
|
+
border-radius: 1rem;
|
|
121
|
+
padding: 0.05rem 0.55rem;
|
|
122
|
+
font-size: 0.8rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@media print {
|
|
126
|
+
.cv {
|
|
127
|
+
width: auto;
|
|
128
|
+
min-height: 0;
|
|
129
|
+
margin: 0;
|
|
130
|
+
padding: 0;
|
|
131
|
+
box-shadow: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.entryHeading a,
|
|
135
|
+
.contact a {
|
|
136
|
+
color: var(--takuhon-color-text, #1a1a1a);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@page {
|
|
141
|
+
size: A4;
|
|
142
|
+
margin: 14mm;
|
|
143
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LocalizedTakuhon, ActivitySnapshot, LocaleTag, LocalizedProfile, LocalizedLink, LocalizedCareer, LocalizedEducation, LocalizedCertification, LocalizedMembership, LocalizedVolunteering, LocalizedHonor, LocalizedRecommendation, LocalizedPublication, LocalizedLanguage, LocalizedTestScore, LocalizedCourse, LocalizedPatent, LocalizedProject, Skill, Contact } from '@takuhon/core';
|
|
1
|
+
import { LocalizedTakuhon, ActivitySnapshot, LocaleTag, CvDocument, LocalizedProfile, LocalizedLink, LocalizedCareer, LocalizedEducation, LocalizedCertification, LocalizedMembership, LocalizedVolunteering, LocalizedHonor, LocalizedRecommendation, LocalizedPublication, LocalizedLanguage, LocalizedTestScore, LocalizedCourse, LocalizedPatent, LocalizedProject, Skill, Contact } from '@takuhon/core';
|
|
2
2
|
|
|
3
3
|
interface TakuhonProfileProps {
|
|
4
4
|
data: LocalizedTakuhon;
|
|
@@ -30,6 +30,22 @@ interface ActivitySectionProps {
|
|
|
30
30
|
*/
|
|
31
31
|
declare function ActivitySection({ snapshot, locale, }: ActivitySectionProps): React.JSX.Element | null;
|
|
32
32
|
|
|
33
|
+
interface CvViewProps {
|
|
34
|
+
/** The CV projection from `@takuhon/core`'s `deriveCv` (already privacy-filtered upstream). */
|
|
35
|
+
cv: CvDocument;
|
|
36
|
+
/** Locale for headings and dates; defaults to the CV's resolved locale. */
|
|
37
|
+
locale?: LocaleTag;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Print-ready résumé/CV view, the React counterpart of the CLI's `renderCvHtml`.
|
|
41
|
+
* Renders a {@link CvDocument} (from `@takuhon/core`'s `deriveCv`) as an A4
|
|
42
|
+
* single-column document; the co-located CSS module carries an `@media print`
|
|
43
|
+
* block so the browser's "Save as PDF" yields a clean résumé. This is a
|
|
44
|
+
* presentational component (it shows what `deriveCv` gives it, which the host
|
|
45
|
+
* has already privacy-filtered) and renders nothing for an empty CV.
|
|
46
|
+
*/
|
|
47
|
+
declare function CvView({ cv, locale }: CvViewProps): React.JSX.Element | null;
|
|
48
|
+
|
|
33
49
|
interface ProfileHeaderProps {
|
|
34
50
|
profile: LocalizedProfile;
|
|
35
51
|
}
|
|
@@ -149,4 +165,4 @@ interface TakuhonHeadProps {
|
|
|
149
165
|
}
|
|
150
166
|
declare function TakuhonHead({ data, siteUrl, pageUrl }: TakuhonHeadProps): React.JSX.Element;
|
|
151
167
|
|
|
152
|
-
export { ActivitySection, type ActivitySectionProps, CareerTimeline, type CareerTimelineProps, Certifications, type CertificationsProps, ContactInfo, type ContactInfoProps, Courses, type CoursesProps, EducationTimeline, type EducationTimelineProps, Footer, HonorsList, type HonorsListProps, Languages, type LanguagesProps, LinksList, type LinksListProps, LocaleSwitcher, type LocaleSwitcherProps, Memberships, type MembershipsProps, Patents, type PatentsProps, ProfileHeader, type ProfileHeaderProps, ProjectsList, type ProjectsListProps, Publications, type PublicationsProps, Recommendations, type RecommendationsProps, SkillsList, type SkillsListProps, TakuhonHead, type TakuhonHeadProps, TakuhonProfile, type TakuhonProfileProps, TestScores, type TestScoresProps, Volunteering, type VolunteeringProps };
|
|
168
|
+
export { ActivitySection, type ActivitySectionProps, CareerTimeline, type CareerTimelineProps, Certifications, type CertificationsProps, ContactInfo, type ContactInfoProps, Courses, type CoursesProps, CvView, type CvViewProps, EducationTimeline, type EducationTimelineProps, Footer, HonorsList, type HonorsListProps, Languages, type LanguagesProps, LinksList, type LinksListProps, LocaleSwitcher, type LocaleSwitcherProps, Memberships, type MembershipsProps, Patents, type PatentsProps, ProfileHeader, type ProfileHeaderProps, ProjectsList, type ProjectsListProps, Publications, type PublicationsProps, Recommendations, type RecommendationsProps, SkillsList, type SkillsListProps, TakuhonHead, type TakuhonHeadProps, TakuhonProfile, type TakuhonProfileProps, TestScores, type TestScoresProps, Volunteering, type VolunteeringProps };
|
package/dist/index.js
CHANGED
|
@@ -913,9 +913,222 @@ function TakuhonProfile({ data, activitySnapshot }) {
|
|
|
913
913
|
] });
|
|
914
914
|
}
|
|
915
915
|
|
|
916
|
+
// src/components/CvView.tsx
|
|
917
|
+
import styles21 from "./CvView.module-4V6YB2ID.module.css";
|
|
918
|
+
import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
919
|
+
var SECTION_LABEL = {
|
|
920
|
+
experience: "section.career",
|
|
921
|
+
education: "section.education",
|
|
922
|
+
skills: "section.skills",
|
|
923
|
+
certifications: "section.certifications",
|
|
924
|
+
publications: "section.publications",
|
|
925
|
+
honors: "section.honors",
|
|
926
|
+
courses: "section.courses",
|
|
927
|
+
patents: "section.patents",
|
|
928
|
+
languages: "section.languages",
|
|
929
|
+
volunteering: "section.volunteering",
|
|
930
|
+
memberships: "section.memberships"
|
|
931
|
+
};
|
|
932
|
+
function joinNonEmpty(values, separator) {
|
|
933
|
+
const joined = values.filter((v) => typeof v === "string" && v.length > 0).join(separator);
|
|
934
|
+
return joined.length > 0 ? joined : void 0;
|
|
935
|
+
}
|
|
936
|
+
function EntryList({ entries }) {
|
|
937
|
+
return /* @__PURE__ */ jsx21("ul", { className: styles21.list, children: entries.map((e) => /* @__PURE__ */ jsxs21("li", { className: styles21.entry, children: [
|
|
938
|
+
/* @__PURE__ */ jsxs21("div", { className: styles21.row, children: [
|
|
939
|
+
/* @__PURE__ */ jsx21("h3", { className: styles21.entryHeading, children: e.url !== void 0 ? /* @__PURE__ */ jsx21("a", { href: e.url, children: e.heading }) : e.heading }),
|
|
940
|
+
e.dates !== void 0 ? /* @__PURE__ */ jsx21("span", { className: styles21.dates, children: e.dates }) : null
|
|
941
|
+
] }),
|
|
942
|
+
e.sub !== void 0 ? /* @__PURE__ */ jsx21("p", { className: styles21.sub, children: e.sub }) : null,
|
|
943
|
+
e.body !== void 0 ? /* @__PURE__ */ jsx21("p", { className: styles21.body, children: e.body }) : null
|
|
944
|
+
] }, e.key)) });
|
|
945
|
+
}
|
|
946
|
+
function ChipList({ labels }) {
|
|
947
|
+
return /* @__PURE__ */ jsx21("ul", { className: styles21.chips, children: labels.map((label, i) => /* @__PURE__ */ jsx21("li", { className: styles21.chip, children: label }, `${label}-${String(i)}`)) });
|
|
948
|
+
}
|
|
949
|
+
function range(locale, start, end, isCurrent) {
|
|
950
|
+
const left = start ? formatYearMonth(start, locale) : "";
|
|
951
|
+
const ongoing = isCurrent === true || end === null;
|
|
952
|
+
const right = ongoing ? getUILabel("timeline.present", locale) : end ? formatYearMonth(end, locale) : "";
|
|
953
|
+
const text = left && right ? `${left} \u2013 ${right}` : left || right;
|
|
954
|
+
return text || void 0;
|
|
955
|
+
}
|
|
956
|
+
function languageLabel(l, locale) {
|
|
957
|
+
const name = l.displayName ?? l.language;
|
|
958
|
+
return `${name} \u2014 ${getUILabel(`proficiency.${l.proficiency}`, locale)}`;
|
|
959
|
+
}
|
|
960
|
+
function SectionBody({
|
|
961
|
+
section,
|
|
962
|
+
locale
|
|
963
|
+
}) {
|
|
964
|
+
switch (section.kind) {
|
|
965
|
+
case "experience":
|
|
966
|
+
return /* @__PURE__ */ jsx21(
|
|
967
|
+
EntryList,
|
|
968
|
+
{
|
|
969
|
+
entries: section.entries.map((c) => ({
|
|
970
|
+
key: c.id,
|
|
971
|
+
heading: c.role,
|
|
972
|
+
sub: c.organization,
|
|
973
|
+
dates: range(locale, c.startDate, c.endDate, c.isCurrent),
|
|
974
|
+
body: c.description,
|
|
975
|
+
url: c.url
|
|
976
|
+
}))
|
|
977
|
+
}
|
|
978
|
+
);
|
|
979
|
+
case "education":
|
|
980
|
+
return /* @__PURE__ */ jsx21(
|
|
981
|
+
EntryList,
|
|
982
|
+
{
|
|
983
|
+
entries: section.entries.map((e) => {
|
|
984
|
+
const degree = joinNonEmpty([e.degree, e.fieldOfStudy], ", ");
|
|
985
|
+
return {
|
|
986
|
+
key: e.id,
|
|
987
|
+
heading: degree ?? e.institution,
|
|
988
|
+
sub: degree ? e.institution : void 0,
|
|
989
|
+
dates: range(locale, e.startDate, e.endDate, e.isCurrent),
|
|
990
|
+
body: e.description,
|
|
991
|
+
url: e.url
|
|
992
|
+
};
|
|
993
|
+
})
|
|
994
|
+
}
|
|
995
|
+
);
|
|
996
|
+
case "skills":
|
|
997
|
+
return /* @__PURE__ */ jsx21(ChipList, { labels: section.entries.map((s) => s.label) });
|
|
998
|
+
case "languages":
|
|
999
|
+
return /* @__PURE__ */ jsx21(ChipList, { labels: section.entries.map((l) => languageLabel(l, locale)) });
|
|
1000
|
+
case "certifications":
|
|
1001
|
+
return /* @__PURE__ */ jsx21(
|
|
1002
|
+
EntryList,
|
|
1003
|
+
{
|
|
1004
|
+
entries: section.entries.map((c) => ({
|
|
1005
|
+
key: c.id,
|
|
1006
|
+
heading: c.title,
|
|
1007
|
+
sub: c.issuingOrganization,
|
|
1008
|
+
dates: range(locale, c.issueDate, c.expirationDate),
|
|
1009
|
+
url: c.url
|
|
1010
|
+
}))
|
|
1011
|
+
}
|
|
1012
|
+
);
|
|
1013
|
+
case "publications":
|
|
1014
|
+
return /* @__PURE__ */ jsx21(
|
|
1015
|
+
EntryList,
|
|
1016
|
+
{
|
|
1017
|
+
entries: section.entries.map((x) => ({
|
|
1018
|
+
key: x.id,
|
|
1019
|
+
heading: x.title,
|
|
1020
|
+
sub: joinNonEmpty([x.publisher, x.coAuthors?.join(", ")], " \xB7 "),
|
|
1021
|
+
dates: range(locale, x.date),
|
|
1022
|
+
body: x.description,
|
|
1023
|
+
url: x.url ?? (x.doi ? `https://doi.org/${x.doi}` : void 0)
|
|
1024
|
+
}))
|
|
1025
|
+
}
|
|
1026
|
+
);
|
|
1027
|
+
case "honors":
|
|
1028
|
+
return /* @__PURE__ */ jsx21(
|
|
1029
|
+
EntryList,
|
|
1030
|
+
{
|
|
1031
|
+
entries: section.entries.map((x) => ({
|
|
1032
|
+
key: x.id,
|
|
1033
|
+
heading: x.title,
|
|
1034
|
+
sub: x.issuer,
|
|
1035
|
+
dates: range(locale, x.date),
|
|
1036
|
+
body: x.description,
|
|
1037
|
+
url: x.url
|
|
1038
|
+
}))
|
|
1039
|
+
}
|
|
1040
|
+
);
|
|
1041
|
+
case "courses":
|
|
1042
|
+
return /* @__PURE__ */ jsx21(
|
|
1043
|
+
EntryList,
|
|
1044
|
+
{
|
|
1045
|
+
entries: section.entries.map((x) => ({
|
|
1046
|
+
key: x.id,
|
|
1047
|
+
heading: x.title,
|
|
1048
|
+
sub: x.provider,
|
|
1049
|
+
dates: range(locale, x.completionDate),
|
|
1050
|
+
body: x.description,
|
|
1051
|
+
url: x.certificateUrl
|
|
1052
|
+
}))
|
|
1053
|
+
}
|
|
1054
|
+
);
|
|
1055
|
+
case "patents":
|
|
1056
|
+
return /* @__PURE__ */ jsx21(
|
|
1057
|
+
EntryList,
|
|
1058
|
+
{
|
|
1059
|
+
entries: section.entries.map((x) => ({
|
|
1060
|
+
key: x.id,
|
|
1061
|
+
heading: x.title,
|
|
1062
|
+
sub: joinNonEmpty([x.patentNumber, x.office, x.status], " \xB7 "),
|
|
1063
|
+
dates: range(locale, x.filingDate ?? x.grantDate),
|
|
1064
|
+
body: x.description,
|
|
1065
|
+
url: x.url
|
|
1066
|
+
}))
|
|
1067
|
+
}
|
|
1068
|
+
);
|
|
1069
|
+
case "volunteering":
|
|
1070
|
+
return /* @__PURE__ */ jsx21(
|
|
1071
|
+
EntryList,
|
|
1072
|
+
{
|
|
1073
|
+
entries: section.entries.map((x) => ({
|
|
1074
|
+
key: x.id,
|
|
1075
|
+
heading: x.role,
|
|
1076
|
+
sub: joinNonEmpty([x.organization, x.cause], " \xB7 "),
|
|
1077
|
+
dates: range(locale, x.startDate, x.endDate, x.isCurrent),
|
|
1078
|
+
body: x.description,
|
|
1079
|
+
url: x.url
|
|
1080
|
+
}))
|
|
1081
|
+
}
|
|
1082
|
+
);
|
|
1083
|
+
case "memberships":
|
|
1084
|
+
return /* @__PURE__ */ jsx21(
|
|
1085
|
+
EntryList,
|
|
1086
|
+
{
|
|
1087
|
+
entries: section.entries.map((x) => ({
|
|
1088
|
+
key: x.id,
|
|
1089
|
+
heading: x.role ?? x.organization,
|
|
1090
|
+
sub: x.role ? x.organization : void 0,
|
|
1091
|
+
dates: range(locale, x.startDate, x.endDate, x.isCurrent),
|
|
1092
|
+
body: x.description,
|
|
1093
|
+
url: x.url
|
|
1094
|
+
}))
|
|
1095
|
+
}
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
function CvView({ cv, locale }) {
|
|
1100
|
+
const loc = locale ?? cv.resolvedLocale;
|
|
1101
|
+
const h = cv.header;
|
|
1102
|
+
if (cv.sections.length === 0 && h.displayName === "") return null;
|
|
1103
|
+
const contact = [];
|
|
1104
|
+
if (h.location !== void 0) contact.push(/* @__PURE__ */ jsx21("span", { children: h.location }, "loc"));
|
|
1105
|
+
if (h.email !== void 0) {
|
|
1106
|
+
contact.push(
|
|
1107
|
+
/* @__PURE__ */ jsx21("a", { href: `mailto:${h.email}`, children: h.email }, "email")
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1110
|
+
if (h.formUrl !== void 0) {
|
|
1111
|
+
contact.push(
|
|
1112
|
+
/* @__PURE__ */ jsx21("a", { href: h.formUrl, children: getUILabel("contact.formLink", loc) }, "form")
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
return /* @__PURE__ */ jsxs21("article", { className: styles21.cv, lang: loc, children: [
|
|
1116
|
+
/* @__PURE__ */ jsxs21("header", { className: styles21.header, children: [
|
|
1117
|
+
/* @__PURE__ */ jsx21("h1", { className: styles21.name, children: h.displayName }),
|
|
1118
|
+
h.tagline !== void 0 ? /* @__PURE__ */ jsx21("p", { className: styles21.tagline, children: h.tagline }) : null,
|
|
1119
|
+
contact.length > 0 ? /* @__PURE__ */ jsx21("div", { className: styles21.contact, children: contact }) : null,
|
|
1120
|
+
h.bio !== void 0 ? /* @__PURE__ */ jsx21("p", { className: styles21.bio, children: h.bio }) : null
|
|
1121
|
+
] }),
|
|
1122
|
+
cv.sections.map((section) => /* @__PURE__ */ jsxs21("section", { className: styles21.section, children: [
|
|
1123
|
+
/* @__PURE__ */ jsx21("h2", { className: styles21.heading, children: getUILabel(SECTION_LABEL[section.kind], loc) }),
|
|
1124
|
+
/* @__PURE__ */ jsx21(SectionBody, { section, locale: loc })
|
|
1125
|
+
] }, section.kind))
|
|
1126
|
+
] });
|
|
1127
|
+
}
|
|
1128
|
+
|
|
916
1129
|
// src/components/LocaleSwitcher.tsx
|
|
917
|
-
import
|
|
918
|
-
import { jsx as
|
|
1130
|
+
import styles22 from "./LocaleSwitcher.module-QVLPVGLG.module.css";
|
|
1131
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
919
1132
|
function LocaleSwitcher({
|
|
920
1133
|
availableLocales,
|
|
921
1134
|
currentLocale,
|
|
@@ -925,16 +1138,16 @@ function LocaleSwitcher({
|
|
|
925
1138
|
}) {
|
|
926
1139
|
const label = ariaLabel ?? getUILabel("a11y.selectLanguage", currentLocale);
|
|
927
1140
|
const format = formatLocale ?? ((locale) => locale);
|
|
928
|
-
return /* @__PURE__ */
|
|
1141
|
+
return /* @__PURE__ */ jsx22("div", { className: styles22.wrapper, children: /* @__PURE__ */ jsx22(
|
|
929
1142
|
"select",
|
|
930
1143
|
{
|
|
931
|
-
className:
|
|
1144
|
+
className: styles22.select,
|
|
932
1145
|
"aria-label": label,
|
|
933
1146
|
value: currentLocale,
|
|
934
1147
|
onChange: (event) => {
|
|
935
1148
|
onSelect(event.target.value);
|
|
936
1149
|
},
|
|
937
|
-
children: availableLocales.map((locale) => /* @__PURE__ */
|
|
1150
|
+
children: availableLocales.map((locale) => /* @__PURE__ */ jsx22("option", { value: locale, children: format(locale) }, locale))
|
|
938
1151
|
}
|
|
939
1152
|
) });
|
|
940
1153
|
}
|
|
@@ -942,7 +1155,7 @@ function LocaleSwitcher({
|
|
|
942
1155
|
// src/components/TakuhonHead.tsx
|
|
943
1156
|
import { generateJsonLd } from "@takuhon/core";
|
|
944
1157
|
import { useEffect } from "react";
|
|
945
|
-
import { Fragment as Fragment4, jsx as
|
|
1158
|
+
import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
946
1159
|
function primarySubtag(tag) {
|
|
947
1160
|
const dash = tag.indexOf("-");
|
|
948
1161
|
return (dash === -1 ? tag : tag.slice(0, dash)).toLowerCase();
|
|
@@ -1027,20 +1240,20 @@ function TakuhonHead({ data, siteUrl, pageUrl }) {
|
|
|
1027
1240
|
script.remove();
|
|
1028
1241
|
};
|
|
1029
1242
|
}, [jsonLdPayload]);
|
|
1030
|
-
return /* @__PURE__ */
|
|
1031
|
-
/* @__PURE__ */
|
|
1032
|
-
description ? /* @__PURE__ */
|
|
1033
|
-
canonical ? /* @__PURE__ */
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
ogDescription ? /* @__PURE__ */
|
|
1036
|
-
canonical ? /* @__PURE__ */
|
|
1037
|
-
ogImage ? /* @__PURE__ */
|
|
1038
|
-
/* @__PURE__ */
|
|
1039
|
-
/* @__PURE__ */
|
|
1040
|
-
ogAlternates.map((loc) => /* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
alternates.map(({ locale, href }) => /* @__PURE__ */
|
|
1043
|
-
xDefaultHref ? /* @__PURE__ */
|
|
1243
|
+
return /* @__PURE__ */ jsxs22(Fragment4, { children: [
|
|
1244
|
+
/* @__PURE__ */ jsx23("title", { children: profile.displayName }),
|
|
1245
|
+
description ? /* @__PURE__ */ jsx23("meta", { name: "description", content: description }) : null,
|
|
1246
|
+
canonical ? /* @__PURE__ */ jsx23("link", { rel: "canonical", href: canonical }) : null,
|
|
1247
|
+
/* @__PURE__ */ jsx23("meta", { property: "og:title", content: profile.displayName }),
|
|
1248
|
+
ogDescription ? /* @__PURE__ */ jsx23("meta", { property: "og:description", content: ogDescription }) : null,
|
|
1249
|
+
canonical ? /* @__PURE__ */ jsx23("meta", { property: "og:url", content: canonical }) : null,
|
|
1250
|
+
ogImage ? /* @__PURE__ */ jsx23("meta", { property: "og:image", content: ogImage }) : null,
|
|
1251
|
+
/* @__PURE__ */ jsx23("meta", { property: "og:type", content: "profile" }),
|
|
1252
|
+
/* @__PURE__ */ jsx23("meta", { property: "og:locale", content: resolvedLocale }),
|
|
1253
|
+
ogAlternates.map((loc) => /* @__PURE__ */ jsx23("meta", { property: "og:locale:alternate", content: loc }, loc)),
|
|
1254
|
+
/* @__PURE__ */ jsx23("meta", { name: "twitter:card", content: twitterCard }),
|
|
1255
|
+
alternates.map(({ locale, href }) => /* @__PURE__ */ jsx23("link", { rel: "alternate", hrefLang: locale, href }, locale)),
|
|
1256
|
+
xDefaultHref ? /* @__PURE__ */ jsx23("link", { rel: "alternate", hrefLang: "x-default", href: xDefaultHref }) : null
|
|
1044
1257
|
] });
|
|
1045
1258
|
}
|
|
1046
1259
|
export {
|
|
@@ -1049,6 +1262,7 @@ export {
|
|
|
1049
1262
|
Certifications,
|
|
1050
1263
|
ContactInfo,
|
|
1051
1264
|
Courses,
|
|
1265
|
+
CvView,
|
|
1052
1266
|
EducationTimeline,
|
|
1053
1267
|
Footer,
|
|
1054
1268
|
HonorsList,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/TakuhonProfile.tsx","../src/components/ActivitySection.tsx","../src/lib/ui-labels.ts","../src/lib/date-formatter.ts","../src/components/CareerTimeline.tsx","../src/components/Certifications.tsx","../src/components/ContactInfo.tsx","../src/components/Courses.tsx","../src/components/EducationTimeline.tsx","../src/components/Footer.tsx","../src/components/HonorsList.tsx","../src/components/Languages.tsx","../src/components/LinksList.tsx","../src/components/Memberships.tsx","../src/components/Patents.tsx","../src/components/ProfileHeader.tsx","../src/components/ProjectsList.tsx","../src/components/Publications.tsx","../src/components/Recommendations.tsx","../src/components/SkillsList.tsx","../src/components/TestScores.tsx","../src/components/Volunteering.tsx","../src/components/LocaleSwitcher.tsx","../src/components/TakuhonHead.tsx"],"sourcesContent":["import type { ActivitySnapshot, LocalizedTakuhon } from '@takuhon/core';\n\nimport '../styles/tokens.css';\n\nimport { ActivitySection } from './ActivitySection.js';\nimport { CareerTimeline } from './CareerTimeline.js';\nimport { Certifications } from './Certifications.js';\nimport { ContactInfo } from './ContactInfo.js';\nimport { Courses } from './Courses.js';\nimport { EducationTimeline } from './EducationTimeline.js';\nimport { Footer } from './Footer.js';\nimport { HonorsList } from './HonorsList.js';\nimport { Languages } from './Languages.js';\nimport { LinksList } from './LinksList.js';\nimport { Memberships } from './Memberships.js';\nimport { Patents } from './Patents.js';\nimport { ProfileHeader } from './ProfileHeader.js';\nimport { ProjectsList } from './ProjectsList.js';\nimport { Publications } from './Publications.js';\nimport { Recommendations } from './Recommendations.js';\nimport { SkillsList } from './SkillsList.js';\nimport styles from './TakuhonProfile.module.css';\nimport { TestScores } from './TestScores.js';\nimport { Volunteering } from './Volunteering.js';\n\nexport interface TakuhonProfileProps {\n data: LocalizedTakuhon;\n /**\n * Synced developer-activity snapshot (a sibling document, fetched by the\n * host — e.g. `GET /api/activity`). Rendered only while\n * `settings.activity.enabled` is true, the same opt-in gate the API and the\n * static export apply, so disabling the feature drops the section even if a\n * stale snapshot is still supplied.\n */\n activitySnapshot?: ActivitySnapshot | null;\n}\n\nexport function TakuhonProfile({ data, activitySnapshot }: TakuhonProfileProps): React.JSX.Element {\n const showFooter = data.settings.showPoweredBy !== false;\n const locale = data.resolvedLocale;\n const activity = data.settings.activity?.enabled === true ? activitySnapshot : undefined;\n\n return (\n <article className={styles.root}>\n <ProfileHeader profile={data.profile} />\n <LinksList links={data.links} locale={locale} />\n <EducationTimeline education={data.education} locale={locale} />\n <Courses courses={data.courses} locale={locale} />\n <CareerTimeline careers={data.careers} locale={locale} />\n <Memberships memberships={data.memberships} locale={locale} />\n <Certifications certifications={data.certifications} locale={locale} />\n <Patents patents={data.patents} locale={locale} />\n <ProjectsList projects={data.projects} locale={locale} />\n <Publications publications={data.publications} locale={locale} />\n <HonorsList honors={data.honors} locale={locale} />\n <Recommendations recommendations={data.recommendations} locale={locale} />\n <Volunteering volunteering={data.volunteering} locale={locale} />\n <SkillsList skills={data.skills} locale={locale} />\n <ActivitySection snapshot={activity} locale={locale} />\n <Languages languages={data.languages} locale={locale} />\n <TestScores testScores={data.testScores} locale={locale} />\n <ContactInfo contact={data.contact} locale={locale} />\n {showFooter ? <Footer /> : null}\n </article>\n );\n}\n","import { renderActivitySvg } from '@takuhon/core';\nimport type { ActivitySnapshot, LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ActivitySection.module.css';\n\nexport interface ActivitySectionProps {\n /**\n * The synced developer-activity snapshot (a sibling document, not part of\n * `LocalizedTakuhon`). Hosts fetch it themselves — `GET /api/activity` on a\n * deployment, or the `activity.json` beside the profile locally.\n */\n snapshot?: ActivitySnapshot | null;\n locale?: LocaleTag;\n}\n\n/**\n * Developer-activity section: the same self-owned inline-SVG card the static\n * export renders, generated by `@takuhon/core`'s `renderActivitySvg` so the\n * two surfaces cannot drift. Renders nothing without a snapshot (or with one\n * that carries no metric data) — the section degrades away gracefully.\n */\nexport function ActivitySection({\n snapshot,\n locale = 'en',\n}: ActivitySectionProps): React.JSX.Element | null {\n if (!snapshot) return null;\n const svg = renderActivitySvg(snapshot);\n if (svg === '') return null;\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-activity-heading\">\n <h2 id=\"takuhon-activity-heading\" className={styles.heading}>\n {getUILabel('section.activity', locale)}\n </h2>\n {/* The markup is produced entirely by core's renderActivitySvg, which\n XML-escapes every snapshot-derived value (language names are external\n API data); no raw input ever reaches this sink. */}\n <div className={styles.card} dangerouslySetInnerHTML={{ __html: svg }} />\n </section>\n );\n}\n","import type { LanguageProficiency, LocaleTag, PatentStatus } from '@takuhon/core';\n\n/**\n * Keys for UI-generated fixed labels — text the UI emits itself, as opposed to\n * profile data resolved by `@takuhon/core`. These are localized via\n * {@link getUILabel}, keyed by a `LocalizedTakuhon.resolvedLocale`. See spec\n * §8.5 (Phase 2+ i18n).\n *\n * The proficiency / patent-status members are derived from the corresponding\n * core enums so the dictionaries below stay in lockstep with the schema: adding\n * a value to either enum turns the missing dictionary entry into a type error.\n */\n/** Section heading identifiers — the `<h2>` of each profile section. */\ntype SectionKey =\n | 'activity'\n | 'career'\n | 'education'\n | 'certifications'\n | 'patents'\n | 'projects'\n | 'publications'\n | 'honors'\n | 'recommendations'\n | 'volunteering'\n | 'memberships'\n | 'courses'\n | 'languages'\n | 'testScores'\n | 'skills'\n | 'contact';\n\nexport type UILabelKey =\n | 'timeline.present'\n | 'certification.noExpiration'\n | 'patent.filed'\n | 'patent.granted'\n | 'patent.coInventorsPrefix'\n | 'publication.coAuthorsPrefix'\n | `proficiency.${LanguageProficiency}`\n | `patentStatus.${PatentStatus}`\n | `section.${SectionKey}`\n | 'a11y.statusPrefix'\n | 'a11y.causePrefix'\n | 'a11y.profileLinks'\n | 'a11y.tags'\n | 'a11y.skillsSuffix'\n | 'a11y.selectLanguage'\n | 'contact.formLink'\n | 'skills.uncategorized';\n\ntype LabelDictionary = Record<UILabelKey, string>;\n\n/**\n * English dictionary. Also the fallback for any locale without its own\n * dictionary, so it MUST remain exhaustive — the `LabelDictionary` type\n * enforces that every `UILabelKey` is present.\n *\n * The co-inventor / co-author prefixes end in a trailing space (`with `):\n * callers concatenate the prefix directly with the names list, so the\n * separator between label and names is locale-specific and lives here, not at\n * the call site.\n */\nconst EN: LabelDictionary = {\n 'timeline.present': 'Present',\n 'certification.noExpiration': 'No expiration',\n 'patent.filed': 'Filed',\n 'patent.granted': 'Granted',\n 'patent.coInventorsPrefix': 'with ',\n 'publication.coAuthorsPrefix': 'with ',\n 'proficiency.native': 'Native',\n 'proficiency.fluent': 'Fluent',\n 'proficiency.professional': 'Professional working',\n 'proficiency.intermediate': 'Intermediate',\n 'proficiency.basic': 'Basic',\n 'patentStatus.pending': 'Pending',\n 'patentStatus.issued': 'Issued',\n 'patentStatus.expired': 'Expired',\n 'patentStatus.abandoned': 'Abandoned',\n 'section.activity': 'Activity',\n 'section.career': 'Career',\n 'section.education': 'Education',\n 'section.certifications': 'Certifications',\n 'section.patents': 'Patents',\n 'section.projects': 'Projects',\n 'section.publications': 'Publications',\n 'section.honors': 'Honors & Awards',\n 'section.recommendations': 'Recommendations',\n 'section.volunteering': 'Volunteering',\n 'section.memberships': 'Memberships',\n 'section.courses': 'Courses',\n 'section.languages': 'Languages',\n 'section.testScores': 'Test Scores',\n 'section.skills': 'Skills',\n 'section.contact': 'Contact',\n // a11y / chrome affixes. Status/Cause prefixes carry their trailing\n // separator (a space in English) so callers concatenate prefix + value.\n 'a11y.statusPrefix': 'Status: ',\n 'a11y.causePrefix': 'Cause: ',\n 'a11y.profileLinks': 'Profile links',\n 'a11y.tags': 'Tags',\n 'a11y.skillsSuffix': 'skills',\n 'a11y.selectLanguage': 'Select language',\n 'contact.formLink': 'Contact form',\n 'skills.uncategorized': 'Other',\n};\n\n/**\n * Japanese dictionary. The co-inventor / co-author prefixes end in a full-width\n * colon and no space (`共著者:`) — the conventional Japanese form — since\n * callers concatenate the prefix directly with the names list (`共著者:A, B`)\n * rather than using the English preposition (`with A, B`).\n */\nconst JA: LabelDictionary = {\n 'timeline.present': '現在',\n 'certification.noExpiration': '無期限',\n 'patent.filed': '出願',\n 'patent.granted': '登録',\n 'patent.coInventorsPrefix': '共同発明者:',\n 'publication.coAuthorsPrefix': '共著者:',\n 'proficiency.native': 'ネイティブ',\n 'proficiency.fluent': '流暢',\n 'proficiency.professional': '実務レベル',\n 'proficiency.intermediate': '中級',\n 'proficiency.basic': '初級',\n 'patentStatus.pending': '出願中',\n 'patentStatus.issued': '登録済',\n 'patentStatus.expired': '失効',\n 'patentStatus.abandoned': '放棄',\n 'section.activity': 'アクティビティ',\n 'section.career': '職歴',\n 'section.education': '学歴',\n 'section.certifications': '資格・認定',\n 'section.patents': '特許',\n 'section.projects': 'プロジェクト',\n 'section.publications': '論文・出版',\n 'section.honors': '受賞・栄誉',\n 'section.recommendations': '推薦',\n 'section.volunteering': 'ボランティア',\n 'section.memberships': '所属',\n 'section.courses': '講座',\n 'section.languages': '言語',\n 'section.testScores': 'テストスコア',\n 'section.skills': 'スキル',\n 'section.contact': '連絡先',\n // Status/Cause prefixes use a full-width colon (no trailing space), the\n // conventional Japanese form, mirroring the co-author prefix convention.\n 'a11y.statusPrefix': 'ステータス:',\n 'a11y.causePrefix': '分野:',\n 'a11y.profileLinks': 'プロフィールリンク',\n 'a11y.tags': 'タグ',\n 'a11y.skillsSuffix': 'スキル',\n 'a11y.selectLanguage': '言語を選択',\n 'contact.formLink': 'お問い合わせフォーム',\n 'skills.uncategorized': 'その他',\n};\n\nconst DICTIONARIES: Record<LocaleTag, LabelDictionary> = {\n en: EN,\n ja: JA,\n};\n\n/**\n * Resolve a UI label for the given locale. Tries the exact tag first, then the\n * base language subtag (so a resolved `ja-JP` still finds the `ja` dictionary,\n * mirroring the regional-subtag expansion in core's `resolveLocale`), and\n * finally falls back to English. Callers pass `LocalizedTakuhon.resolvedLocale`.\n */\nexport function getUILabel(key: UILabelKey, locale: LocaleTag): string {\n const base = locale.split('-')[0] ?? locale;\n return DICTIONARIES[locale]?.[key] ?? DICTIONARIES[base]?.[key] ?? EN[key];\n}\n","import type { LocaleTag } from '@takuhon/core';\n\nconst YEAR_MONTH = /^(\\d{4})-(0[1-9]|1[0-2])$/;\n\n/**\n * Format a `YYYY-MM` (`YearMonth`) value for display in the given locale — e.g.\n * `2024-05` renders as `May 2024` (en) or `2024年5月` (ja). This is the\n * human-facing text only; the machine-readable value belongs in the enclosing\n * `<time dateTime>` attribute, which keeps the raw ISO string.\n *\n * The date is constructed via `setUTCFullYear` — not `Date.UTC`, which coerces\n * years 0-99 into 1900-1999 — and formatted in UTC, so a `YearMonth` keeps its\n * century and never slips to the previous month (`new Date('2024-05')` parses\n * as midnight UTC and would render as the prior month west of UTC).\n *\n * `Intl` performs its own locale negotiation, so a regional tag such as `ja-JP`\n * resolves to Japanese without extra handling; an invalid BCP-47 tag falls back\n * to English instead of throwing. A value that is not a well-formed `YearMonth`\n * is returned unchanged rather than risking an `Invalid Date`.\n */\nexport function formatYearMonth(value: string, locale: LocaleTag): string {\n const match = YEAR_MONTH.exec(value);\n if (!match) return value;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, 1);\n const options: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n timeZone: 'UTC',\n };\n try {\n return new Intl.DateTimeFormat(locale || 'en', options).format(date);\n } catch {\n // An invalid BCP-47 tag throws a RangeError; fall back to English.\n return new Intl.DateTimeFormat('en', options).format(date);\n }\n}\n","import type { LocalizedCareer, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './CareerTimeline.module.css';\n\nexport interface CareerTimelineProps {\n careers: LocalizedCareer[];\n locale?: LocaleTag;\n}\n\nfunction sortCareers(careers: LocalizedCareer[]): LocalizedCareer[] {\n return [...careers].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(career: LocalizedCareer): boolean {\n return career.isCurrent === true || career.endDate === null || career.endDate === undefined;\n}\n\nexport function CareerTimeline({\n careers,\n locale = 'en',\n}: CareerTimelineProps): React.JSX.Element | null {\n if (careers.length === 0) return null;\n const ordered = sortCareers(careers);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-career-heading\">\n <h2 id=\"takuhon-career-heading\" className={styles.heading}>\n {getUILabel('section.career', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((career) => (\n <li key={career.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.role}>\n {career.url ? (\n <a\n className={styles.organizationLink}\n href={career.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {career.role} · {career.organization}\n </a>\n ) : (\n <>\n {career.role} · {career.organization}\n </>\n )}\n </p>\n <p className={styles.range}>\n <time dateTime={career.startDate}>{formatYearMonth(career.startDate, locale)}</time>\n {' – '}\n {isOngoing(career) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={career.endDate!}>{formatYearMonth(career.endDate!, locale)}</time>\n )}\n </p>\n {career.location?.display ? (\n <p className={styles.location}>{career.location.display}</p>\n ) : null}\n {career.description ? (\n <p className={styles.description}>{career.description}</p>\n ) : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { LocalizedCertification, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Certifications.module.css';\n\nexport interface CertificationsProps {\n certifications: LocalizedCertification[];\n locale?: LocaleTag;\n}\n\nfunction sortCerts(certs: LocalizedCertification[]): LocalizedCertification[] {\n return [...certs].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.issueDate.localeCompare(a.issueDate);\n });\n}\n\nexport function Certifications({\n certifications,\n locale = 'en',\n}: CertificationsProps): React.JSX.Element | null {\n if (certifications.length === 0) return null;\n const ordered = sortCerts(certifications);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-certifications-heading\">\n <h2 id=\"takuhon-certifications-heading\" className={styles.heading}>\n {getUILabel('section.certifications', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((cert) => (\n <li key={cert.id} className={styles.item}>\n <p className={styles.title}>\n {cert.url ? (\n <a\n className={styles.link}\n href={cert.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {cert.title}\n </a>\n ) : (\n cert.title\n )}\n </p>\n <p className={styles.issuer}>{cert.issuingOrganization}</p>\n <p className={styles.range}>\n <time dateTime={cert.issueDate}>{formatYearMonth(cert.issueDate, locale)}</time>\n {cert.expirationDate === null ? (\n <span className={styles.tag}>\n {' '}\n · {getUILabel('certification.noExpiration', locale)}\n </span>\n ) : cert.expirationDate !== undefined ? (\n <>\n {' – '}\n <time dateTime={cert.expirationDate}>\n {formatYearMonth(cert.expirationDate, locale)}\n </time>\n </>\n ) : null}\n </p>\n {/* credentialId is intentionally not rendered by default — the API\n privacy filter strips it for public responses unless\n meta.privacy.hideCredentialIds is explicitly false. */}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { Contact, LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ContactInfo.module.css';\n\nexport interface ContactInfoProps {\n contact: Contact;\n locale?: LocaleTag;\n}\n\nexport function ContactInfo({\n contact,\n locale = 'en',\n}: ContactInfoProps): React.JSX.Element | null {\n const showEmail = contact.showEmail === true && contact.email !== undefined;\n if (!showEmail && contact.formUrl === undefined) return null;\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-contact-heading\">\n <h2 id=\"takuhon-contact-heading\" className={styles.heading}>\n {getUILabel('section.contact', locale)}\n </h2>\n <ul className={styles.list}>\n {showEmail && contact.email !== undefined ? (\n <li className={styles.item}>\n <a className={styles.link} href={`mailto:${contact.email}`}>\n {contact.email}\n </a>\n </li>\n ) : null}\n {contact.formUrl !== undefined ? (\n <li className={styles.item}>\n <a\n className={styles.link}\n href={contact.formUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {getUILabel('contact.formLink', locale)}\n </a>\n </li>\n ) : null}\n </ul>\n </section>\n );\n}\n","import type { LocalizedCourse, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Courses.module.css';\n\nexport interface CoursesProps {\n courses: LocalizedCourse[];\n locale?: LocaleTag;\n}\n\nfunction sortCourses(entries: LocalizedCourse[]): LocalizedCourse[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return (b.completionDate ?? '').localeCompare(a.completionDate ?? '');\n });\n}\n\nexport function Courses({ courses, locale = 'en' }: CoursesProps): React.JSX.Element | null {\n if (courses.length === 0) return null;\n const ordered = sortCourses(courses);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-courses-heading\">\n <h2 id=\"takuhon-courses-heading\" className={styles.heading}>\n {getUILabel('section.courses', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.certificateUrl ? (\n <a\n className={styles.link}\n href={entry.certificateUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n {entry.provider ? <p className={styles.provider}>{entry.provider}</p> : null}\n {entry.courseNumber ? (\n <p className={styles.courseNumber}>{entry.courseNumber}</p>\n ) : null}\n {entry.completionDate ? (\n <p className={styles.date}>\n <time dateTime={entry.completionDate}>\n {formatYearMonth(entry.completionDate, locale)}\n </time>\n </p>\n ) : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedEducation, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './EducationTimeline.module.css';\n\nexport interface EducationTimelineProps {\n education: LocalizedEducation[];\n locale?: LocaleTag;\n}\n\nfunction sortEducation(entries: LocalizedEducation[]): LocalizedEducation[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedEducation): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nfunction composeStudyLine(entry: LocalizedEducation): string | undefined {\n if (entry.degree !== undefined && entry.fieldOfStudy !== undefined) {\n return `${entry.degree} · ${entry.fieldOfStudy}`;\n }\n return entry.degree ?? entry.fieldOfStudy;\n}\n\nexport function EducationTimeline({\n education,\n locale = 'en',\n}: EducationTimelineProps): React.JSX.Element | null {\n if (education.length === 0) return null;\n const ordered = sortEducation(education);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-education-heading\">\n <h2 id=\"takuhon-education-heading\" className={styles.heading}>\n {getUILabel('section.education', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => {\n const study = composeStudyLine(entry);\n return (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.institution}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.institution}\n </a>\n ) : (\n entry.institution\n )}\n </p>\n {study ? <p className={styles.study}>{study}</p> : null}\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.grade ? <p className={styles.grade}>{entry.grade}</p> : null}\n {entry.description ? (\n <p className={styles.description}>{entry.description}</p>\n ) : null}\n </div>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","import styles from './Footer.module.css';\n\nexport function Footer(): React.JSX.Element {\n return (\n <footer className={styles.footer}>\n <p className={styles.line}>\n Powered by{' '}\n <a\n className={styles.link}\n href=\"https://github.com/takuhon-dev/takuhon\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n takuhon\n </a>\n </p>\n </footer>\n );\n}\n","import type { LocalizedHonor, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './HonorsList.module.css';\n\nexport interface HonorsListProps {\n honors: LocalizedHonor[];\n locale?: LocaleTag;\n}\n\nfunction sortHonors(honors: LocalizedHonor[]): LocalizedHonor[] {\n return [...honors].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\nexport function HonorsList({ honors, locale = 'en' }: HonorsListProps): React.JSX.Element | null {\n if (honors.length === 0) return null;\n const ordered = sortHonors(honors);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-honors-heading\">\n <h2 id=\"takuhon-honors-heading\" className={styles.heading}>\n {getUILabel('section.honors', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((honor) => (\n <li key={honor.id} className={styles.item}>\n <p className={styles.title}>\n {honor.url ? (\n <a\n className={styles.link}\n href={honor.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {honor.title}\n </a>\n ) : (\n honor.title\n )}\n </p>\n <p className={styles.meta}>\n {honor.issuer}\n {' · '}\n <time dateTime={honor.date}>{formatYearMonth(honor.date, locale)}</time>\n </p>\n {honor.description ? <p className={styles.description}>{honor.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedLanguage } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Languages.module.css';\n\nexport interface LanguagesProps {\n languages: LocalizedLanguage[];\n locale?: LocaleTag;\n}\n\nfunction sortLanguages(languages: LocalizedLanguage[]): LocalizedLanguage[] {\n return [...languages].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nexport function Languages({ languages, locale = 'en' }: LanguagesProps): React.JSX.Element | null {\n if (languages.length === 0) return null;\n const ordered = sortLanguages(languages);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-languages-heading\">\n <h2 id=\"takuhon-languages-heading\" className={styles.heading}>\n {getUILabel('section.languages', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <span className={styles.name} lang={entry.language}>\n {entry.displayName ?? entry.language}\n </span>\n <span className={styles.proficiency}>\n {getUILabel(`proficiency.${entry.proficiency}`, locale)}\n </span>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedLink } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './LinksList.module.css';\n\nexport interface LinksListProps {\n links: LocalizedLink[];\n locale?: LocaleTag;\n}\n\nfunction sortLinks(links: LocalizedLink[]): LocalizedLink[] {\n return [...links].sort((a, b) => {\n const aFeatured = a.featured ? 1 : 0;\n const bFeatured = b.featured ? 1 : 0;\n if (aFeatured !== bFeatured) return bFeatured - aFeatured;\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nfunction formatLinkLabel(link: LocalizedLink): string {\n if (link.label) return link.label;\n if (link.type === 'custom') return link.id;\n return link.type;\n}\n\nexport function LinksList({ links, locale = 'en' }: LinksListProps): React.JSX.Element | null {\n if (links.length === 0) return null;\n\n const ordered = sortLinks(links);\n\n return (\n <nav aria-label={getUILabel('a11y.profileLinks', locale)} className={styles.nav}>\n <ul className={styles.list}>\n {ordered.map((link) => (\n <li key={link.id} className={styles.item}>\n <a\n className={styles.link}\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-featured={link.featured ? 'true' : undefined}\n >\n {link.iconUrl ? <img className={styles.icon} src={link.iconUrl} alt=\"\" /> : null}\n <span className={styles.label}>{formatLinkLabel(link)}</span>\n </a>\n </li>\n ))}\n </ul>\n </nav>\n );\n}\n","import type { LocalizedMembership, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Memberships.module.css';\n\nexport interface MembershipsProps {\n memberships: LocalizedMembership[];\n locale?: LocaleTag;\n}\n\nfunction sortMemberships(entries: LocalizedMembership[]): LocalizedMembership[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedMembership): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nexport function Memberships({\n memberships,\n locale = 'en',\n}: MembershipsProps): React.JSX.Element | null {\n if (memberships.length === 0) return null;\n const ordered = sortMemberships(memberships);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-memberships-heading\">\n <h2 id=\"takuhon-memberships-heading\" className={styles.heading}>\n {getUILabel('section.memberships', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.organization}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.organization}\n </a>\n ) : (\n entry.organization\n )}\n </p>\n {entry.role ? <p className={styles.role}>{entry.role}</p> : null}\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedPatent } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Patents.module.css';\n\nexport interface PatentsProps {\n patents: LocalizedPatent[];\n locale?: LocaleTag;\n}\n\nfunction sortPatents(entries: LocalizedPatent[]): LocalizedPatent[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n const aDate = a.grantDate ?? a.filingDate ?? '';\n const bDate = b.grantDate ?? b.filingDate ?? '';\n return bDate.localeCompare(aDate);\n });\n}\n\nexport function Patents({ patents, locale = 'en' }: PatentsProps): React.JSX.Element | null {\n if (patents.length === 0) return null;\n const ordered = sortPatents(patents);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-patents-heading\">\n <h2 id=\"takuhon-patents-heading\" className={styles.heading}>\n {getUILabel('section.patents', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n <span className={styles.statusBadge} data-status={entry.status}>\n <span className={styles.srOnly}>{getUILabel('a11y.statusPrefix', locale)}</span>\n {getUILabel(`patentStatus.${entry.status}`, locale)}\n </span>\n </p>\n <p className={styles.patentNumber}>{entry.patentNumber}</p>\n {entry.office ? <p className={styles.office}>{entry.office}</p> : null}\n {entry.filingDate !== undefined || entry.grantDate !== undefined ? (\n <p className={styles.dates}>\n {entry.filingDate ? (\n <>\n {`${getUILabel('patent.filed', locale)} `}\n <time dateTime={entry.filingDate}>\n {formatYearMonth(entry.filingDate, locale)}\n </time>\n </>\n ) : null}\n {entry.filingDate && entry.grantDate ? ' · ' : null}\n {entry.grantDate ? (\n <>\n {`${getUILabel('patent.granted', locale)} `}\n <time dateTime={entry.grantDate}>\n {formatYearMonth(entry.grantDate, locale)}\n </time>\n </>\n ) : null}\n </p>\n ) : null}\n {entry.coInventors && entry.coInventors.length > 0 ? (\n <p className={styles.coInventors}>\n {`${getUILabel('patent.coInventorsPrefix', locale)}${entry.coInventors.join(', ')}`}\n </p>\n ) : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedProfile } from '@takuhon/core';\n\nimport styles from './ProfileHeader.module.css';\n\nexport interface ProfileHeaderProps {\n profile: LocalizedProfile;\n}\n\nexport function ProfileHeader({ profile }: ProfileHeaderProps): React.JSX.Element {\n const locationLabel = profile.location?.display ?? profile.location?.locality;\n\n return (\n <header className={styles.header}>\n {profile.avatar ? (\n <img\n className={styles.avatar}\n src={profile.avatar.url}\n alt={profile.avatar.alt ?? ''}\n width={128}\n height={128}\n loading=\"eager\"\n decoding=\"async\"\n />\n ) : null}\n <h1 className={styles.displayName}>{profile.displayName}</h1>\n {profile.tagline ? <p className={styles.tagline}>{profile.tagline}</p> : null}\n {locationLabel ? <p className={styles.location}>{locationLabel}</p> : null}\n {profile.bio ? <p className={styles.bio}>{profile.bio}</p> : null}\n </header>\n );\n}\n","import type { LocalizedProject, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ProjectsList.module.css';\n\nexport interface ProjectsListProps {\n projects: LocalizedProject[];\n locale?: LocaleTag;\n}\n\nfunction sortProjects(projects: LocalizedProject[]): LocalizedProject[] {\n return [...projects].sort((a, b) => {\n const aHighlighted = a.highlighted ? 1 : 0;\n const bHighlighted = b.highlighted ? 1 : 0;\n if (aHighlighted !== bHighlighted) return bHighlighted - aHighlighted;\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nexport function ProjectsList({\n projects,\n locale = 'en',\n}: ProjectsListProps): React.JSX.Element | null {\n if (projects.length === 0) return null;\n const ordered = sortProjects(projects);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-projects-heading\">\n <h2 id=\"takuhon-projects-heading\" className={styles.heading}>\n {getUILabel('section.projects', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((project) => (\n <li\n key={project.id}\n className={styles.item}\n data-highlighted={project.highlighted ? 'true' : undefined}\n >\n <p className={styles.title}>\n {project.url ? (\n <a\n className={styles.titleLink}\n href={project.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {project.title}\n </a>\n ) : (\n project.title\n )}\n </p>\n {project.startDate !== undefined ? (\n <p className={styles.range}>\n <time dateTime={project.startDate}>\n {formatYearMonth(project.startDate, locale)}\n </time>\n {' – '}\n {project.endDate ? (\n <time dateTime={project.endDate}>{formatYearMonth(project.endDate, locale)}</time>\n ) : (\n getUILabel('timeline.present', locale)\n )}\n </p>\n ) : null}\n {project.description ? (\n <p className={styles.description}>{project.description}</p>\n ) : null}\n {project.tags && project.tags.length > 0 ? (\n <ul className={styles.tags} aria-label={getUILabel('a11y.tags', locale)}>\n {project.tags.map((tag) => (\n <li key={tag} className={styles.tag}>\n {tag}\n </li>\n ))}\n </ul>\n ) : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedPublication, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Publications.module.css';\n\nexport interface PublicationsProps {\n publications: LocalizedPublication[];\n locale?: LocaleTag;\n}\n\nfunction sortPublications(entries: LocalizedPublication[]): LocalizedPublication[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\n// Strip an optional doi.org URL prefix so the rendered href is always\n// `https://doi.org/<bare-identifier>`. Defensive against fixtures that\n// inadvertently store a full URL instead of the bare DOI per spec §6.15.\nfunction normalizeDoi(doi: string): string {\n return doi.replace(/^https?:\\/\\/(?:dx\\.)?doi\\.org\\//i, '');\n}\n\nexport function Publications({\n publications,\n locale = 'en',\n}: PublicationsProps): React.JSX.Element | null {\n if (publications.length === 0) return null;\n const ordered = sortPublications(publications);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-publications-heading\">\n <h2 id=\"takuhon-publications-heading\" className={styles.heading}>\n {getUILabel('section.publications', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n {entry.publisher ? <p className={styles.publisher}>{entry.publisher}</p> : null}\n <p className={styles.date}>\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n {entry.coAuthors && entry.coAuthors.length > 0 ? (\n <p className={styles.coAuthors}>\n {`${getUILabel('publication.coAuthorsPrefix', locale)}${entry.coAuthors.join(', ')}`}\n </p>\n ) : null}\n {entry.doi\n ? (() => {\n const bare = normalizeDoi(entry.doi);\n return (\n <p className={styles.doi}>\n <a\n className={styles.link}\n href={`https://doi.org/${bare}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {`doi:${bare}`}\n </a>\n </p>\n );\n })()\n : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedRecommendation, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Recommendations.module.css';\n\nexport interface RecommendationsProps {\n recommendations: LocalizedRecommendation[];\n locale?: LocaleTag;\n}\n\nfunction sortRecommendations(entries: LocalizedRecommendation[]): LocalizedRecommendation[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return (b.date ?? '').localeCompare(a.date ?? '');\n });\n}\n\nexport function Recommendations({\n recommendations,\n locale = 'en',\n}: RecommendationsProps): React.JSX.Element | null {\n if (recommendations.length === 0) return null;\n const ordered = sortRecommendations(recommendations);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-recommendations-heading\">\n <h2 id=\"takuhon-recommendations-heading\" className={styles.heading}>\n {getUILabel('section.recommendations', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <blockquote className={styles.body}>\n <p className={styles.quote}>{entry.body}</p>\n </blockquote>\n <p className={styles.attribution}>\n <span className={styles.author}>\n {entry.author.url ? (\n <a\n className={styles.link}\n href={entry.author.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.author.name}\n </a>\n ) : (\n entry.author.name\n )}\n </span>\n {entry.author.headline ? (\n <span className={styles.headline}>{entry.author.headline}</span>\n ) : null}\n </p>\n {entry.relationship ? <p className={styles.meta}>{entry.relationship}</p> : null}\n {entry.date ? (\n <p className={styles.meta}>\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n ) : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, Skill } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './SkillsList.module.css';\n\nexport interface SkillsListProps {\n skills: Skill[];\n locale?: LocaleTag;\n}\n\ninterface SkillGroup {\n category: string;\n skills: Skill[];\n}\n\n/** Internal grouping key for skills with no `category`; localized for display. */\nconst UNCATEGORIZED = 'other';\n\nfunction groupSkills(skills: Skill[]): SkillGroup[] {\n const sorted = [...skills].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n const groups = new Map<string, Skill[]>();\n for (const skill of sorted) {\n const key = skill.category ?? UNCATEGORIZED;\n const bucket = groups.get(key);\n if (bucket) {\n bucket.push(skill);\n } else {\n groups.set(key, [skill]);\n }\n }\n return [...groups.entries()].map(([category, items]) => ({ category, skills: items }));\n}\n\nexport function SkillsList({ skills, locale = 'en' }: SkillsListProps): React.JSX.Element | null {\n if (skills.length === 0) return null;\n const groups = groupSkills(skills);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-skills-heading\">\n <h2 id=\"takuhon-skills-heading\" className={styles.heading}>\n {getUILabel('section.skills', locale)}\n </h2>\n <div className={styles.groups}>\n {groups.map((group) => {\n // User-provided category names are profile data and stay as-is; only\n // the internal uncategorized fallback is a UI string to localize.\n const categoryLabel =\n group.category === UNCATEGORIZED\n ? getUILabel('skills.uncategorized', locale)\n : group.category;\n return (\n <div key={group.category} className={styles.group}>\n <h3 className={styles.category}>{categoryLabel}</h3>\n <ul\n className={styles.list}\n aria-label={`${categoryLabel} ${getUILabel('a11y.skillsSuffix', locale)}`}\n >\n {group.skills.map((skill) => (\n <li key={skill.id} className={styles.item}>\n {skill.label}\n </li>\n ))}\n </ul>\n </div>\n );\n })}\n </div>\n </section>\n );\n}\n","import type { LocalizedTestScore, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './TestScores.module.css';\n\nexport interface TestScoresProps {\n testScores: LocalizedTestScore[];\n locale?: LocaleTag;\n}\n\nfunction sortTestScores(entries: LocalizedTestScore[]): LocalizedTestScore[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\nexport function TestScores({\n testScores,\n locale = 'en',\n}: TestScoresProps): React.JSX.Element | null {\n if (testScores.length === 0) return null;\n const ordered = sortTestScores(testScores);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-test-scores-heading\">\n <h2 id=\"takuhon-test-scores-heading\" className={styles.heading}>\n {getUILabel('section.testScores', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n <p className={styles.meta}>\n <span className={styles.score}>{entry.score}</span>\n {' · '}\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedVolunteering, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Volunteering.module.css';\n\nexport interface VolunteeringProps {\n volunteering: LocalizedVolunteering[];\n locale?: LocaleTag;\n}\n\nfunction sortVolunteering(entries: LocalizedVolunteering[]): LocalizedVolunteering[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedVolunteering): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nexport function Volunteering({\n volunteering,\n locale = 'en',\n}: VolunteeringProps): React.JSX.Element | null {\n if (volunteering.length === 0) return null;\n const ordered = sortVolunteering(volunteering);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-volunteering-heading\">\n <h2 id=\"takuhon-volunteering-heading\" className={styles.heading}>\n {getUILabel('section.volunteering', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.organization}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.organization}\n </a>\n ) : (\n entry.organization\n )}\n </p>\n <p className={styles.role}>\n {entry.role}\n {entry.cause ? (\n <span className={styles.cause}>\n <span className={styles.srOnly}>{getUILabel('a11y.causePrefix', locale)}</span>\n {entry.cause}\n </span>\n ) : null}\n </p>\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './LocaleSwitcher.module.css';\n\nexport interface LocaleSwitcherProps {\n availableLocales: LocaleTag[];\n currentLocale: LocaleTag;\n onSelect: (locale: LocaleTag) => void;\n ariaLabel?: string;\n formatLocale?: (locale: LocaleTag) => string;\n}\n\nexport function LocaleSwitcher({\n availableLocales,\n currentLocale,\n onSelect,\n ariaLabel,\n formatLocale,\n}: LocaleSwitcherProps): React.JSX.Element {\n const label = ariaLabel ?? getUILabel('a11y.selectLanguage', currentLocale);\n const format = formatLocale ?? ((locale: LocaleTag) => locale);\n return (\n <div className={styles.wrapper}>\n <select\n className={styles.select}\n aria-label={label}\n value={currentLocale}\n onChange={(event) => {\n onSelect(event.target.value);\n }}\n >\n {availableLocales.map((locale) => (\n <option key={locale} value={locale}>\n {format(locale)}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import { generateJsonLd, type LocalizedTakuhon } from '@takuhon/core';\nimport { useEffect } from 'react';\n\nexport interface TakuhonHeadProps {\n data: LocalizedTakuhon;\n siteUrl?: string;\n pageUrl?: string;\n}\n\nfunction primarySubtag(tag: string): string {\n const dash = tag.indexOf('-');\n return (dash === -1 ? tag : tag.slice(0, dash)).toLowerCase();\n}\n\n/**\n * Whether a leading path segment should be treated as a locale prefix.\n * Mirrors the server resolver's `matchAvailable` so the two surfaces agree:\n * an exact (case-insensitive) match, or a primary-subtag match so a\n * regional segment like `en-US` is recognized against an available `en`.\n */\nfunction isLocaleSegment(segment: string, availableLocales: readonly string[]): boolean {\n const lower = segment.toLowerCase();\n const primary = primarySubtag(segment);\n return availableLocales.some(\n (loc) => loc.toLowerCase() === lower || primarySubtag(loc) === primary,\n );\n}\n\n/**\n * Remove a leading `/{locale}` path segment (when it is recognizable as a\n * locale per {@link isLocaleSegment}) and any legacy `?lang=` query,\n * yielding a locale-neutral base URL. This prevents stacking (`/ja/en/...`,\n * `/en/en-US/...`) when the current page is already locale-prefixed: the\n * existing segment is stripped before {@link withLocalePrefix} re-adds the\n * target locale.\n */\nfunction localeNeutralUrl(pageUrl: string, availableLocales: readonly string[]): string {\n try {\n const url = new URL(pageUrl);\n url.searchParams.delete('lang');\n const segments = url.pathname.split('/');\n const first = segments[1];\n if (first !== undefined && first !== '' && isLocaleSegment(first, availableLocales)) {\n segments.splice(1, 1);\n url.pathname = segments.join('/') || '/';\n }\n return url.toString();\n } catch {\n return pageUrl;\n }\n}\n\n/**\n * Prepend a `/{locale}` path segment to a locale-neutral URL, producing\n * the canonical path form (`https://site/profile` → `https://site/ja/profile`,\n * `https://site/` → `https://site/ja/`). The path form is the advertised\n * URL; `?lang=` remains a resolution input but is never emitted here.\n *\n * This is deployment-agnostic: it inserts a locale segment into whatever\n * page URL `TakuhonHead` is given, regardless of how that page is routed.\n * The built-in `@takuhon/api` public app resolves the path prefix for its\n * own surfaces (`/`, `/api/profile`, `/api/jsonld`); the canonical\n * deployment serves the rendered profile at the site root, so its `/ja/`\n * form resolves out of the box. A deployment that serves the HTML profile\n * at another path is responsible for routing that locale-prefixed page.\n */\nfunction withLocalePrefix(neutralUrl: string, locale: string): string {\n try {\n const url = new URL(neutralUrl);\n url.pathname = url.pathname === '/' ? `/${locale}/` : `/${locale}${url.pathname}`;\n return url.toString();\n } catch {\n return neutralUrl;\n }\n}\n\nfunction absolutizeUrl(url: string | undefined, base: string | undefined): string | undefined {\n if (!url) return undefined;\n if (!base) return url;\n try {\n return new URL(url, base).toString();\n } catch {\n return url;\n }\n}\n\nfunction detectSiteUrl(explicit: string | undefined): string | undefined {\n if (explicit) return explicit;\n if (typeof window !== 'undefined') return window.location.origin;\n return undefined;\n}\n\nfunction detectPageUrl(\n explicit: string | undefined,\n siteUrl: string | undefined,\n): string | undefined {\n if (explicit) return explicit;\n if (typeof window !== 'undefined') {\n return window.location.origin + window.location.pathname;\n }\n return siteUrl;\n}\n\nexport function TakuhonHead({ data, siteUrl, pageUrl }: TakuhonHeadProps): React.JSX.Element {\n const resolvedSiteUrl = detectSiteUrl(siteUrl);\n const resolvedPageUrl = detectPageUrl(pageUrl, resolvedSiteUrl);\n\n const { profile, settings, resolvedLocale } = data;\n const description = profile.bio ?? profile.tagline;\n const ogDescription = profile.tagline ?? profile.bio;\n const ogImage = absolutizeUrl(profile.avatar?.url, resolvedSiteUrl);\n const twitterCard = profile.avatar ? 'summary_large_image' : 'summary';\n\n // Locale-neutral base, so canonical/alternates emit one clean path form\n // per locale (`/ja/...`) and never stack when the current page is\n // already locale-prefixed.\n const neutralPageUrl = resolvedPageUrl\n ? localeNeutralUrl(resolvedPageUrl, settings.availableLocales)\n : undefined;\n\n const canonical = neutralPageUrl ? withLocalePrefix(neutralPageUrl, resolvedLocale) : undefined;\n const alternates = neutralPageUrl\n ? settings.availableLocales.map((loc) => ({\n locale: loc,\n href: withLocalePrefix(neutralPageUrl, loc),\n }))\n : [];\n const xDefaultHref = neutralPageUrl\n ? withLocalePrefix(neutralPageUrl, settings.defaultLocale)\n : undefined;\n\n const ogAlternates = settings.availableLocales.filter((loc) => loc !== resolvedLocale);\n\n const emitJsonLd = settings.enableJsonLd !== false;\n const jsonLdPayload = emitJsonLd ? JSON.stringify(generateJsonLd(data)) : null;\n\n useEffect(() => {\n if (!jsonLdPayload) return;\n const script = document.createElement('script');\n script.type = 'application/ld+json';\n script.textContent = jsonLdPayload;\n document.head.appendChild(script);\n return () => {\n script.remove();\n };\n }, [jsonLdPayload]);\n\n return (\n <>\n <title>{profile.displayName}</title>\n {description ? <meta name=\"description\" content={description} /> : null}\n {canonical ? <link rel=\"canonical\" href={canonical} /> : null}\n\n <meta property=\"og:title\" content={profile.displayName} />\n {ogDescription ? <meta property=\"og:description\" content={ogDescription} /> : null}\n {canonical ? <meta property=\"og:url\" content={canonical} /> : null}\n {ogImage ? <meta property=\"og:image\" content={ogImage} /> : null}\n <meta property=\"og:type\" content=\"profile\" />\n <meta property=\"og:locale\" content={resolvedLocale} />\n {ogAlternates.map((loc) => (\n <meta key={loc} property=\"og:locale:alternate\" content={loc} />\n ))}\n\n <meta name=\"twitter:card\" content={twitterCard} />\n\n {alternates.map(({ locale, href }) => (\n <link key={locale} rel=\"alternate\" hrefLang={locale} href={href} />\n ))}\n {xDefaultHref ? <link rel=\"alternate\" hrefLang=\"x-default\" href={xDefaultHref} /> : null}\n </>\n );\n}\n"],"mappings":"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","names":["styles","jsx","jsxs","styles","Fragment","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","styles","Fragment","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","jsx","jsxs","styles","styles","jsx","Fragment","jsx","jsxs"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/TakuhonProfile.tsx","../src/components/ActivitySection.tsx","../src/lib/ui-labels.ts","../src/lib/date-formatter.ts","../src/components/CareerTimeline.tsx","../src/components/Certifications.tsx","../src/components/ContactInfo.tsx","../src/components/Courses.tsx","../src/components/EducationTimeline.tsx","../src/components/Footer.tsx","../src/components/HonorsList.tsx","../src/components/Languages.tsx","../src/components/LinksList.tsx","../src/components/Memberships.tsx","../src/components/Patents.tsx","../src/components/ProfileHeader.tsx","../src/components/ProjectsList.tsx","../src/components/Publications.tsx","../src/components/Recommendations.tsx","../src/components/SkillsList.tsx","../src/components/TestScores.tsx","../src/components/Volunteering.tsx","../src/components/CvView.tsx","../src/components/LocaleSwitcher.tsx","../src/components/TakuhonHead.tsx"],"sourcesContent":["import type { ActivitySnapshot, LocalizedTakuhon } from '@takuhon/core';\n\nimport '../styles/tokens.css';\n\nimport { ActivitySection } from './ActivitySection.js';\nimport { CareerTimeline } from './CareerTimeline.js';\nimport { Certifications } from './Certifications.js';\nimport { ContactInfo } from './ContactInfo.js';\nimport { Courses } from './Courses.js';\nimport { EducationTimeline } from './EducationTimeline.js';\nimport { Footer } from './Footer.js';\nimport { HonorsList } from './HonorsList.js';\nimport { Languages } from './Languages.js';\nimport { LinksList } from './LinksList.js';\nimport { Memberships } from './Memberships.js';\nimport { Patents } from './Patents.js';\nimport { ProfileHeader } from './ProfileHeader.js';\nimport { ProjectsList } from './ProjectsList.js';\nimport { Publications } from './Publications.js';\nimport { Recommendations } from './Recommendations.js';\nimport { SkillsList } from './SkillsList.js';\nimport styles from './TakuhonProfile.module.css';\nimport { TestScores } from './TestScores.js';\nimport { Volunteering } from './Volunteering.js';\n\nexport interface TakuhonProfileProps {\n data: LocalizedTakuhon;\n /**\n * Synced developer-activity snapshot (a sibling document, fetched by the\n * host — e.g. `GET /api/activity`). Rendered only while\n * `settings.activity.enabled` is true, the same opt-in gate the API and the\n * static export apply, so disabling the feature drops the section even if a\n * stale snapshot is still supplied.\n */\n activitySnapshot?: ActivitySnapshot | null;\n}\n\nexport function TakuhonProfile({ data, activitySnapshot }: TakuhonProfileProps): React.JSX.Element {\n const showFooter = data.settings.showPoweredBy !== false;\n const locale = data.resolvedLocale;\n const activity = data.settings.activity?.enabled === true ? activitySnapshot : undefined;\n\n return (\n <article className={styles.root}>\n <ProfileHeader profile={data.profile} />\n <LinksList links={data.links} locale={locale} />\n <EducationTimeline education={data.education} locale={locale} />\n <Courses courses={data.courses} locale={locale} />\n <CareerTimeline careers={data.careers} locale={locale} />\n <Memberships memberships={data.memberships} locale={locale} />\n <Certifications certifications={data.certifications} locale={locale} />\n <Patents patents={data.patents} locale={locale} />\n <ProjectsList projects={data.projects} locale={locale} />\n <Publications publications={data.publications} locale={locale} />\n <HonorsList honors={data.honors} locale={locale} />\n <Recommendations recommendations={data.recommendations} locale={locale} />\n <Volunteering volunteering={data.volunteering} locale={locale} />\n <SkillsList skills={data.skills} locale={locale} />\n <ActivitySection snapshot={activity} locale={locale} />\n <Languages languages={data.languages} locale={locale} />\n <TestScores testScores={data.testScores} locale={locale} />\n <ContactInfo contact={data.contact} locale={locale} />\n {showFooter ? <Footer /> : null}\n </article>\n );\n}\n","import { renderActivitySvg } from '@takuhon/core';\nimport type { ActivitySnapshot, LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ActivitySection.module.css';\n\nexport interface ActivitySectionProps {\n /**\n * The synced developer-activity snapshot (a sibling document, not part of\n * `LocalizedTakuhon`). Hosts fetch it themselves — `GET /api/activity` on a\n * deployment, or the `activity.json` beside the profile locally.\n */\n snapshot?: ActivitySnapshot | null;\n locale?: LocaleTag;\n}\n\n/**\n * Developer-activity section: the same self-owned inline-SVG card the static\n * export renders, generated by `@takuhon/core`'s `renderActivitySvg` so the\n * two surfaces cannot drift. Renders nothing without a snapshot (or with one\n * that carries no metric data) — the section degrades away gracefully.\n */\nexport function ActivitySection({\n snapshot,\n locale = 'en',\n}: ActivitySectionProps): React.JSX.Element | null {\n if (!snapshot) return null;\n const svg = renderActivitySvg(snapshot);\n if (svg === '') return null;\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-activity-heading\">\n <h2 id=\"takuhon-activity-heading\" className={styles.heading}>\n {getUILabel('section.activity', locale)}\n </h2>\n {/* The markup is produced entirely by core's renderActivitySvg, which\n XML-escapes every snapshot-derived value (language names are external\n API data); no raw input ever reaches this sink. */}\n <div className={styles.card} dangerouslySetInnerHTML={{ __html: svg }} />\n </section>\n );\n}\n","import type { LanguageProficiency, LocaleTag, PatentStatus } from '@takuhon/core';\n\n/**\n * Keys for UI-generated fixed labels — text the UI emits itself, as opposed to\n * profile data resolved by `@takuhon/core`. These are localized via\n * {@link getUILabel}, keyed by a `LocalizedTakuhon.resolvedLocale`. See spec\n * §8.5 (Phase 2+ i18n).\n *\n * The proficiency / patent-status members are derived from the corresponding\n * core enums so the dictionaries below stay in lockstep with the schema: adding\n * a value to either enum turns the missing dictionary entry into a type error.\n */\n/** Section heading identifiers — the `<h2>` of each profile section. */\ntype SectionKey =\n | 'activity'\n | 'career'\n | 'education'\n | 'certifications'\n | 'patents'\n | 'projects'\n | 'publications'\n | 'honors'\n | 'recommendations'\n | 'volunteering'\n | 'memberships'\n | 'courses'\n | 'languages'\n | 'testScores'\n | 'skills'\n | 'contact';\n\nexport type UILabelKey =\n | 'timeline.present'\n | 'certification.noExpiration'\n | 'patent.filed'\n | 'patent.granted'\n | 'patent.coInventorsPrefix'\n | 'publication.coAuthorsPrefix'\n | `proficiency.${LanguageProficiency}`\n | `patentStatus.${PatentStatus}`\n | `section.${SectionKey}`\n | 'a11y.statusPrefix'\n | 'a11y.causePrefix'\n | 'a11y.profileLinks'\n | 'a11y.tags'\n | 'a11y.skillsSuffix'\n | 'a11y.selectLanguage'\n | 'contact.formLink'\n | 'skills.uncategorized';\n\ntype LabelDictionary = Record<UILabelKey, string>;\n\n/**\n * English dictionary. Also the fallback for any locale without its own\n * dictionary, so it MUST remain exhaustive — the `LabelDictionary` type\n * enforces that every `UILabelKey` is present.\n *\n * The co-inventor / co-author prefixes end in a trailing space (`with `):\n * callers concatenate the prefix directly with the names list, so the\n * separator between label and names is locale-specific and lives here, not at\n * the call site.\n */\nconst EN: LabelDictionary = {\n 'timeline.present': 'Present',\n 'certification.noExpiration': 'No expiration',\n 'patent.filed': 'Filed',\n 'patent.granted': 'Granted',\n 'patent.coInventorsPrefix': 'with ',\n 'publication.coAuthorsPrefix': 'with ',\n 'proficiency.native': 'Native',\n 'proficiency.fluent': 'Fluent',\n 'proficiency.professional': 'Professional working',\n 'proficiency.intermediate': 'Intermediate',\n 'proficiency.basic': 'Basic',\n 'patentStatus.pending': 'Pending',\n 'patentStatus.issued': 'Issued',\n 'patentStatus.expired': 'Expired',\n 'patentStatus.abandoned': 'Abandoned',\n 'section.activity': 'Activity',\n 'section.career': 'Career',\n 'section.education': 'Education',\n 'section.certifications': 'Certifications',\n 'section.patents': 'Patents',\n 'section.projects': 'Projects',\n 'section.publications': 'Publications',\n 'section.honors': 'Honors & Awards',\n 'section.recommendations': 'Recommendations',\n 'section.volunteering': 'Volunteering',\n 'section.memberships': 'Memberships',\n 'section.courses': 'Courses',\n 'section.languages': 'Languages',\n 'section.testScores': 'Test Scores',\n 'section.skills': 'Skills',\n 'section.contact': 'Contact',\n // a11y / chrome affixes. Status/Cause prefixes carry their trailing\n // separator (a space in English) so callers concatenate prefix + value.\n 'a11y.statusPrefix': 'Status: ',\n 'a11y.causePrefix': 'Cause: ',\n 'a11y.profileLinks': 'Profile links',\n 'a11y.tags': 'Tags',\n 'a11y.skillsSuffix': 'skills',\n 'a11y.selectLanguage': 'Select language',\n 'contact.formLink': 'Contact form',\n 'skills.uncategorized': 'Other',\n};\n\n/**\n * Japanese dictionary. The co-inventor / co-author prefixes end in a full-width\n * colon and no space (`共著者:`) — the conventional Japanese form — since\n * callers concatenate the prefix directly with the names list (`共著者:A, B`)\n * rather than using the English preposition (`with A, B`).\n */\nconst JA: LabelDictionary = {\n 'timeline.present': '現在',\n 'certification.noExpiration': '無期限',\n 'patent.filed': '出願',\n 'patent.granted': '登録',\n 'patent.coInventorsPrefix': '共同発明者:',\n 'publication.coAuthorsPrefix': '共著者:',\n 'proficiency.native': 'ネイティブ',\n 'proficiency.fluent': '流暢',\n 'proficiency.professional': '実務レベル',\n 'proficiency.intermediate': '中級',\n 'proficiency.basic': '初級',\n 'patentStatus.pending': '出願中',\n 'patentStatus.issued': '登録済',\n 'patentStatus.expired': '失効',\n 'patentStatus.abandoned': '放棄',\n 'section.activity': 'アクティビティ',\n 'section.career': '職歴',\n 'section.education': '学歴',\n 'section.certifications': '資格・認定',\n 'section.patents': '特許',\n 'section.projects': 'プロジェクト',\n 'section.publications': '論文・出版',\n 'section.honors': '受賞・栄誉',\n 'section.recommendations': '推薦',\n 'section.volunteering': 'ボランティア',\n 'section.memberships': '所属',\n 'section.courses': '講座',\n 'section.languages': '言語',\n 'section.testScores': 'テストスコア',\n 'section.skills': 'スキル',\n 'section.contact': '連絡先',\n // Status/Cause prefixes use a full-width colon (no trailing space), the\n // conventional Japanese form, mirroring the co-author prefix convention.\n 'a11y.statusPrefix': 'ステータス:',\n 'a11y.causePrefix': '分野:',\n 'a11y.profileLinks': 'プロフィールリンク',\n 'a11y.tags': 'タグ',\n 'a11y.skillsSuffix': 'スキル',\n 'a11y.selectLanguage': '言語を選択',\n 'contact.formLink': 'お問い合わせフォーム',\n 'skills.uncategorized': 'その他',\n};\n\nconst DICTIONARIES: Record<LocaleTag, LabelDictionary> = {\n en: EN,\n ja: JA,\n};\n\n/**\n * Resolve a UI label for the given locale. Tries the exact tag first, then the\n * base language subtag (so a resolved `ja-JP` still finds the `ja` dictionary,\n * mirroring the regional-subtag expansion in core's `resolveLocale`), and\n * finally falls back to English. Callers pass `LocalizedTakuhon.resolvedLocale`.\n */\nexport function getUILabel(key: UILabelKey, locale: LocaleTag): string {\n const base = locale.split('-')[0] ?? locale;\n return DICTIONARIES[locale]?.[key] ?? DICTIONARIES[base]?.[key] ?? EN[key];\n}\n","import type { LocaleTag } from '@takuhon/core';\n\nconst YEAR_MONTH = /^(\\d{4})-(0[1-9]|1[0-2])$/;\n\n/**\n * Format a `YYYY-MM` (`YearMonth`) value for display in the given locale — e.g.\n * `2024-05` renders as `May 2024` (en) or `2024年5月` (ja). This is the\n * human-facing text only; the machine-readable value belongs in the enclosing\n * `<time dateTime>` attribute, which keeps the raw ISO string.\n *\n * The date is constructed via `setUTCFullYear` — not `Date.UTC`, which coerces\n * years 0-99 into 1900-1999 — and formatted in UTC, so a `YearMonth` keeps its\n * century and never slips to the previous month (`new Date('2024-05')` parses\n * as midnight UTC and would render as the prior month west of UTC).\n *\n * `Intl` performs its own locale negotiation, so a regional tag such as `ja-JP`\n * resolves to Japanese without extra handling; an invalid BCP-47 tag falls back\n * to English instead of throwing. A value that is not a well-formed `YearMonth`\n * is returned unchanged rather than risking an `Invalid Date`.\n */\nexport function formatYearMonth(value: string, locale: LocaleTag): string {\n const match = YEAR_MONTH.exec(value);\n if (!match) return value;\n const year = Number(match[1]);\n const month = Number(match[2]);\n const date = new Date(0);\n date.setUTCFullYear(year, month - 1, 1);\n const options: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n timeZone: 'UTC',\n };\n try {\n return new Intl.DateTimeFormat(locale || 'en', options).format(date);\n } catch {\n // An invalid BCP-47 tag throws a RangeError; fall back to English.\n return new Intl.DateTimeFormat('en', options).format(date);\n }\n}\n","import type { LocalizedCareer, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './CareerTimeline.module.css';\n\nexport interface CareerTimelineProps {\n careers: LocalizedCareer[];\n locale?: LocaleTag;\n}\n\nfunction sortCareers(careers: LocalizedCareer[]): LocalizedCareer[] {\n return [...careers].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(career: LocalizedCareer): boolean {\n return career.isCurrent === true || career.endDate === null || career.endDate === undefined;\n}\n\nexport function CareerTimeline({\n careers,\n locale = 'en',\n}: CareerTimelineProps): React.JSX.Element | null {\n if (careers.length === 0) return null;\n const ordered = sortCareers(careers);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-career-heading\">\n <h2 id=\"takuhon-career-heading\" className={styles.heading}>\n {getUILabel('section.career', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((career) => (\n <li key={career.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.role}>\n {career.url ? (\n <a\n className={styles.organizationLink}\n href={career.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {career.role} · {career.organization}\n </a>\n ) : (\n <>\n {career.role} · {career.organization}\n </>\n )}\n </p>\n <p className={styles.range}>\n <time dateTime={career.startDate}>{formatYearMonth(career.startDate, locale)}</time>\n {' – '}\n {isOngoing(career) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={career.endDate!}>{formatYearMonth(career.endDate!, locale)}</time>\n )}\n </p>\n {career.location?.display ? (\n <p className={styles.location}>{career.location.display}</p>\n ) : null}\n {career.description ? (\n <p className={styles.description}>{career.description}</p>\n ) : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { LocalizedCertification, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Certifications.module.css';\n\nexport interface CertificationsProps {\n certifications: LocalizedCertification[];\n locale?: LocaleTag;\n}\n\nfunction sortCerts(certs: LocalizedCertification[]): LocalizedCertification[] {\n return [...certs].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.issueDate.localeCompare(a.issueDate);\n });\n}\n\nexport function Certifications({\n certifications,\n locale = 'en',\n}: CertificationsProps): React.JSX.Element | null {\n if (certifications.length === 0) return null;\n const ordered = sortCerts(certifications);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-certifications-heading\">\n <h2 id=\"takuhon-certifications-heading\" className={styles.heading}>\n {getUILabel('section.certifications', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((cert) => (\n <li key={cert.id} className={styles.item}>\n <p className={styles.title}>\n {cert.url ? (\n <a\n className={styles.link}\n href={cert.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {cert.title}\n </a>\n ) : (\n cert.title\n )}\n </p>\n <p className={styles.issuer}>{cert.issuingOrganization}</p>\n <p className={styles.range}>\n <time dateTime={cert.issueDate}>{formatYearMonth(cert.issueDate, locale)}</time>\n {cert.expirationDate === null ? (\n <span className={styles.tag}>\n {' '}\n · {getUILabel('certification.noExpiration', locale)}\n </span>\n ) : cert.expirationDate !== undefined ? (\n <>\n {' – '}\n <time dateTime={cert.expirationDate}>\n {formatYearMonth(cert.expirationDate, locale)}\n </time>\n </>\n ) : null}\n </p>\n {/* credentialId is intentionally not rendered by default — the API\n privacy filter strips it for public responses unless\n meta.privacy.hideCredentialIds is explicitly false. */}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { Contact, LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ContactInfo.module.css';\n\nexport interface ContactInfoProps {\n contact: Contact;\n locale?: LocaleTag;\n}\n\nexport function ContactInfo({\n contact,\n locale = 'en',\n}: ContactInfoProps): React.JSX.Element | null {\n const showEmail = contact.showEmail === true && contact.email !== undefined;\n if (!showEmail && contact.formUrl === undefined) return null;\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-contact-heading\">\n <h2 id=\"takuhon-contact-heading\" className={styles.heading}>\n {getUILabel('section.contact', locale)}\n </h2>\n <ul className={styles.list}>\n {showEmail && contact.email !== undefined ? (\n <li className={styles.item}>\n <a className={styles.link} href={`mailto:${contact.email}`}>\n {contact.email}\n </a>\n </li>\n ) : null}\n {contact.formUrl !== undefined ? (\n <li className={styles.item}>\n <a\n className={styles.link}\n href={contact.formUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {getUILabel('contact.formLink', locale)}\n </a>\n </li>\n ) : null}\n </ul>\n </section>\n );\n}\n","import type { LocalizedCourse, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Courses.module.css';\n\nexport interface CoursesProps {\n courses: LocalizedCourse[];\n locale?: LocaleTag;\n}\n\nfunction sortCourses(entries: LocalizedCourse[]): LocalizedCourse[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return (b.completionDate ?? '').localeCompare(a.completionDate ?? '');\n });\n}\n\nexport function Courses({ courses, locale = 'en' }: CoursesProps): React.JSX.Element | null {\n if (courses.length === 0) return null;\n const ordered = sortCourses(courses);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-courses-heading\">\n <h2 id=\"takuhon-courses-heading\" className={styles.heading}>\n {getUILabel('section.courses', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.certificateUrl ? (\n <a\n className={styles.link}\n href={entry.certificateUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n {entry.provider ? <p className={styles.provider}>{entry.provider}</p> : null}\n {entry.courseNumber ? (\n <p className={styles.courseNumber}>{entry.courseNumber}</p>\n ) : null}\n {entry.completionDate ? (\n <p className={styles.date}>\n <time dateTime={entry.completionDate}>\n {formatYearMonth(entry.completionDate, locale)}\n </time>\n </p>\n ) : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedEducation, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './EducationTimeline.module.css';\n\nexport interface EducationTimelineProps {\n education: LocalizedEducation[];\n locale?: LocaleTag;\n}\n\nfunction sortEducation(entries: LocalizedEducation[]): LocalizedEducation[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedEducation): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nfunction composeStudyLine(entry: LocalizedEducation): string | undefined {\n if (entry.degree !== undefined && entry.fieldOfStudy !== undefined) {\n return `${entry.degree} · ${entry.fieldOfStudy}`;\n }\n return entry.degree ?? entry.fieldOfStudy;\n}\n\nexport function EducationTimeline({\n education,\n locale = 'en',\n}: EducationTimelineProps): React.JSX.Element | null {\n if (education.length === 0) return null;\n const ordered = sortEducation(education);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-education-heading\">\n <h2 id=\"takuhon-education-heading\" className={styles.heading}>\n {getUILabel('section.education', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => {\n const study = composeStudyLine(entry);\n return (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.institution}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.institution}\n </a>\n ) : (\n entry.institution\n )}\n </p>\n {study ? <p className={styles.study}>{study}</p> : null}\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.grade ? <p className={styles.grade}>{entry.grade}</p> : null}\n {entry.description ? (\n <p className={styles.description}>{entry.description}</p>\n ) : null}\n </div>\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","import styles from './Footer.module.css';\n\nexport function Footer(): React.JSX.Element {\n return (\n <footer className={styles.footer}>\n <p className={styles.line}>\n Powered by{' '}\n <a\n className={styles.link}\n href=\"https://github.com/takuhon-dev/takuhon\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n takuhon\n </a>\n </p>\n </footer>\n );\n}\n","import type { LocalizedHonor, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './HonorsList.module.css';\n\nexport interface HonorsListProps {\n honors: LocalizedHonor[];\n locale?: LocaleTag;\n}\n\nfunction sortHonors(honors: LocalizedHonor[]): LocalizedHonor[] {\n return [...honors].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\nexport function HonorsList({ honors, locale = 'en' }: HonorsListProps): React.JSX.Element | null {\n if (honors.length === 0) return null;\n const ordered = sortHonors(honors);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-honors-heading\">\n <h2 id=\"takuhon-honors-heading\" className={styles.heading}>\n {getUILabel('section.honors', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((honor) => (\n <li key={honor.id} className={styles.item}>\n <p className={styles.title}>\n {honor.url ? (\n <a\n className={styles.link}\n href={honor.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {honor.title}\n </a>\n ) : (\n honor.title\n )}\n </p>\n <p className={styles.meta}>\n {honor.issuer}\n {' · '}\n <time dateTime={honor.date}>{formatYearMonth(honor.date, locale)}</time>\n </p>\n {honor.description ? <p className={styles.description}>{honor.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedLanguage } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Languages.module.css';\n\nexport interface LanguagesProps {\n languages: LocalizedLanguage[];\n locale?: LocaleTag;\n}\n\nfunction sortLanguages(languages: LocalizedLanguage[]): LocalizedLanguage[] {\n return [...languages].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nexport function Languages({ languages, locale = 'en' }: LanguagesProps): React.JSX.Element | null {\n if (languages.length === 0) return null;\n const ordered = sortLanguages(languages);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-languages-heading\">\n <h2 id=\"takuhon-languages-heading\" className={styles.heading}>\n {getUILabel('section.languages', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <span className={styles.name} lang={entry.language}>\n {entry.displayName ?? entry.language}\n </span>\n <span className={styles.proficiency}>\n {getUILabel(`proficiency.${entry.proficiency}`, locale)}\n </span>\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedLink } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './LinksList.module.css';\n\nexport interface LinksListProps {\n links: LocalizedLink[];\n locale?: LocaleTag;\n}\n\nfunction sortLinks(links: LocalizedLink[]): LocalizedLink[] {\n return [...links].sort((a, b) => {\n const aFeatured = a.featured ? 1 : 0;\n const bFeatured = b.featured ? 1 : 0;\n if (aFeatured !== bFeatured) return bFeatured - aFeatured;\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nfunction formatLinkLabel(link: LocalizedLink): string {\n if (link.label) return link.label;\n if (link.type === 'custom') return link.id;\n return link.type;\n}\n\nexport function LinksList({ links, locale = 'en' }: LinksListProps): React.JSX.Element | null {\n if (links.length === 0) return null;\n\n const ordered = sortLinks(links);\n\n return (\n <nav aria-label={getUILabel('a11y.profileLinks', locale)} className={styles.nav}>\n <ul className={styles.list}>\n {ordered.map((link) => (\n <li key={link.id} className={styles.item}>\n <a\n className={styles.link}\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-featured={link.featured ? 'true' : undefined}\n >\n {link.iconUrl ? <img className={styles.icon} src={link.iconUrl} alt=\"\" /> : null}\n <span className={styles.label}>{formatLinkLabel(link)}</span>\n </a>\n </li>\n ))}\n </ul>\n </nav>\n );\n}\n","import type { LocalizedMembership, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Memberships.module.css';\n\nexport interface MembershipsProps {\n memberships: LocalizedMembership[];\n locale?: LocaleTag;\n}\n\nfunction sortMemberships(entries: LocalizedMembership[]): LocalizedMembership[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedMembership): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nexport function Memberships({\n memberships,\n locale = 'en',\n}: MembershipsProps): React.JSX.Element | null {\n if (memberships.length === 0) return null;\n const ordered = sortMemberships(memberships);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-memberships-heading\">\n <h2 id=\"takuhon-memberships-heading\" className={styles.heading}>\n {getUILabel('section.memberships', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.organization}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.organization}\n </a>\n ) : (\n entry.organization\n )}\n </p>\n {entry.role ? <p className={styles.role}>{entry.role}</p> : null}\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { LocaleTag, LocalizedPatent } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Patents.module.css';\n\nexport interface PatentsProps {\n patents: LocalizedPatent[];\n locale?: LocaleTag;\n}\n\nfunction sortPatents(entries: LocalizedPatent[]): LocalizedPatent[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n const aDate = a.grantDate ?? a.filingDate ?? '';\n const bDate = b.grantDate ?? b.filingDate ?? '';\n return bDate.localeCompare(aDate);\n });\n}\n\nexport function Patents({ patents, locale = 'en' }: PatentsProps): React.JSX.Element | null {\n if (patents.length === 0) return null;\n const ordered = sortPatents(patents);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-patents-heading\">\n <h2 id=\"takuhon-patents-heading\" className={styles.heading}>\n {getUILabel('section.patents', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n <span className={styles.statusBadge} data-status={entry.status}>\n <span className={styles.srOnly}>{getUILabel('a11y.statusPrefix', locale)}</span>\n {getUILabel(`patentStatus.${entry.status}`, locale)}\n </span>\n </p>\n <p className={styles.patentNumber}>{entry.patentNumber}</p>\n {entry.office ? <p className={styles.office}>{entry.office}</p> : null}\n {entry.filingDate !== undefined || entry.grantDate !== undefined ? (\n <p className={styles.dates}>\n {entry.filingDate ? (\n <>\n {`${getUILabel('patent.filed', locale)} `}\n <time dateTime={entry.filingDate}>\n {formatYearMonth(entry.filingDate, locale)}\n </time>\n </>\n ) : null}\n {entry.filingDate && entry.grantDate ? ' · ' : null}\n {entry.grantDate ? (\n <>\n {`${getUILabel('patent.granted', locale)} `}\n <time dateTime={entry.grantDate}>\n {formatYearMonth(entry.grantDate, locale)}\n </time>\n </>\n ) : null}\n </p>\n ) : null}\n {entry.coInventors && entry.coInventors.length > 0 ? (\n <p className={styles.coInventors}>\n {`${getUILabel('patent.coInventorsPrefix', locale)}${entry.coInventors.join(', ')}`}\n </p>\n ) : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedProfile } from '@takuhon/core';\n\nimport styles from './ProfileHeader.module.css';\n\nexport interface ProfileHeaderProps {\n profile: LocalizedProfile;\n}\n\nexport function ProfileHeader({ profile }: ProfileHeaderProps): React.JSX.Element {\n const locationLabel = profile.location?.display ?? profile.location?.locality;\n\n return (\n <header className={styles.header}>\n {profile.avatar ? (\n <img\n className={styles.avatar}\n src={profile.avatar.url}\n alt={profile.avatar.alt ?? ''}\n width={128}\n height={128}\n loading=\"eager\"\n decoding=\"async\"\n />\n ) : null}\n <h1 className={styles.displayName}>{profile.displayName}</h1>\n {profile.tagline ? <p className={styles.tagline}>{profile.tagline}</p> : null}\n {locationLabel ? <p className={styles.location}>{locationLabel}</p> : null}\n {profile.bio ? <p className={styles.bio}>{profile.bio}</p> : null}\n </header>\n );\n}\n","import type { LocalizedProject, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './ProjectsList.module.css';\n\nexport interface ProjectsListProps {\n projects: LocalizedProject[];\n locale?: LocaleTag;\n}\n\nfunction sortProjects(projects: LocalizedProject[]): LocalizedProject[] {\n return [...projects].sort((a, b) => {\n const aHighlighted = a.highlighted ? 1 : 0;\n const bHighlighted = b.highlighted ? 1 : 0;\n if (aHighlighted !== bHighlighted) return bHighlighted - aHighlighted;\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n}\n\nexport function ProjectsList({\n projects,\n locale = 'en',\n}: ProjectsListProps): React.JSX.Element | null {\n if (projects.length === 0) return null;\n const ordered = sortProjects(projects);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-projects-heading\">\n <h2 id=\"takuhon-projects-heading\" className={styles.heading}>\n {getUILabel('section.projects', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((project) => (\n <li\n key={project.id}\n className={styles.item}\n data-highlighted={project.highlighted ? 'true' : undefined}\n >\n <p className={styles.title}>\n {project.url ? (\n <a\n className={styles.titleLink}\n href={project.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {project.title}\n </a>\n ) : (\n project.title\n )}\n </p>\n {project.startDate !== undefined ? (\n <p className={styles.range}>\n <time dateTime={project.startDate}>\n {formatYearMonth(project.startDate, locale)}\n </time>\n {' – '}\n {project.endDate ? (\n <time dateTime={project.endDate}>{formatYearMonth(project.endDate, locale)}</time>\n ) : (\n getUILabel('timeline.present', locale)\n )}\n </p>\n ) : null}\n {project.description ? (\n <p className={styles.description}>{project.description}</p>\n ) : null}\n {project.tags && project.tags.length > 0 ? (\n <ul className={styles.tags} aria-label={getUILabel('a11y.tags', locale)}>\n {project.tags.map((tag) => (\n <li key={tag} className={styles.tag}>\n {tag}\n </li>\n ))}\n </ul>\n ) : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedPublication, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Publications.module.css';\n\nexport interface PublicationsProps {\n publications: LocalizedPublication[];\n locale?: LocaleTag;\n}\n\nfunction sortPublications(entries: LocalizedPublication[]): LocalizedPublication[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\n// Strip an optional doi.org URL prefix so the rendered href is always\n// `https://doi.org/<bare-identifier>`. Defensive against fixtures that\n// inadvertently store a full URL instead of the bare DOI per spec §6.15.\nfunction normalizeDoi(doi: string): string {\n return doi.replace(/^https?:\\/\\/(?:dx\\.)?doi\\.org\\//i, '');\n}\n\nexport function Publications({\n publications,\n locale = 'en',\n}: PublicationsProps): React.JSX.Element | null {\n if (publications.length === 0) return null;\n const ordered = sortPublications(publications);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-publications-heading\">\n <h2 id=\"takuhon-publications-heading\" className={styles.heading}>\n {getUILabel('section.publications', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n {entry.publisher ? <p className={styles.publisher}>{entry.publisher}</p> : null}\n <p className={styles.date}>\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n {entry.coAuthors && entry.coAuthors.length > 0 ? (\n <p className={styles.coAuthors}>\n {`${getUILabel('publication.coAuthorsPrefix', locale)}${entry.coAuthors.join(', ')}`}\n </p>\n ) : null}\n {entry.doi\n ? (() => {\n const bare = normalizeDoi(entry.doi);\n return (\n <p className={styles.doi}>\n <a\n className={styles.link}\n href={`https://doi.org/${bare}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {`doi:${bare}`}\n </a>\n </p>\n );\n })()\n : null}\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedRecommendation, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Recommendations.module.css';\n\nexport interface RecommendationsProps {\n recommendations: LocalizedRecommendation[];\n locale?: LocaleTag;\n}\n\nfunction sortRecommendations(entries: LocalizedRecommendation[]): LocalizedRecommendation[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return (b.date ?? '').localeCompare(a.date ?? '');\n });\n}\n\nexport function Recommendations({\n recommendations,\n locale = 'en',\n}: RecommendationsProps): React.JSX.Element | null {\n if (recommendations.length === 0) return null;\n const ordered = sortRecommendations(recommendations);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-recommendations-heading\">\n <h2 id=\"takuhon-recommendations-heading\" className={styles.heading}>\n {getUILabel('section.recommendations', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <blockquote className={styles.body}>\n <p className={styles.quote}>{entry.body}</p>\n </blockquote>\n <p className={styles.attribution}>\n <span className={styles.author}>\n {entry.author.url ? (\n <a\n className={styles.link}\n href={entry.author.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.author.name}\n </a>\n ) : (\n entry.author.name\n )}\n </span>\n {entry.author.headline ? (\n <span className={styles.headline}>{entry.author.headline}</span>\n ) : null}\n </p>\n {entry.relationship ? <p className={styles.meta}>{entry.relationship}</p> : null}\n {entry.date ? (\n <p className={styles.meta}>\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n ) : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocaleTag, Skill } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './SkillsList.module.css';\n\nexport interface SkillsListProps {\n skills: Skill[];\n locale?: LocaleTag;\n}\n\ninterface SkillGroup {\n category: string;\n skills: Skill[];\n}\n\n/** Internal grouping key for skills with no `category`; localized for display. */\nconst UNCATEGORIZED = 'other';\n\nfunction groupSkills(skills: Skill[]): SkillGroup[] {\n const sorted = [...skills].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n return aOrder - bOrder;\n });\n const groups = new Map<string, Skill[]>();\n for (const skill of sorted) {\n const key = skill.category ?? UNCATEGORIZED;\n const bucket = groups.get(key);\n if (bucket) {\n bucket.push(skill);\n } else {\n groups.set(key, [skill]);\n }\n }\n return [...groups.entries()].map(([category, items]) => ({ category, skills: items }));\n}\n\nexport function SkillsList({ skills, locale = 'en' }: SkillsListProps): React.JSX.Element | null {\n if (skills.length === 0) return null;\n const groups = groupSkills(skills);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-skills-heading\">\n <h2 id=\"takuhon-skills-heading\" className={styles.heading}>\n {getUILabel('section.skills', locale)}\n </h2>\n <div className={styles.groups}>\n {groups.map((group) => {\n // User-provided category names are profile data and stay as-is; only\n // the internal uncategorized fallback is a UI string to localize.\n const categoryLabel =\n group.category === UNCATEGORIZED\n ? getUILabel('skills.uncategorized', locale)\n : group.category;\n return (\n <div key={group.category} className={styles.group}>\n <h3 className={styles.category}>{categoryLabel}</h3>\n <ul\n className={styles.list}\n aria-label={`${categoryLabel} ${getUILabel('a11y.skillsSuffix', locale)}`}\n >\n {group.skills.map((skill) => (\n <li key={skill.id} className={styles.item}>\n {skill.label}\n </li>\n ))}\n </ul>\n </div>\n );\n })}\n </div>\n </section>\n );\n}\n","import type { LocalizedTestScore, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './TestScores.module.css';\n\nexport interface TestScoresProps {\n testScores: LocalizedTestScore[];\n locale?: LocaleTag;\n}\n\nfunction sortTestScores(entries: LocalizedTestScore[]): LocalizedTestScore[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.date.localeCompare(a.date);\n });\n}\n\nexport function TestScores({\n testScores,\n locale = 'en',\n}: TestScoresProps): React.JSX.Element | null {\n if (testScores.length === 0) return null;\n const ordered = sortTestScores(testScores);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-test-scores-heading\">\n <h2 id=\"takuhon-test-scores-heading\" className={styles.heading}>\n {getUILabel('section.testScores', locale)}\n </h2>\n <ul className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <p className={styles.title}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.title}\n </a>\n ) : (\n entry.title\n )}\n </p>\n <p className={styles.meta}>\n <span className={styles.score}>{entry.score}</span>\n {' · '}\n <time dateTime={entry.date}>{formatYearMonth(entry.date, locale)}</time>\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </li>\n ))}\n </ul>\n </section>\n );\n}\n","import type { LocalizedVolunteering, LocaleTag } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './Volunteering.module.css';\n\nexport interface VolunteeringProps {\n volunteering: LocalizedVolunteering[];\n locale?: LocaleTag;\n}\n\nfunction sortVolunteering(entries: LocalizedVolunteering[]): LocalizedVolunteering[] {\n return [...entries].sort((a, b) => {\n const aOrder = a.order ?? Number.POSITIVE_INFINITY;\n const bOrder = b.order ?? Number.POSITIVE_INFINITY;\n if (aOrder !== bOrder) return aOrder - bOrder;\n return b.startDate.localeCompare(a.startDate);\n });\n}\n\nfunction isOngoing(entry: LocalizedVolunteering): boolean {\n return entry.isCurrent === true || entry.endDate === null || entry.endDate === undefined;\n}\n\nexport function Volunteering({\n volunteering,\n locale = 'en',\n}: VolunteeringProps): React.JSX.Element | null {\n if (volunteering.length === 0) return null;\n const ordered = sortVolunteering(volunteering);\n\n return (\n <section className={styles.section} aria-labelledby=\"takuhon-volunteering-heading\">\n <h2 id=\"takuhon-volunteering-heading\" className={styles.heading}>\n {getUILabel('section.volunteering', locale)}\n </h2>\n <ol className={styles.list}>\n {ordered.map((entry) => (\n <li key={entry.id} className={styles.item}>\n <div className={styles.timelineMarker} aria-hidden=\"true\" />\n <div className={styles.content}>\n <p className={styles.organization}>\n {entry.url ? (\n <a\n className={styles.link}\n href={entry.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {entry.organization}\n </a>\n ) : (\n entry.organization\n )}\n </p>\n <p className={styles.role}>\n {entry.role}\n {entry.cause ? (\n <span className={styles.cause}>\n <span className={styles.srOnly}>{getUILabel('a11y.causePrefix', locale)}</span>\n {entry.cause}\n </span>\n ) : null}\n </p>\n <p className={styles.range}>\n <time dateTime={entry.startDate}>{formatYearMonth(entry.startDate, locale)}</time>\n {' – '}\n {isOngoing(entry) ? (\n getUILabel('timeline.present', locale)\n ) : (\n <time dateTime={entry.endDate!}>{formatYearMonth(entry.endDate!, locale)}</time>\n )}\n </p>\n {entry.description ? <p className={styles.description}>{entry.description}</p> : null}\n </div>\n </li>\n ))}\n </ol>\n </section>\n );\n}\n","import type { CvDocument, CvSection, LocaleTag, LocalizedLanguage } from '@takuhon/core';\n\nimport { formatYearMonth } from '../lib/date-formatter.js';\nimport { getUILabel, type UILabelKey } from '../lib/ui-labels.js';\n\nimport styles from './CvView.module.css';\n\nexport interface CvViewProps {\n /** The CV projection from `@takuhon/core`'s `deriveCv` (already privacy-filtered upstream). */\n cv: CvDocument;\n /** Locale for headings and dates; defaults to the CV's resolved locale. */\n locale?: LocaleTag;\n}\n\n/** Map each CV section kind to its `section.*` UI-label key. */\nconst SECTION_LABEL: Record<CvSection['kind'], UILabelKey> = {\n experience: 'section.career',\n education: 'section.education',\n skills: 'section.skills',\n certifications: 'section.certifications',\n publications: 'section.publications',\n honors: 'section.honors',\n courses: 'section.courses',\n patents: 'section.patents',\n languages: 'section.languages',\n volunteering: 'section.volunteering',\n memberships: 'section.memberships',\n};\n\n/** A normalized entry row: a heading (optionally linked), dates, a sub line, and a body. */\ninterface EntryView {\n key: string;\n heading: string;\n url?: string;\n dates?: string;\n sub?: string;\n body?: string;\n}\n\nfunction joinNonEmpty(values: (string | undefined)[], separator: string): string | undefined {\n const joined = values\n .filter((v): v is string => typeof v === 'string' && v.length > 0)\n .join(separator);\n return joined.length > 0 ? joined : undefined;\n}\n\nfunction EntryList({ entries }: { entries: EntryView[] }): React.JSX.Element {\n return (\n <ul className={styles.list}>\n {entries.map((e) => (\n <li key={e.key} className={styles.entry}>\n <div className={styles.row}>\n <h3 className={styles.entryHeading}>\n {e.url !== undefined ? <a href={e.url}>{e.heading}</a> : e.heading}\n </h3>\n {e.dates !== undefined ? <span className={styles.dates}>{e.dates}</span> : null}\n </div>\n {e.sub !== undefined ? <p className={styles.sub}>{e.sub}</p> : null}\n {e.body !== undefined ? <p className={styles.body}>{e.body}</p> : null}\n </li>\n ))}\n </ul>\n );\n}\n\nfunction ChipList({ labels }: { labels: string[] }): React.JSX.Element {\n return (\n <ul className={styles.chips}>\n {labels.map((label, i) => (\n <li key={`${label}-${String(i)}`} className={styles.chip}>\n {label}\n </li>\n ))}\n </ul>\n );\n}\n\n/** Build the dated date-range string for an entry, or undefined when blank. */\nfunction range(\n locale: LocaleTag,\n start?: string,\n end?: string | null,\n isCurrent?: boolean,\n): string | undefined {\n const left = start ? formatYearMonth(start, locale) : '';\n const ongoing = isCurrent === true || end === null;\n const right = ongoing\n ? getUILabel('timeline.present', locale)\n : end\n ? formatYearMonth(end, locale)\n : '';\n const text = left && right ? `${left} – ${right}` : left || right;\n return text || undefined;\n}\n\nfunction languageLabel(l: LocalizedLanguage, locale: LocaleTag): string {\n const name = l.displayName ?? l.language;\n return `${name} — ${getUILabel(`proficiency.${l.proficiency}`, locale)}`;\n}\n\n/** Render one CV section's body (entry list or chip list), dispatching on kind. */\nfunction SectionBody({\n section,\n locale,\n}: {\n section: CvSection;\n locale: LocaleTag;\n}): React.JSX.Element {\n switch (section.kind) {\n case 'experience':\n return (\n <EntryList\n entries={section.entries.map((c) => ({\n key: c.id,\n heading: c.role,\n sub: c.organization,\n dates: range(locale, c.startDate, c.endDate, c.isCurrent),\n body: c.description,\n url: c.url,\n }))}\n />\n );\n case 'education':\n return (\n <EntryList\n entries={section.entries.map((e) => {\n const degree = joinNonEmpty([e.degree, e.fieldOfStudy], ', ');\n return {\n key: e.id,\n heading: degree ?? e.institution,\n sub: degree ? e.institution : undefined,\n dates: range(locale, e.startDate, e.endDate, e.isCurrent),\n body: e.description,\n url: e.url,\n };\n })}\n />\n );\n case 'skills':\n return <ChipList labels={section.entries.map((s) => s.label)} />;\n case 'languages':\n return <ChipList labels={section.entries.map((l) => languageLabel(l, locale))} />;\n case 'certifications':\n return (\n <EntryList\n entries={section.entries.map((c) => ({\n key: c.id,\n heading: c.title,\n sub: c.issuingOrganization,\n dates: range(locale, c.issueDate, c.expirationDate),\n url: c.url,\n }))}\n />\n );\n case 'publications':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.title,\n sub: joinNonEmpty([x.publisher, x.coAuthors?.join(', ')], ' · '),\n dates: range(locale, x.date),\n body: x.description,\n url: x.url ?? (x.doi ? `https://doi.org/${x.doi}` : undefined),\n }))}\n />\n );\n case 'honors':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.title,\n sub: x.issuer,\n dates: range(locale, x.date),\n body: x.description,\n url: x.url,\n }))}\n />\n );\n case 'courses':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.title,\n sub: x.provider,\n dates: range(locale, x.completionDate),\n body: x.description,\n url: x.certificateUrl,\n }))}\n />\n );\n case 'patents':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.title,\n sub: joinNonEmpty([x.patentNumber, x.office, x.status], ' · '),\n dates: range(locale, x.filingDate ?? x.grantDate),\n body: x.description,\n url: x.url,\n }))}\n />\n );\n case 'volunteering':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.role,\n sub: joinNonEmpty([x.organization, x.cause], ' · '),\n dates: range(locale, x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n }))}\n />\n );\n case 'memberships':\n return (\n <EntryList\n entries={section.entries.map((x) => ({\n key: x.id,\n heading: x.role ?? x.organization,\n sub: x.role ? x.organization : undefined,\n dates: range(locale, x.startDate, x.endDate, x.isCurrent),\n body: x.description,\n url: x.url,\n }))}\n />\n );\n }\n}\n\n/**\n * Print-ready résumé/CV view, the React counterpart of the CLI's `renderCvHtml`.\n * Renders a {@link CvDocument} (from `@takuhon/core`'s `deriveCv`) as an A4\n * single-column document; the co-located CSS module carries an `@media print`\n * block so the browser's \"Save as PDF\" yields a clean résumé. This is a\n * presentational component (it shows what `deriveCv` gives it, which the host\n * has already privacy-filtered) and renders nothing for an empty CV.\n */\nexport function CvView({ cv, locale }: CvViewProps): React.JSX.Element | null {\n const loc = locale ?? cv.resolvedLocale;\n const h = cv.header;\n if (cv.sections.length === 0 && h.displayName === '') return null;\n\n const contact: React.JSX.Element[] = [];\n if (h.location !== undefined) contact.push(<span key=\"loc\">{h.location}</span>);\n if (h.email !== undefined) {\n contact.push(\n <a key=\"email\" href={`mailto:${h.email}`}>\n {h.email}\n </a>,\n );\n }\n if (h.formUrl !== undefined) {\n contact.push(\n <a key=\"form\" href={h.formUrl}>\n {getUILabel('contact.formLink', loc)}\n </a>,\n );\n }\n\n return (\n <article className={styles.cv} lang={loc}>\n <header className={styles.header}>\n <h1 className={styles.name}>{h.displayName}</h1>\n {h.tagline !== undefined ? <p className={styles.tagline}>{h.tagline}</p> : null}\n {contact.length > 0 ? <div className={styles.contact}>{contact}</div> : null}\n {h.bio !== undefined ? <p className={styles.bio}>{h.bio}</p> : null}\n </header>\n {cv.sections.map((section) => (\n <section key={section.kind} className={styles.section}>\n <h2 className={styles.heading}>{getUILabel(SECTION_LABEL[section.kind], loc)}</h2>\n <SectionBody section={section} locale={loc} />\n </section>\n ))}\n </article>\n );\n}\n","import type { LocaleTag } from '@takuhon/core';\n\nimport { getUILabel } from '../lib/ui-labels.js';\n\nimport styles from './LocaleSwitcher.module.css';\n\nexport interface LocaleSwitcherProps {\n availableLocales: LocaleTag[];\n currentLocale: LocaleTag;\n onSelect: (locale: LocaleTag) => void;\n ariaLabel?: string;\n formatLocale?: (locale: LocaleTag) => string;\n}\n\nexport function LocaleSwitcher({\n availableLocales,\n currentLocale,\n onSelect,\n ariaLabel,\n formatLocale,\n}: LocaleSwitcherProps): React.JSX.Element {\n const label = ariaLabel ?? getUILabel('a11y.selectLanguage', currentLocale);\n const format = formatLocale ?? ((locale: LocaleTag) => locale);\n return (\n <div className={styles.wrapper}>\n <select\n className={styles.select}\n aria-label={label}\n value={currentLocale}\n onChange={(event) => {\n onSelect(event.target.value);\n }}\n >\n {availableLocales.map((locale) => (\n <option key={locale} value={locale}>\n {format(locale)}\n </option>\n ))}\n </select>\n </div>\n );\n}\n","import { generateJsonLd, type LocalizedTakuhon } from '@takuhon/core';\nimport { useEffect } from 'react';\n\nexport interface TakuhonHeadProps {\n data: LocalizedTakuhon;\n siteUrl?: string;\n pageUrl?: string;\n}\n\nfunction primarySubtag(tag: string): string {\n const dash = tag.indexOf('-');\n return (dash === -1 ? tag : tag.slice(0, dash)).toLowerCase();\n}\n\n/**\n * Whether a leading path segment should be treated as a locale prefix.\n * Mirrors the server resolver's `matchAvailable` so the two surfaces agree:\n * an exact (case-insensitive) match, or a primary-subtag match so a\n * regional segment like `en-US` is recognized against an available `en`.\n */\nfunction isLocaleSegment(segment: string, availableLocales: readonly string[]): boolean {\n const lower = segment.toLowerCase();\n const primary = primarySubtag(segment);\n return availableLocales.some(\n (loc) => loc.toLowerCase() === lower || primarySubtag(loc) === primary,\n );\n}\n\n/**\n * Remove a leading `/{locale}` path segment (when it is recognizable as a\n * locale per {@link isLocaleSegment}) and any legacy `?lang=` query,\n * yielding a locale-neutral base URL. This prevents stacking (`/ja/en/...`,\n * `/en/en-US/...`) when the current page is already locale-prefixed: the\n * existing segment is stripped before {@link withLocalePrefix} re-adds the\n * target locale.\n */\nfunction localeNeutralUrl(pageUrl: string, availableLocales: readonly string[]): string {\n try {\n const url = new URL(pageUrl);\n url.searchParams.delete('lang');\n const segments = url.pathname.split('/');\n const first = segments[1];\n if (first !== undefined && first !== '' && isLocaleSegment(first, availableLocales)) {\n segments.splice(1, 1);\n url.pathname = segments.join('/') || '/';\n }\n return url.toString();\n } catch {\n return pageUrl;\n }\n}\n\n/**\n * Prepend a `/{locale}` path segment to a locale-neutral URL, producing\n * the canonical path form (`https://site/profile` → `https://site/ja/profile`,\n * `https://site/` → `https://site/ja/`). The path form is the advertised\n * URL; `?lang=` remains a resolution input but is never emitted here.\n *\n * This is deployment-agnostic: it inserts a locale segment into whatever\n * page URL `TakuhonHead` is given, regardless of how that page is routed.\n * The built-in `@takuhon/api` public app resolves the path prefix for its\n * own surfaces (`/`, `/api/profile`, `/api/jsonld`); the canonical\n * deployment serves the rendered profile at the site root, so its `/ja/`\n * form resolves out of the box. A deployment that serves the HTML profile\n * at another path is responsible for routing that locale-prefixed page.\n */\nfunction withLocalePrefix(neutralUrl: string, locale: string): string {\n try {\n const url = new URL(neutralUrl);\n url.pathname = url.pathname === '/' ? `/${locale}/` : `/${locale}${url.pathname}`;\n return url.toString();\n } catch {\n return neutralUrl;\n }\n}\n\nfunction absolutizeUrl(url: string | undefined, base: string | undefined): string | undefined {\n if (!url) return undefined;\n if (!base) return url;\n try {\n return new URL(url, base).toString();\n } catch {\n return url;\n }\n}\n\nfunction detectSiteUrl(explicit: string | undefined): string | undefined {\n if (explicit) return explicit;\n if (typeof window !== 'undefined') return window.location.origin;\n return undefined;\n}\n\nfunction detectPageUrl(\n explicit: string | undefined,\n siteUrl: string | undefined,\n): string | undefined {\n if (explicit) return explicit;\n if (typeof window !== 'undefined') {\n return window.location.origin + window.location.pathname;\n }\n return siteUrl;\n}\n\nexport function TakuhonHead({ data, siteUrl, pageUrl }: TakuhonHeadProps): React.JSX.Element {\n const resolvedSiteUrl = detectSiteUrl(siteUrl);\n const resolvedPageUrl = detectPageUrl(pageUrl, resolvedSiteUrl);\n\n const { profile, settings, resolvedLocale } = data;\n const description = profile.bio ?? profile.tagline;\n const ogDescription = profile.tagline ?? profile.bio;\n const ogImage = absolutizeUrl(profile.avatar?.url, resolvedSiteUrl);\n const twitterCard = profile.avatar ? 'summary_large_image' : 'summary';\n\n // Locale-neutral base, so canonical/alternates emit one clean path form\n // per locale (`/ja/...`) and never stack when the current page is\n // already locale-prefixed.\n const neutralPageUrl = resolvedPageUrl\n ? localeNeutralUrl(resolvedPageUrl, settings.availableLocales)\n : undefined;\n\n const canonical = neutralPageUrl ? withLocalePrefix(neutralPageUrl, resolvedLocale) : undefined;\n const alternates = neutralPageUrl\n ? settings.availableLocales.map((loc) => ({\n locale: loc,\n href: withLocalePrefix(neutralPageUrl, loc),\n }))\n : [];\n const xDefaultHref = neutralPageUrl\n ? withLocalePrefix(neutralPageUrl, settings.defaultLocale)\n : undefined;\n\n const ogAlternates = settings.availableLocales.filter((loc) => loc !== resolvedLocale);\n\n const emitJsonLd = settings.enableJsonLd !== false;\n const jsonLdPayload = emitJsonLd ? JSON.stringify(generateJsonLd(data)) : null;\n\n useEffect(() => {\n if (!jsonLdPayload) return;\n const script = document.createElement('script');\n script.type = 'application/ld+json';\n script.textContent = jsonLdPayload;\n document.head.appendChild(script);\n return () => {\n script.remove();\n };\n }, [jsonLdPayload]);\n\n return (\n <>\n <title>{profile.displayName}</title>\n {description ? <meta name=\"description\" content={description} /> : null}\n {canonical ? <link rel=\"canonical\" href={canonical} /> : null}\n\n <meta property=\"og:title\" content={profile.displayName} />\n {ogDescription ? <meta property=\"og:description\" content={ogDescription} /> : null}\n {canonical ? <meta property=\"og:url\" content={canonical} /> : null}\n {ogImage ? <meta property=\"og:image\" content={ogImage} /> : null}\n <meta property=\"og:type\" content=\"profile\" />\n <meta property=\"og:locale\" content={resolvedLocale} />\n {ogAlternates.map((loc) => (\n <meta key={loc} property=\"og:locale:alternate\" content={loc} />\n ))}\n\n <meta name=\"twitter:card\" content={twitterCard} />\n\n {alternates.map(({ locale, href }) => (\n <link key={locale} rel=\"alternate\" hrefLang={locale} href={href} />\n ))}\n {xDefaultHref ? <link rel=\"alternate\" hrefLang=\"x-default\" href={xDefaultHref} /> : null}\n </>\n );\n}\n"],"mappings":";AAEA,OAAO;;;ACFP,SAAS,yBAAyB;;;AC8DlC,IAAM,KAAsB;AAAA,EAC1B,oBAAoB;AAAA,EACpB,8BAA8B;AAAA,EAC9B,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,4BAA4B;AAAA,EAC5B,+BAA+B;AAAA,EAC/B,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA;AAAA,EAGnB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,wBAAwB;AAC1B;AAQA,IAAM,KAAsB;AAAA,EAC1B,oBAAoB;AAAA,EACpB,8BAA8B;AAAA,EAC9B,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,4BAA4B;AAAA,EAC5B,+BAA+B;AAAA,EAC/B,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,4BAA4B;AAAA,EAC5B,4BAA4B;AAAA,EAC5B,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA,EAC1B,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA,EACxB,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,sBAAsB;AAAA,EACtB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA;AAAA;AAAA,EAGnB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,wBAAwB;AAC1B;AAEA,IAAM,eAAmD;AAAA,EACvD,IAAI;AAAA,EACJ,IAAI;AACN;AAQO,SAAS,WAAW,KAAiB,QAA2B;AACrE,QAAM,OAAO,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AACrC,SAAO,aAAa,MAAM,IAAI,GAAG,KAAK,aAAa,IAAI,IAAI,GAAG,KAAK,GAAG,GAAG;AAC3E;;;ADrKA,OAAO,YAAY;AA2Bf,SACE,KADF;AATG,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,SAAS;AACX,GAAmD;AACjD,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAAM,kBAAkB,QAAQ;AACtC,MAAI,QAAQ,GAAI,QAAO;AAEvB,SACE,qBAAC,aAAQ,WAAW,OAAO,SAAS,mBAAgB,4BAClD;AAAA,wBAAC,QAAG,IAAG,4BAA2B,WAAW,OAAO,SACjD,qBAAW,oBAAoB,MAAM,GACxC;AAAA,IAIA,oBAAC,SAAI,WAAW,OAAO,MAAM,yBAAyB,EAAE,QAAQ,IAAI,GAAG;AAAA,KACzE;AAEJ;;;AExCA,IAAM,aAAa;AAkBZ,SAAS,gBAAgB,OAAe,QAA2B;AACxE,QAAM,QAAQ,WAAW,KAAK,KAAK;AACnC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,OAAO,MAAM,CAAC,CAAC;AAC5B,QAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC7B,QAAM,OAAO,oBAAI,KAAK,CAAC;AACvB,OAAK,eAAe,MAAM,QAAQ,GAAG,CAAC;AACtC,QAAM,UAAsC;AAAA,IAC1C,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AACA,MAAI;AACF,WAAO,IAAI,KAAK,eAAe,UAAU,MAAM,OAAO,EAAE,OAAO,IAAI;AAAA,EACrE,QAAQ;AAEN,WAAO,IAAI,KAAK,eAAe,MAAM,OAAO,EAAE,OAAO,IAAI;AAAA,EAC3D;AACF;;;ACjCA,OAAOA,aAAY;AA6Bb,SAmBY,UAnBZ,OAAAC,MAUY,QAAAC,aAVZ;AAtBN,SAAS,YAAY,SAA+C;AAClE,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC9C,CAAC;AACH;AAEA,SAAS,UAAU,QAAkC;AACnD,SAAO,OAAO,cAAc,QAAQ,OAAO,YAAY,QAAQ,OAAO,YAAY;AACpF;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,SAAS;AACX,GAAkD;AAChD,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,UAAU,YAAY,OAAO;AAEnC,SACE,gBAAAA,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,0BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,0BAAyB,WAAWD,QAAO,SAC/C,qBAAW,kBAAkB,MAAM,GACtC;AAAA,IACA,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACnB,kBAAQ,IAAI,CAAC,WACZ,gBAAAE,MAAC,QAAmB,WAAWF,QAAO,MACpC;AAAA,sBAAAC,KAAC,SAAI,WAAWD,QAAO,gBAAgB,eAAY,QAAO;AAAA,MAC1D,gBAAAE,MAAC,SAAI,WAAWF,QAAO,SACrB;AAAA,wBAAAC,KAAC,OAAE,WAAWD,QAAO,MAClB,iBAAO,MACN,gBAAAE;AAAA,UAAC;AAAA;AAAA,YACC,WAAWF,QAAO;AAAA,YAClB,MAAM,OAAO;AAAA,YACb,QAAO;AAAA,YACP,KAAI;AAAA,YAEH;AAAA,qBAAO;AAAA,cAAK;AAAA,cAAI,OAAO;AAAA;AAAA;AAAA,QAC1B,IAEA,gBAAAE,MAAA,YACG;AAAA,iBAAO;AAAA,UAAK;AAAA,UAAI,OAAO;AAAA,WAC1B,GAEJ;AAAA,QACA,gBAAAA,MAAC,OAAE,WAAWF,QAAO,OACnB;AAAA,0BAAAC,KAAC,UAAK,UAAU,OAAO,WAAY,0BAAgB,OAAO,WAAW,MAAM,GAAE;AAAA,UAC5E;AAAA,UACA,UAAU,MAAM,IACf,WAAW,oBAAoB,MAAM,IAErC,gBAAAA,KAAC,UAAK,UAAU,OAAO,SAAW,0BAAgB,OAAO,SAAU,MAAM,GAAE;AAAA,WAE/E;AAAA,QACC,OAAO,UAAU,UAChB,gBAAAA,KAAC,OAAE,WAAWD,QAAO,UAAW,iBAAO,SAAS,SAAQ,IACtD;AAAA,QACH,OAAO,cACN,gBAAAC,KAAC,OAAE,WAAWD,QAAO,aAAc,iBAAO,aAAY,IACpD;AAAA,SACN;AAAA,SAlCO,OAAO,EAmChB,CACD,GACH;AAAA,KACF;AAEJ;;;AC1EA,OAAOG,aAAY;AAyBb,SA6BU,YAAAC,WA7BV,OAAAC,MAwBU,QAAAC,aAxBV;AAlBN,SAAS,UAAU,OAA2D;AAC5E,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC9C,CAAC;AACH;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA,SAAS;AACX,GAAkD;AAChD,MAAI,eAAe,WAAW,EAAG,QAAO;AACxC,QAAM,UAAU,UAAU,cAAc;AAExC,SACE,gBAAAA,MAAC,aAAQ,WAAWH,QAAO,SAAS,mBAAgB,kCAClD;AAAA,oBAAAE,KAAC,QAAG,IAAG,kCAAiC,WAAWF,QAAO,SACvD,qBAAW,0BAA0B,MAAM,GAC9C;AAAA,IACA,gBAAAE,KAAC,QAAG,WAAWF,QAAO,MACnB,kBAAQ,IAAI,CAAC,SACZ,gBAAAG,MAAC,QAAiB,WAAWH,QAAO,MAClC;AAAA,sBAAAE,KAAC,OAAE,WAAWF,QAAO,OAClB,eAAK,MACJ,gBAAAE;AAAA,QAAC;AAAA;AAAA,UACC,WAAWF,QAAO;AAAA,UAClB,MAAM,KAAK;AAAA,UACX,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,eAAK;AAAA;AAAA,MACR,IAEA,KAAK,OAET;AAAA,MACA,gBAAAE,KAAC,OAAE,WAAWF,QAAO,QAAS,eAAK,qBAAoB;AAAA,MACvD,gBAAAG,MAAC,OAAE,WAAWH,QAAO,OACnB;AAAA,wBAAAE,KAAC,UAAK,UAAU,KAAK,WAAY,0BAAgB,KAAK,WAAW,MAAM,GAAE;AAAA,QACxE,KAAK,mBAAmB,OACvB,gBAAAC,MAAC,UAAK,WAAWH,QAAO,KACrB;AAAA;AAAA,UAAI;AAAA,UACF,WAAW,8BAA8B,MAAM;AAAA,WACpD,IACE,KAAK,mBAAmB,SAC1B,gBAAAG,MAAAF,WAAA,EACG;AAAA;AAAA,UACD,gBAAAC,KAAC,UAAK,UAAU,KAAK,gBAClB,0BAAgB,KAAK,gBAAgB,MAAM,GAC9C;AAAA,WACF,IACE;AAAA,SACN;AAAA,SA/BO,KAAK,EAmCd,CACD,GACH;AAAA,KACF;AAEJ;;;ACvEA,OAAOE,aAAY;AAgBb,gBAAAC,MAGA,QAAAC,aAHA;AATC,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,SAAS;AACX,GAA+C;AAC7C,QAAM,YAAY,QAAQ,cAAc,QAAQ,QAAQ,UAAU;AAClE,MAAI,CAAC,aAAa,QAAQ,YAAY,OAAW,QAAO;AAExD,SACE,gBAAAA,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,2BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,2BAA0B,WAAWD,QAAO,SAChD,qBAAW,mBAAmB,MAAM,GACvC;AAAA,IACA,gBAAAE,MAAC,QAAG,WAAWF,QAAO,MACnB;AAAA,mBAAa,QAAQ,UAAU,SAC9B,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACpB,0BAAAC,KAAC,OAAE,WAAWD,QAAO,MAAM,MAAM,UAAU,QAAQ,KAAK,IACrD,kBAAQ,OACX,GACF,IACE;AAAA,MACH,QAAQ,YAAY,SACnB,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACpB,0BAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWD,QAAO;AAAA,UAClB,MAAM,QAAQ;AAAA,UACd,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,qBAAW,oBAAoB,MAAM;AAAA;AAAA,MACxC,GACF,IACE;AAAA,OACN;AAAA,KACF;AAEJ;;;ACzCA,OAAOG,aAAY;AAsBb,gBAAAC,MAKI,QAAAC,aALJ;AAfN,SAAS,YAAY,SAA+C;AAClE,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,YAAQ,EAAE,kBAAkB,IAAI,cAAc,EAAE,kBAAkB,EAAE;AAAA,EACtE,CAAC;AACH;AAEO,SAAS,QAAQ,EAAE,SAAS,SAAS,KAAK,GAA2C;AAC1F,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,UAAU,YAAY,OAAO;AAEnC,SACE,gBAAAA,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,2BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,2BAA0B,WAAWD,QAAO,SAChD,qBAAW,mBAAmB,MAAM,GACvC;AAAA,IACA,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,MAAC,QAAkB,WAAWF,QAAO,MACnC;AAAA,sBAAAC,KAAC,OAAE,WAAWD,QAAO,OAClB,gBAAM,iBACL,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWD,QAAO;AAAA,UAClB,MAAM,MAAM;AAAA,UACZ,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,gBAAM;AAAA;AAAA,MACT,IAEA,MAAM,OAEV;AAAA,MACC,MAAM,WAAW,gBAAAC,KAAC,OAAE,WAAWD,QAAO,UAAW,gBAAM,UAAS,IAAO;AAAA,MACvE,MAAM,eACL,gBAAAC,KAAC,OAAE,WAAWD,QAAO,cAAe,gBAAM,cAAa,IACrD;AAAA,MACH,MAAM,iBACL,gBAAAC,KAAC,OAAE,WAAWD,QAAO,MACnB,0BAAAC,KAAC,UAAK,UAAU,MAAM,gBACnB,0BAAgB,MAAM,gBAAgB,MAAM,GAC/C,GACF,IACE;AAAA,MACH,MAAM,cAAc,gBAAAA,KAAC,OAAE,WAAWD,QAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SA1B1E,MAAM,EA2Bf,CACD,GACH;AAAA,KACF;AAEJ;;;AC3DA,OAAOG,aAAY;AAoCb,gBAAAC,MAyBU,QAAAC,aAzBV;AA7BN,SAAS,cAAc,SAAqD;AAC1E,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC9C,CAAC;AACH;AAEA,SAASC,WAAU,OAAoC;AACrD,SAAO,MAAM,cAAc,QAAQ,MAAM,YAAY,QAAQ,MAAM,YAAY;AACjF;AAEA,SAAS,iBAAiB,OAA+C;AACvE,MAAI,MAAM,WAAW,UAAa,MAAM,iBAAiB,QAAW;AAClE,WAAO,GAAG,MAAM,MAAM,SAAM,MAAM,YAAY;AAAA,EAChD;AACA,SAAO,MAAM,UAAU,MAAM;AAC/B;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,SAAS;AACX,GAAqD;AACnD,MAAI,UAAU,WAAW,EAAG,QAAO;AACnC,QAAM,UAAU,cAAc,SAAS;AAEvC,SACE,gBAAAD,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,6BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,6BAA4B,WAAWD,QAAO,SAClD,qBAAW,qBAAqB,MAAM,GACzC;AAAA,IACA,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACnB,kBAAQ,IAAI,CAAC,UAAU;AACtB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,aACE,gBAAAE,MAAC,QAAkB,WAAWF,QAAO,MACnC;AAAA,wBAAAC,KAAC,SAAI,WAAWD,QAAO,gBAAgB,eAAY,QAAO;AAAA,QAC1D,gBAAAE,MAAC,SAAI,WAAWF,QAAO,SACrB;AAAA,0BAAAC,KAAC,OAAE,WAAWD,QAAO,aAClB,gBAAM,MACL,gBAAAC;AAAA,YAAC;AAAA;AAAA,cACC,WAAWD,QAAO;AAAA,cAClB,MAAM,MAAM;AAAA,cACZ,QAAO;AAAA,cACP,KAAI;AAAA,cAEH,gBAAM;AAAA;AAAA,UACT,IAEA,MAAM,aAEV;AAAA,UACC,QAAQ,gBAAAC,KAAC,OAAE,WAAWD,QAAO,OAAQ,iBAAM,IAAO;AAAA,UACnD,gBAAAE,MAAC,OAAE,WAAWF,QAAO,OACnB;AAAA,4BAAAC,KAAC,UAAK,UAAU,MAAM,WAAY,0BAAgB,MAAM,WAAW,MAAM,GAAE;AAAA,YAC1E;AAAA,YACAE,WAAU,KAAK,IACd,WAAW,oBAAoB,MAAM,IAErC,gBAAAF,KAAC,UAAK,UAAU,MAAM,SAAW,0BAAgB,MAAM,SAAU,MAAM,GAAE;AAAA,aAE7E;AAAA,UACC,MAAM,QAAQ,gBAAAA,KAAC,OAAE,WAAWD,QAAO,OAAQ,gBAAM,OAAM,IAAO;AAAA,UAC9D,MAAM,cACL,gBAAAC,KAAC,OAAE,WAAWD,QAAO,aAAc,gBAAM,aAAY,IACnD;AAAA,WACN;AAAA,WA/BO,MAAM,EAgCf;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;;;ACtFA,OAAOI,aAAY;AAKb,SAEE,OAAAC,MAFF,QAAAC,aAAA;AAHC,SAAS,SAA4B;AAC1C,SACE,gBAAAD,KAAC,YAAO,WAAWD,QAAO,QACxB,0BAAAE,MAAC,OAAE,WAAWF,QAAO,MAAM;AAAA;AAAA,IACd;AAAA,IACX,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAWD,QAAO;AAAA,QAClB,MAAK;AAAA,QACL,QAAO;AAAA,QACP,KAAI;AAAA,QACL;AAAA;AAAA,IAED;AAAA,KACF,GACF;AAEJ;;;ACbA,OAAOG,aAAY;AAsBb,gBAAAC,MAoBM,QAAAC,aApBN;AAfN,SAAS,WAAW,QAA4C;AAC9D,SAAO,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAChC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AACH;AAEO,SAAS,WAAW,EAAE,QAAQ,SAAS,KAAK,GAA8C;AAC/F,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,UAAU,WAAW,MAAM;AAEjC,SACE,gBAAAA,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,0BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,0BAAyB,WAAWD,QAAO,SAC/C,qBAAW,kBAAkB,MAAM,GACtC;AAAA,IACA,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,MAAC,QAAkB,WAAWF,QAAO,MACnC;AAAA,sBAAAC,KAAC,OAAE,WAAWD,QAAO,OAClB,gBAAM,MACL,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWD,QAAO;AAAA,UAClB,MAAM,MAAM;AAAA,UACZ,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,gBAAM;AAAA;AAAA,MACT,IAEA,MAAM,OAEV;AAAA,MACA,gBAAAE,MAAC,OAAE,WAAWF,QAAO,MAClB;AAAA,cAAM;AAAA,QACN;AAAA,QACD,gBAAAC,KAAC,UAAK,UAAU,MAAM,MAAO,0BAAgB,MAAM,MAAM,MAAM,GAAE;AAAA,SACnE;AAAA,MACC,MAAM,cAAc,gBAAAA,KAAC,OAAE,WAAWD,QAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SApB1E,MAAM,EAqBf,CACD,GACH;AAAA,KACF;AAEJ;;;ACtDA,OAAOG,aAAY;AAqBb,gBAAAC,MAKI,QAAAC,aALJ;AAdN,SAAS,cAAc,WAAqD;AAC1E,SAAO,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM;AACnC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,WAAO,SAAS;AAAA,EAClB,CAAC;AACH;AAEO,SAAS,UAAU,EAAE,WAAW,SAAS,KAAK,GAA6C;AAChG,MAAI,UAAU,WAAW,EAAG,QAAO;AACnC,QAAM,UAAU,cAAc,SAAS;AAEvC,SACE,gBAAAA,MAAC,aAAQ,WAAWF,QAAO,SAAS,mBAAgB,6BAClD;AAAA,oBAAAC,KAAC,QAAG,IAAG,6BAA4B,WAAWD,QAAO,SAClD,qBAAW,qBAAqB,MAAM,GACzC;AAAA,IACA,gBAAAC,KAAC,QAAG,WAAWD,QAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,MAAC,QAAkB,WAAWF,QAAO,MACnC;AAAA,sBAAAC,KAAC,UAAK,WAAWD,QAAO,MAAM,MAAM,MAAM,UACvC,gBAAM,eAAe,MAAM,UAC9B;AAAA,MACA,gBAAAC,KAAC,UAAK,WAAWD,QAAO,aACrB,qBAAW,eAAe,MAAM,WAAW,IAAI,MAAM,GACxD;AAAA,SANO,MAAM,EAOf,CACD,GACH;AAAA,KACF;AAEJ;;;ACtCA,OAAOG,cAAY;AAkCP,SAOkB,OAAAC,OAPlB,QAAAC,cAAA;AA3BZ,SAAS,UAAU,OAAyC;AAC1D,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,YAAY,EAAE,WAAW,IAAI;AACnC,UAAM,YAAY,EAAE,WAAW,IAAI;AACnC,QAAI,cAAc,UAAW,QAAO,YAAY;AAChD,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,WAAO,SAAS;AAAA,EAClB,CAAC;AACH;AAEA,SAAS,gBAAgB,MAA6B;AACpD,MAAI,KAAK,MAAO,QAAO,KAAK;AAC5B,MAAI,KAAK,SAAS,SAAU,QAAO,KAAK;AACxC,SAAO,KAAK;AACd;AAEO,SAAS,UAAU,EAAE,OAAO,SAAS,KAAK,GAA6C;AAC5F,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,UAAU,UAAU,KAAK;AAE/B,SACE,gBAAAD,MAAC,SAAI,cAAY,WAAW,qBAAqB,MAAM,GAAG,WAAWD,SAAO,KAC1E,0BAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,SACZ,gBAAAC,MAAC,QAAiB,WAAWD,SAAO,MAClC,0BAAAE;AAAA,IAAC;AAAA;AAAA,MACC,WAAWF,SAAO;AAAA,MAClB,MAAM,KAAK;AAAA,MACX,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,iBAAe,KAAK,WAAW,SAAS;AAAA,MAEvC;AAAA,aAAK,UAAU,gBAAAC,MAAC,SAAI,WAAWD,SAAO,MAAM,KAAK,KAAK,SAAS,KAAI,IAAG,IAAK;AAAA,QAC5E,gBAAAC,MAAC,UAAK,WAAWD,SAAO,OAAQ,0BAAgB,IAAI,GAAE;AAAA;AAAA;AAAA,EACxD,KAVO,KAAK,EAWd,CACD,GACH,GACF;AAEJ;;;AChDA,OAAOG,cAAY;AA6Bb,gBAAAC,OAuBQ,QAAAC,cAvBR;AAtBN,SAAS,gBAAgB,SAAuD;AAC9E,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC9C,CAAC;AACH;AAEA,SAASC,WAAU,OAAqC;AACtD,SAAO,MAAM,cAAc,QAAQ,MAAM,YAAY,QAAQ,MAAM,YAAY;AACjF;AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA,SAAS;AACX,GAA+C;AAC7C,MAAI,YAAY,WAAW,EAAG,QAAO;AACrC,QAAM,UAAU,gBAAgB,WAAW;AAE3C,SACE,gBAAAD,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,+BAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,+BAA8B,WAAWD,SAAO,SACpD,qBAAW,uBAAuB,MAAM,GAC3C;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,OAAC,QAAkB,WAAWF,SAAO,MACnC;AAAA,sBAAAC,MAAC,SAAI,WAAWD,SAAO,gBAAgB,eAAY,QAAO;AAAA,MAC1D,gBAAAE,OAAC,SAAI,WAAWF,SAAO,SACrB;AAAA,wBAAAC,MAAC,OAAE,WAAWD,SAAO,cAClB,gBAAM,MACL,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAWD,SAAO;AAAA,YAClB,MAAM,MAAM;AAAA,YACZ,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,gBAAM;AAAA;AAAA,QACT,IAEA,MAAM,cAEV;AAAA,QACC,MAAM,OAAO,gBAAAC,MAAC,OAAE,WAAWD,SAAO,MAAO,gBAAM,MAAK,IAAO;AAAA,QAC5D,gBAAAE,OAAC,OAAE,WAAWF,SAAO,OACnB;AAAA,0BAAAC,MAAC,UAAK,UAAU,MAAM,WAAY,0BAAgB,MAAM,WAAW,MAAM,GAAE;AAAA,UAC1E;AAAA,UACAE,WAAU,KAAK,IACd,WAAW,oBAAoB,MAAM,IAErC,gBAAAF,MAAC,UAAK,UAAU,MAAM,SAAW,0BAAgB,MAAM,SAAU,MAAM,GAAE;AAAA,WAE7E;AAAA,QACC,MAAM,cAAc,gBAAAA,MAAC,OAAE,WAAWD,SAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SACnF;AAAA,SA5BO,MAAM,EA6Bf,CACD,GACH;AAAA,KACF;AAEJ;;;ACpEA,OAAOI,cAAY;AAwBb,SA6BY,YAAAC,WA7BZ,OAAAC,OAmBQ,QAAAC,cAnBR;AAjBN,SAAS,YAAY,SAA+C;AAClE,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,UAAM,QAAQ,EAAE,aAAa,EAAE,cAAc;AAC7C,UAAM,QAAQ,EAAE,aAAa,EAAE,cAAc;AAC7C,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,CAAC;AACH;AAEO,SAAS,QAAQ,EAAE,SAAS,SAAS,KAAK,GAA2C;AAC1F,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QAAM,UAAU,YAAY,OAAO;AAEnC,SACE,gBAAAA,OAAC,aAAQ,WAAWH,SAAO,SAAS,mBAAgB,2BAClD;AAAA,oBAAAE,MAAC,QAAG,IAAG,2BAA0B,WAAWF,SAAO,SAChD,qBAAW,mBAAmB,MAAM,GACvC;AAAA,IACA,gBAAAE,MAAC,QAAG,WAAWF,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAG,OAAC,QAAkB,WAAWH,SAAO,MACnC;AAAA,sBAAAG,OAAC,OAAE,WAAWH,SAAO,OAClB;AAAA,cAAM,MACL,gBAAAE;AAAA,UAAC;AAAA;AAAA,YACC,WAAWF,SAAO;AAAA,YAClB,MAAM,MAAM;AAAA,YACZ,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,gBAAM;AAAA;AAAA,QACT,IAEA,MAAM;AAAA,QAER,gBAAAG,OAAC,UAAK,WAAWH,SAAO,aAAa,eAAa,MAAM,QACtD;AAAA,0BAAAE,MAAC,UAAK,WAAWF,SAAO,QAAS,qBAAW,qBAAqB,MAAM,GAAE;AAAA,UACxE,WAAW,gBAAgB,MAAM,MAAM,IAAI,MAAM;AAAA,WACpD;AAAA,SACF;AAAA,MACA,gBAAAE,MAAC,OAAE,WAAWF,SAAO,cAAe,gBAAM,cAAa;AAAA,MACtD,MAAM,SAAS,gBAAAE,MAAC,OAAE,WAAWF,SAAO,QAAS,gBAAM,QAAO,IAAO;AAAA,MACjE,MAAM,eAAe,UAAa,MAAM,cAAc,SACrD,gBAAAG,OAAC,OAAE,WAAWH,SAAO,OAClB;AAAA,cAAM,aACL,gBAAAG,OAAAF,WAAA,EACG;AAAA,aAAG,WAAW,gBAAgB,MAAM,CAAC;AAAA,UACtC,gBAAAC,MAAC,UAAK,UAAU,MAAM,YACnB,0BAAgB,MAAM,YAAY,MAAM,GAC3C;AAAA,WACF,IACE;AAAA,QACH,MAAM,cAAc,MAAM,YAAY,WAAQ;AAAA,QAC9C,MAAM,YACL,gBAAAC,OAAAF,WAAA,EACG;AAAA,aAAG,WAAW,kBAAkB,MAAM,CAAC;AAAA,UACxC,gBAAAC,MAAC,UAAK,UAAU,MAAM,WACnB,0BAAgB,MAAM,WAAW,MAAM,GAC1C;AAAA,WACF,IACE;AAAA,SACN,IACE;AAAA,MACH,MAAM,eAAe,MAAM,YAAY,SAAS,IAC/C,gBAAAA,MAAC,OAAE,WAAWF,SAAO,aAClB,aAAG,WAAW,4BAA4B,MAAM,CAAC,GAAG,MAAM,YAAY,KAAK,IAAI,CAAC,IACnF,IACE;AAAA,MACH,MAAM,cAAc,gBAAAE,MAAC,OAAE,WAAWF,SAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SA/C1E,MAAM,EAgDf,CACD,GACH;AAAA,KACF;AAEJ;;;ACrFA,OAAOI,cAAY;AAUf,SAEI,OAAAC,OAFJ,QAAAC,cAAA;AAJG,SAAS,cAAc,EAAE,QAAQ,GAA0C;AAChF,QAAM,gBAAgB,QAAQ,UAAU,WAAW,QAAQ,UAAU;AAErE,SACE,gBAAAA,OAAC,YAAO,WAAWF,SAAO,QACvB;AAAA,YAAQ,SACP,gBAAAC;AAAA,MAAC;AAAA;AAAA,QACC,WAAWD,SAAO;AAAA,QAClB,KAAK,QAAQ,OAAO;AAAA,QACpB,KAAK,QAAQ,OAAO,OAAO;AAAA,QAC3B,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAQ;AAAA,QACR,UAAS;AAAA;AAAA,IACX,IACE;AAAA,IACJ,gBAAAC,MAAC,QAAG,WAAWD,SAAO,aAAc,kBAAQ,aAAY;AAAA,IACvD,QAAQ,UAAU,gBAAAC,MAAC,OAAE,WAAWD,SAAO,SAAU,kBAAQ,SAAQ,IAAO;AAAA,IACxE,gBAAgB,gBAAAC,MAAC,OAAE,WAAWD,SAAO,UAAW,yBAAc,IAAO;AAAA,IACrE,QAAQ,MAAM,gBAAAC,MAAC,OAAE,WAAWD,SAAO,KAAM,kBAAQ,KAAI,IAAO;AAAA,KAC/D;AAEJ;;;ACzBA,OAAOG,cAAY;AA2Bb,gBAAAC,OAyBQ,QAAAC,cAzBR;AApBN,SAAS,aAAa,UAAkD;AACtE,SAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM;AAClC,UAAM,eAAe,EAAE,cAAc,IAAI;AACzC,UAAM,eAAe,EAAE,cAAc,IAAI;AACzC,QAAI,iBAAiB,aAAc,QAAO,eAAe;AACzD,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,WAAO,SAAS;AAAA,EAClB,CAAC;AACH;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,SAAS;AACX,GAAgD;AAC9C,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,UAAU,aAAa,QAAQ;AAErC,SACE,gBAAAA,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,4BAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,4BAA2B,WAAWD,SAAO,SACjD,qBAAW,oBAAoB,MAAM,GACxC;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,YACZ,gBAAAE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAWF,SAAO;AAAA,QAClB,oBAAkB,QAAQ,cAAc,SAAS;AAAA,QAEjD;AAAA,0BAAAC,MAAC,OAAE,WAAWD,SAAO,OAClB,kBAAQ,MACP,gBAAAC;AAAA,YAAC;AAAA;AAAA,cACC,WAAWD,SAAO;AAAA,cAClB,MAAM,QAAQ;AAAA,cACd,QAAO;AAAA,cACP,KAAI;AAAA,cAEH,kBAAQ;AAAA;AAAA,UACX,IAEA,QAAQ,OAEZ;AAAA,UACC,QAAQ,cAAc,SACrB,gBAAAE,OAAC,OAAE,WAAWF,SAAO,OACnB;AAAA,4BAAAC,MAAC,UAAK,UAAU,QAAQ,WACrB,0BAAgB,QAAQ,WAAW,MAAM,GAC5C;AAAA,YACC;AAAA,YACA,QAAQ,UACP,gBAAAA,MAAC,UAAK,UAAU,QAAQ,SAAU,0BAAgB,QAAQ,SAAS,MAAM,GAAE,IAE3E,WAAW,oBAAoB,MAAM;AAAA,aAEzC,IACE;AAAA,UACH,QAAQ,cACP,gBAAAA,MAAC,OAAE,WAAWD,SAAO,aAAc,kBAAQ,aAAY,IACrD;AAAA,UACH,QAAQ,QAAQ,QAAQ,KAAK,SAAS,IACrC,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MAAM,cAAY,WAAW,aAAa,MAAM,GACnE,kBAAQ,KAAK,IAAI,CAAC,QACjB,gBAAAC,MAAC,QAAa,WAAWD,SAAO,KAC7B,iBADM,GAET,CACD,GACH,IACE;AAAA;AAAA;AAAA,MA1CC,QAAQ;AAAA,IA2Cf,CACD,GACH;AAAA,KACF;AAEJ;;;ACjFA,OAAOG,cAAY;AAgCb,gBAAAC,OAKI,QAAAC,cALJ;AAzBN,SAAS,iBAAiB,SAAyD;AACjF,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AACH;AAKA,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,QAAQ,oCAAoC,EAAE;AAC3D;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,SAAS;AACX,GAAgD;AAC9C,MAAI,aAAa,WAAW,EAAG,QAAO;AACtC,QAAM,UAAU,iBAAiB,YAAY;AAE7C,SACE,gBAAAA,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,gCAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,gCAA+B,WAAWD,SAAO,SACrD,qBAAW,wBAAwB,MAAM,GAC5C;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,OAAC,QAAkB,WAAWF,SAAO,MACnC;AAAA,sBAAAC,MAAC,OAAE,WAAWD,SAAO,OAClB,gBAAM,MACL,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWD,SAAO;AAAA,UAClB,MAAM,MAAM;AAAA,UACZ,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,gBAAM;AAAA;AAAA,MACT,IAEA,MAAM,OAEV;AAAA,MACC,MAAM,YAAY,gBAAAC,MAAC,OAAE,WAAWD,SAAO,WAAY,gBAAM,WAAU,IAAO;AAAA,MAC3E,gBAAAC,MAAC,OAAE,WAAWD,SAAO,MACnB,0BAAAC,MAAC,UAAK,UAAU,MAAM,MAAO,0BAAgB,MAAM,MAAM,MAAM,GAAE,GACnE;AAAA,MACC,MAAM,aAAa,MAAM,UAAU,SAAS,IAC3C,gBAAAA,MAAC,OAAE,WAAWD,SAAO,WAClB,aAAG,WAAW,+BAA+B,MAAM,CAAC,GAAG,MAAM,UAAU,KAAK,IAAI,CAAC,IACpF,IACE;AAAA,MACH,MAAM,OACF,MAAM;AACL,cAAM,OAAO,aAAa,MAAM,GAAG;AACnC,eACE,gBAAAC,MAAC,OAAE,WAAWD,SAAO,KACnB,0BAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAWD,SAAO;AAAA,YAClB,MAAM,mBAAmB,IAAI;AAAA,YAC7B,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,iBAAO,IAAI;AAAA;AAAA,QACd,GACF;AAAA,MAEJ,GAAG,IACH;AAAA,MACH,MAAM,cAAc,gBAAAC,MAAC,OAAE,WAAWD,SAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SAzC1E,MAAM,EA0Cf,CACD,GACH;AAAA,KACF;AAEJ;;;ACpFA,OAAOG,cAAY;AAyBb,gBAAAC,OASM,QAAAC,cATN;AAlBN,SAAS,oBAAoB,SAA+D;AAC1F,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,YAAQ,EAAE,QAAQ,IAAI,cAAc,EAAE,QAAQ,EAAE;AAAA,EAClD,CAAC;AACH;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,SAAS;AACX,GAAmD;AACjD,MAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,QAAM,UAAU,oBAAoB,eAAe;AAEnD,SACE,gBAAAA,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,mCAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,mCAAkC,WAAWD,SAAO,SACxD,qBAAW,2BAA2B,MAAM,GAC/C;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,OAAC,QAAkB,WAAWF,SAAO,MACnC;AAAA,sBAAAC,MAAC,gBAAW,WAAWD,SAAO,MAC5B,0BAAAC,MAAC,OAAE,WAAWD,SAAO,OAAQ,gBAAM,MAAK,GAC1C;AAAA,MACA,gBAAAE,OAAC,OAAE,WAAWF,SAAO,aACnB;AAAA,wBAAAC,MAAC,UAAK,WAAWD,SAAO,QACrB,gBAAM,OAAO,MACZ,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAWD,SAAO;AAAA,YAClB,MAAM,MAAM,OAAO;AAAA,YACnB,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,gBAAM,OAAO;AAAA;AAAA,QAChB,IAEA,MAAM,OAAO,MAEjB;AAAA,QACC,MAAM,OAAO,WACZ,gBAAAC,MAAC,UAAK,WAAWD,SAAO,UAAW,gBAAM,OAAO,UAAS,IACvD;AAAA,SACN;AAAA,MACC,MAAM,eAAe,gBAAAC,MAAC,OAAE,WAAWD,SAAO,MAAO,gBAAM,cAAa,IAAO;AAAA,MAC3E,MAAM,OACL,gBAAAC,MAAC,OAAE,WAAWD,SAAO,MACnB,0BAAAC,MAAC,UAAK,UAAU,MAAM,MAAO,0BAAgB,MAAM,MAAM,MAAM,GAAE,GACnE,IACE;AAAA,SA5BG,MAAM,EA6Bf,CACD,GACH;AAAA,KACF;AAEJ;;;ACjEA,OAAOE,cAAY;AAwCb,gBAAAC,OAYM,QAAAC,cAZN;AA3BN,IAAM,gBAAgB;AAEtB,SAAS,YAAY,QAA+B;AAClD,QAAM,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AACxC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,WAAO,SAAS;AAAA,EAClB,CAAC;AACD,QAAM,SAAS,oBAAI,IAAqB;AACxC,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,MAAM,YAAY;AAC9B,UAAM,SAAS,OAAO,IAAI,GAAG;AAC7B,QAAI,QAAQ;AACV,aAAO,KAAK,KAAK;AAAA,IACnB,OAAO;AACL,aAAO,IAAI,KAAK,CAAC,KAAK,CAAC;AAAA,IACzB;AAAA,EACF;AACA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,UAAU,KAAK,OAAO,EAAE,UAAU,QAAQ,MAAM,EAAE;AACvF;AAEO,SAAS,WAAW,EAAE,QAAQ,SAAS,KAAK,GAA8C;AAC/F,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,SAAS,YAAY,MAAM;AAEjC,SACE,gBAAAA,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,0BAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,0BAAyB,WAAWD,SAAO,SAC/C,qBAAW,kBAAkB,MAAM,GACtC;AAAA,IACA,gBAAAC,MAAC,SAAI,WAAWD,SAAO,QACpB,iBAAO,IAAI,CAAC,UAAU;AAGrB,YAAM,gBACJ,MAAM,aAAa,gBACf,WAAW,wBAAwB,MAAM,IACzC,MAAM;AACZ,aACE,gBAAAE,OAAC,SAAyB,WAAWF,SAAO,OAC1C;AAAA,wBAAAC,MAAC,QAAG,WAAWD,SAAO,UAAW,yBAAc;AAAA,QAC/C,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAWD,SAAO;AAAA,YAClB,cAAY,GAAG,aAAa,IAAI,WAAW,qBAAqB,MAAM,CAAC;AAAA,YAEtE,gBAAM,OAAO,IAAI,CAAC,UACjB,gBAAAC,MAAC,QAAkB,WAAWD,SAAO,MAClC,gBAAM,SADA,MAAM,EAEf,CACD;AAAA;AAAA,QACH;AAAA,WAXQ,MAAM,QAYhB;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;;;AnBrDA,OAAOG,cAAY;;;AoBhBnB,OAAOC,cAAY;AAyBb,gBAAAC,OAoBM,QAAAC,cApBN;AAlBN,SAAS,eAAe,SAAqD;AAC3E,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,EACpC,CAAC;AACH;AAEO,SAAS,WAAW;AAAA,EACzB;AAAA,EACA,SAAS;AACX,GAA8C;AAC5C,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,QAAM,UAAU,eAAe,UAAU;AAEzC,SACE,gBAAAA,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,+BAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,+BAA8B,WAAWD,SAAO,SACpD,qBAAW,sBAAsB,MAAM,GAC1C;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,OAAC,QAAkB,WAAWF,SAAO,MACnC;AAAA,sBAAAC,MAAC,OAAE,WAAWD,SAAO,OAClB,gBAAM,MACL,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWD,SAAO;AAAA,UAClB,MAAM,MAAM;AAAA,UACZ,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,gBAAM;AAAA;AAAA,MACT,IAEA,MAAM,OAEV;AAAA,MACA,gBAAAE,OAAC,OAAE,WAAWF,SAAO,MACnB;AAAA,wBAAAC,MAAC,UAAK,WAAWD,SAAO,OAAQ,gBAAM,OAAM;AAAA,QAC3C;AAAA,QACD,gBAAAC,MAAC,UAAK,UAAU,MAAM,MAAO,0BAAgB,MAAM,MAAM,MAAM,GAAE;AAAA,SACnE;AAAA,MACC,MAAM,cAAc,gBAAAA,MAAC,OAAE,WAAWD,SAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SApB1E,MAAM,EAqBf,CACD,GACH;AAAA,KACF;AAEJ;;;ACxDA,OAAOG,cAAY;AA6Bb,gBAAAC,OAyBY,QAAAC,cAzBZ;AAtBN,SAAS,iBAAiB,SAA2D;AACnF,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,UAAM,SAAS,EAAE,SAAS,OAAO;AACjC,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,UAAU,cAAc,EAAE,SAAS;AAAA,EAC9C,CAAC;AACH;AAEA,SAASC,WAAU,OAAuC;AACxD,SAAO,MAAM,cAAc,QAAQ,MAAM,YAAY,QAAQ,MAAM,YAAY;AACjF;AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,SAAS;AACX,GAAgD;AAC9C,MAAI,aAAa,WAAW,EAAG,QAAO;AACtC,QAAM,UAAU,iBAAiB,YAAY;AAE7C,SACE,gBAAAD,OAAC,aAAQ,WAAWF,SAAO,SAAS,mBAAgB,gCAClD;AAAA,oBAAAC,MAAC,QAAG,IAAG,gCAA+B,WAAWD,SAAO,SACrD,qBAAW,wBAAwB,MAAM,GAC5C;AAAA,IACA,gBAAAC,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,UACZ,gBAAAE,OAAC,QAAkB,WAAWF,SAAO,MACnC;AAAA,sBAAAC,MAAC,SAAI,WAAWD,SAAO,gBAAgB,eAAY,QAAO;AAAA,MAC1D,gBAAAE,OAAC,SAAI,WAAWF,SAAO,SACrB;AAAA,wBAAAC,MAAC,OAAE,WAAWD,SAAO,cAClB,gBAAM,MACL,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACC,WAAWD,SAAO;AAAA,YAClB,MAAM,MAAM;AAAA,YACZ,QAAO;AAAA,YACP,KAAI;AAAA,YAEH,gBAAM;AAAA;AAAA,QACT,IAEA,MAAM,cAEV;AAAA,QACA,gBAAAE,OAAC,OAAE,WAAWF,SAAO,MAClB;AAAA,gBAAM;AAAA,UACN,MAAM,QACL,gBAAAE,OAAC,UAAK,WAAWF,SAAO,OACtB;AAAA,4BAAAC,MAAC,UAAK,WAAWD,SAAO,QAAS,qBAAW,oBAAoB,MAAM,GAAE;AAAA,YACvE,MAAM;AAAA,aACT,IACE;AAAA,WACN;AAAA,QACA,gBAAAE,OAAC,OAAE,WAAWF,SAAO,OACnB;AAAA,0BAAAC,MAAC,UAAK,UAAU,MAAM,WAAY,0BAAgB,MAAM,WAAW,MAAM,GAAE;AAAA,UAC1E;AAAA,UACAE,WAAU,KAAK,IACd,WAAW,oBAAoB,MAAM,IAErC,gBAAAF,MAAC,UAAK,UAAU,MAAM,SAAW,0BAAgB,MAAM,SAAU,MAAM,GAAE;AAAA,WAE7E;AAAA,QACC,MAAM,cAAc,gBAAAA,MAAC,OAAE,WAAWD,SAAO,aAAc,gBAAM,aAAY,IAAO;AAAA,SACnF;AAAA,SApCO,MAAM,EAqCf,CACD,GACH;AAAA,KACF;AAEJ;;;ArBtCI,SACE,OAAAI,OADF,QAAAC,cAAA;AANG,SAAS,eAAe,EAAE,MAAM,iBAAiB,GAA2C;AACjG,QAAM,aAAa,KAAK,SAAS,kBAAkB;AACnD,QAAM,SAAS,KAAK;AACpB,QAAM,WAAW,KAAK,SAAS,UAAU,YAAY,OAAO,mBAAmB;AAE/E,SACE,gBAAAA,OAAC,aAAQ,WAAWC,SAAO,MACzB;AAAA,oBAAAF,MAAC,iBAAc,SAAS,KAAK,SAAS;AAAA,IACtC,gBAAAA,MAAC,aAAU,OAAO,KAAK,OAAO,QAAgB;AAAA,IAC9C,gBAAAA,MAAC,qBAAkB,WAAW,KAAK,WAAW,QAAgB;AAAA,IAC9D,gBAAAA,MAAC,WAAQ,SAAS,KAAK,SAAS,QAAgB;AAAA,IAChD,gBAAAA,MAAC,kBAAe,SAAS,KAAK,SAAS,QAAgB;AAAA,IACvD,gBAAAA,MAAC,eAAY,aAAa,KAAK,aAAa,QAAgB;AAAA,IAC5D,gBAAAA,MAAC,kBAAe,gBAAgB,KAAK,gBAAgB,QAAgB;AAAA,IACrE,gBAAAA,MAAC,WAAQ,SAAS,KAAK,SAAS,QAAgB;AAAA,IAChD,gBAAAA,MAAC,gBAAa,UAAU,KAAK,UAAU,QAAgB;AAAA,IACvD,gBAAAA,MAAC,gBAAa,cAAc,KAAK,cAAc,QAAgB;AAAA,IAC/D,gBAAAA,MAAC,cAAW,QAAQ,KAAK,QAAQ,QAAgB;AAAA,IACjD,gBAAAA,MAAC,mBAAgB,iBAAiB,KAAK,iBAAiB,QAAgB;AAAA,IACxE,gBAAAA,MAAC,gBAAa,cAAc,KAAK,cAAc,QAAgB;AAAA,IAC/D,gBAAAA,MAAC,cAAW,QAAQ,KAAK,QAAQ,QAAgB;AAAA,IACjD,gBAAAA,MAAC,mBAAgB,UAAU,UAAU,QAAgB;AAAA,IACrD,gBAAAA,MAAC,aAAU,WAAW,KAAK,WAAW,QAAgB;AAAA,IACtD,gBAAAA,MAAC,cAAW,YAAY,KAAK,YAAY,QAAgB;AAAA,IACzD,gBAAAA,MAAC,eAAY,SAAS,KAAK,SAAS,QAAgB;AAAA,IACnD,aAAa,gBAAAA,MAAC,UAAO,IAAK;AAAA,KAC7B;AAEJ;;;AsB5DA,OAAOG,cAAY;AA8CT,SAE2B,OAAAC,OAF3B,QAAAC,cAAA;AApCV,IAAM,gBAAuD;AAAA,EAC3D,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AACf;AAYA,SAAS,aAAa,QAAgC,WAAuC;AAC3F,QAAM,SAAS,OACZ,OAAO,CAAC,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS,CAAC,EAChE,KAAK,SAAS;AACjB,SAAO,OAAO,SAAS,IAAI,SAAS;AACtC;AAEA,SAAS,UAAU,EAAE,QAAQ,GAAgD;AAC3E,SACE,gBAAAD,MAAC,QAAG,WAAWD,SAAO,MACnB,kBAAQ,IAAI,CAAC,MACZ,gBAAAE,OAAC,QAAe,WAAWF,SAAO,OAChC;AAAA,oBAAAE,OAAC,SAAI,WAAWF,SAAO,KACrB;AAAA,sBAAAC,MAAC,QAAG,WAAWD,SAAO,cACnB,YAAE,QAAQ,SAAY,gBAAAC,MAAC,OAAE,MAAM,EAAE,KAAM,YAAE,SAAQ,IAAO,EAAE,SAC7D;AAAA,MACC,EAAE,UAAU,SAAY,gBAAAA,MAAC,UAAK,WAAWD,SAAO,OAAQ,YAAE,OAAM,IAAU;AAAA,OAC7E;AAAA,IACC,EAAE,QAAQ,SAAY,gBAAAC,MAAC,OAAE,WAAWD,SAAO,KAAM,YAAE,KAAI,IAAO;AAAA,IAC9D,EAAE,SAAS,SAAY,gBAAAC,MAAC,OAAE,WAAWD,SAAO,MAAO,YAAE,MAAK,IAAO;AAAA,OAR3D,EAAE,GASX,CACD,GACH;AAEJ;AAEA,SAAS,SAAS,EAAE,OAAO,GAA4C;AACrE,SACE,gBAAAC,MAAC,QAAG,WAAWD,SAAO,OACnB,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAC,MAAC,QAAiC,WAAWD,SAAO,MACjD,mBADM,GAAG,KAAK,IAAI,OAAO,CAAC,CAAC,EAE9B,CACD,GACH;AAEJ;AAGA,SAAS,MACP,QACA,OACA,KACA,WACoB;AACpB,QAAM,OAAO,QAAQ,gBAAgB,OAAO,MAAM,IAAI;AACtD,QAAM,UAAU,cAAc,QAAQ,QAAQ;AAC9C,QAAM,QAAQ,UACV,WAAW,oBAAoB,MAAM,IACrC,MACE,gBAAgB,KAAK,MAAM,IAC3B;AACN,QAAM,OAAO,QAAQ,QAAQ,GAAG,IAAI,WAAM,KAAK,KAAK,QAAQ;AAC5D,SAAO,QAAQ;AACjB;AAEA,SAAS,cAAc,GAAsB,QAA2B;AACtE,QAAM,OAAO,EAAE,eAAe,EAAE;AAChC,SAAO,GAAG,IAAI,WAAM,WAAW,eAAe,EAAE,WAAW,IAAI,MAAM,CAAC;AACxE;AAGA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGsB;AACpB,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aACE,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,EAAE;AAAA,YACP,OAAO,MAAM,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;AAAA,YACxD,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAClC,kBAAM,SAAS,aAAa,CAAC,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI;AAC5D,mBAAO;AAAA,cACL,KAAK,EAAE;AAAA,cACP,SAAS,UAAU,EAAE;AAAA,cACrB,KAAK,SAAS,EAAE,cAAc;AAAA,cAC9B,OAAO,MAAM,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;AAAA,cACxD,MAAM,EAAE;AAAA,cACR,KAAK,EAAE;AAAA,YACT;AAAA,UACF,CAAC;AAAA;AAAA,MACH;AAAA,IAEJ,KAAK;AACH,aAAO,gBAAAA,MAAC,YAAS,QAAQ,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG;AAAA,IAChE,KAAK;AACH,aAAO,gBAAAA,MAAC,YAAS,QAAQ,QAAQ,QAAQ,IAAI,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG;AAAA,IACjF,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,EAAE;AAAA,YACP,OAAO,MAAM,QAAQ,EAAE,WAAW,EAAE,cAAc;AAAA,YAClD,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,aAAa,CAAC,EAAE,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,QAAK;AAAA,YAC/D,OAAO,MAAM,QAAQ,EAAE,IAAI;AAAA,YAC3B,MAAM,EAAE;AAAA,YACR,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,EAAE,GAAG,KAAK;AAAA,UACtD,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,EAAE;AAAA,YACP,OAAO,MAAM,QAAQ,EAAE,IAAI;AAAA,YAC3B,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,EAAE;AAAA,YACP,OAAO,MAAM,QAAQ,EAAE,cAAc;AAAA,YACrC,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,aAAa,CAAC,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,QAAK;AAAA,YAC7D,OAAO,MAAM,QAAQ,EAAE,cAAc,EAAE,SAAS;AAAA,YAChD,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE;AAAA,YACX,KAAK,aAAa,CAAC,EAAE,cAAc,EAAE,KAAK,GAAG,QAAK;AAAA,YAClD,OAAO,MAAM,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;AAAA,YACxD,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,IAEJ,KAAK;AACH,aACE,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAS,QAAQ,QAAQ,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,SAAS,EAAE,QAAQ,EAAE;AAAA,YACrB,KAAK,EAAE,OAAO,EAAE,eAAe;AAAA,YAC/B,OAAO,MAAM,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS;AAAA,YACxD,MAAM,EAAE;AAAA,YACR,KAAK,EAAE;AAAA,UACT,EAAE;AAAA;AAAA,MACJ;AAAA,EAEN;AACF;AAUO,SAAS,OAAO,EAAE,IAAI,OAAO,GAA0C;AAC5E,QAAM,MAAM,UAAU,GAAG;AACzB,QAAM,IAAI,GAAG;AACb,MAAI,GAAG,SAAS,WAAW,KAAK,EAAE,gBAAgB,GAAI,QAAO;AAE7D,QAAM,UAA+B,CAAC;AACtC,MAAI,EAAE,aAAa,OAAW,SAAQ,KAAK,gBAAAA,MAAC,UAAgB,YAAE,YAAT,KAAkB,CAAO;AAC9E,MAAI,EAAE,UAAU,QAAW;AACzB,YAAQ;AAAA,MACN,gBAAAA,MAAC,OAAc,MAAM,UAAU,EAAE,KAAK,IACnC,YAAE,SADE,OAEP;AAAA,IACF;AAAA,EACF;AACA,MAAI,EAAE,YAAY,QAAW;AAC3B,YAAQ;AAAA,MACN,gBAAAA,MAAC,OAAa,MAAM,EAAE,SACnB,qBAAW,oBAAoB,GAAG,KAD9B,MAEP;AAAA,IACF;AAAA,EACF;AAEA,SACE,gBAAAC,OAAC,aAAQ,WAAWF,SAAO,IAAI,MAAM,KACnC;AAAA,oBAAAE,OAAC,YAAO,WAAWF,SAAO,QACxB;AAAA,sBAAAC,MAAC,QAAG,WAAWD,SAAO,MAAO,YAAE,aAAY;AAAA,MAC1C,EAAE,YAAY,SAAY,gBAAAC,MAAC,OAAE,WAAWD,SAAO,SAAU,YAAE,SAAQ,IAAO;AAAA,MAC1E,QAAQ,SAAS,IAAI,gBAAAC,MAAC,SAAI,WAAWD,SAAO,SAAU,mBAAQ,IAAS;AAAA,MACvE,EAAE,QAAQ,SAAY,gBAAAC,MAAC,OAAE,WAAWD,SAAO,KAAM,YAAE,KAAI,IAAO;AAAA,OACjE;AAAA,IACC,GAAG,SAAS,IAAI,CAAC,YAChB,gBAAAE,OAAC,aAA2B,WAAWF,SAAO,SAC5C;AAAA,sBAAAC,MAAC,QAAG,WAAWD,SAAO,SAAU,qBAAW,cAAc,QAAQ,IAAI,GAAG,GAAG,GAAE;AAAA,MAC7E,gBAAAC,MAAC,eAAY,SAAkB,QAAQ,KAAK;AAAA,SAFhC,QAAQ,IAGtB,CACD;AAAA,KACH;AAEJ;;;ACrRA,OAAOE,cAAY;AA8BT,gBAAAC,aAAA;AApBH,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,QAAQ,aAAa,WAAW,uBAAuB,aAAa;AAC1E,QAAM,SAAS,iBAAiB,CAAC,WAAsB;AACvD,SACE,gBAAAA,MAAC,SAAI,WAAWD,SAAO,SACrB,0BAAAC;AAAA,IAAC;AAAA;AAAA,MACC,WAAWD,SAAO;AAAA,MAClB,cAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAU,CAAC,UAAU;AACnB,iBAAS,MAAM,OAAO,KAAK;AAAA,MAC7B;AAAA,MAEC,2BAAiB,IAAI,CAAC,WACrB,gBAAAC,MAAC,YAAoB,OAAO,QACzB,iBAAO,MAAM,KADH,MAEb,CACD;AAAA;AAAA,EACH,GACF;AAEJ;;;ACzCA,SAAS,sBAA6C;AACtD,SAAS,iBAAiB;AAmJtB,qBAAAC,WACE,OAAAC,OADF,QAAAC,cAAA;AA3IJ,SAAS,cAAc,KAAqB;AAC1C,QAAM,OAAO,IAAI,QAAQ,GAAG;AAC5B,UAAQ,SAAS,KAAK,MAAM,IAAI,MAAM,GAAG,IAAI,GAAG,YAAY;AAC9D;AAQA,SAAS,gBAAgB,SAAiB,kBAA8C;AACtF,QAAM,QAAQ,QAAQ,YAAY;AAClC,QAAM,UAAU,cAAc,OAAO;AACrC,SAAO,iBAAiB;AAAA,IACtB,CAAC,QAAQ,IAAI,YAAY,MAAM,SAAS,cAAc,GAAG,MAAM;AAAA,EACjE;AACF;AAUA,SAAS,iBAAiB,SAAiB,kBAA6C;AACtF,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAI,aAAa,OAAO,MAAM;AAC9B,UAAM,WAAW,IAAI,SAAS,MAAM,GAAG;AACvC,UAAM,QAAQ,SAAS,CAAC;AACxB,QAAI,UAAU,UAAa,UAAU,MAAM,gBAAgB,OAAO,gBAAgB,GAAG;AACnF,eAAS,OAAO,GAAG,CAAC;AACpB,UAAI,WAAW,SAAS,KAAK,GAAG,KAAK;AAAA,IACvC;AACA,WAAO,IAAI,SAAS;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAgBA,SAAS,iBAAiB,YAAoB,QAAwB;AACpE,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,UAAU;AAC9B,QAAI,WAAW,IAAI,aAAa,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,GAAG,IAAI,QAAQ;AAC/E,WAAO,IAAI,SAAS;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAAyB,MAA8C;AAC5F,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI;AACF,WAAO,IAAI,IAAI,KAAK,IAAI,EAAE,SAAS;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,UAAkD;AACvE,MAAI,SAAU,QAAO;AACrB,MAAI,OAAO,WAAW,YAAa,QAAO,OAAO,SAAS;AAC1D,SAAO;AACT;AAEA,SAAS,cACP,UACA,SACoB;AACpB,MAAI,SAAU,QAAO;AACrB,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,SAAS,SAAS,OAAO,SAAS;AAAA,EAClD;AACA,SAAO;AACT;AAEO,SAAS,YAAY,EAAE,MAAM,SAAS,QAAQ,GAAwC;AAC3F,QAAM,kBAAkB,cAAc,OAAO;AAC7C,QAAM,kBAAkB,cAAc,SAAS,eAAe;AAE9D,QAAM,EAAE,SAAS,UAAU,eAAe,IAAI;AAC9C,QAAM,cAAc,QAAQ,OAAO,QAAQ;AAC3C,QAAM,gBAAgB,QAAQ,WAAW,QAAQ;AACjD,QAAM,UAAU,cAAc,QAAQ,QAAQ,KAAK,eAAe;AAClE,QAAM,cAAc,QAAQ,SAAS,wBAAwB;AAK7D,QAAM,iBAAiB,kBACnB,iBAAiB,iBAAiB,SAAS,gBAAgB,IAC3D;AAEJ,QAAM,YAAY,iBAAiB,iBAAiB,gBAAgB,cAAc,IAAI;AACtF,QAAM,aAAa,iBACf,SAAS,iBAAiB,IAAI,CAAC,SAAS;AAAA,IACtC,QAAQ;AAAA,IACR,MAAM,iBAAiB,gBAAgB,GAAG;AAAA,EAC5C,EAAE,IACF,CAAC;AACL,QAAM,eAAe,iBACjB,iBAAiB,gBAAgB,SAAS,aAAa,IACvD;AAEJ,QAAM,eAAe,SAAS,iBAAiB,OAAO,CAAC,QAAQ,QAAQ,cAAc;AAErF,QAAM,aAAa,SAAS,iBAAiB;AAC7C,QAAM,gBAAgB,aAAa,KAAK,UAAU,eAAe,IAAI,CAAC,IAAI;AAE1E,YAAU,MAAM;AACd,QAAI,CAAC,cAAe;AACpB,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,OAAO;AACd,WAAO,cAAc;AACrB,aAAS,KAAK,YAAY,MAAM;AAChC,WAAO,MAAM;AACX,aAAO,OAAO;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,SACE,gBAAAA,OAAAF,WAAA,EACE;AAAA,oBAAAC,MAAC,WAAO,kBAAQ,aAAY;AAAA,IAC3B,cAAc,gBAAAA,MAAC,UAAK,MAAK,eAAc,SAAS,aAAa,IAAK;AAAA,IAClE,YAAY,gBAAAA,MAAC,UAAK,KAAI,aAAY,MAAM,WAAW,IAAK;AAAA,IAEzD,gBAAAA,MAAC,UAAK,UAAS,YAAW,SAAS,QAAQ,aAAa;AAAA,IACvD,gBAAgB,gBAAAA,MAAC,UAAK,UAAS,kBAAiB,SAAS,eAAe,IAAK;AAAA,IAC7E,YAAY,gBAAAA,MAAC,UAAK,UAAS,UAAS,SAAS,WAAW,IAAK;AAAA,IAC7D,UAAU,gBAAAA,MAAC,UAAK,UAAS,YAAW,SAAS,SAAS,IAAK;AAAA,IAC5D,gBAAAA,MAAC,UAAK,UAAS,WAAU,SAAQ,WAAU;AAAA,IAC3C,gBAAAA,MAAC,UAAK,UAAS,aAAY,SAAS,gBAAgB;AAAA,IACnD,aAAa,IAAI,CAAC,QACjB,gBAAAA,MAAC,UAAe,UAAS,uBAAsB,SAAS,OAA7C,GAAkD,CAC9D;AAAA,IAED,gBAAAA,MAAC,UAAK,MAAK,gBAAe,SAAS,aAAa;AAAA,IAE/C,WAAW,IAAI,CAAC,EAAE,QAAQ,KAAK,MAC9B,gBAAAA,MAAC,UAAkB,KAAI,aAAY,UAAU,QAAQ,QAA1C,MAAsD,CAClE;AAAA,IACA,eAAe,gBAAAA,MAAC,UAAK,KAAI,aAAY,UAAS,aAAY,MAAM,cAAc,IAAK;AAAA,KACtF;AAEJ;","names":["styles","jsx","jsxs","styles","Fragment","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","styles","Fragment","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","jsx","jsxs","styles","styles","jsx","jsxs","styles","jsx","jsxs","isOngoing","jsx","jsxs","styles","styles","jsx","jsxs","styles","jsx","Fragment","jsx","jsxs"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takuhon/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "React mobile-first profile UI and minimal admin editor components for takuhon",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Takuhon contributors",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"node": ">=22.0.0"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@takuhon/core": "0.
|
|
50
|
+
"@takuhon/core": "0.13.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=19",
|