profile-pane 3.1.5 → 3.2.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.
Files changed (311) hide show
  1. package/README.md +16 -0
  2. package/lib/04567ff683933c35c465.png +0 -0
  3. package/lib/10163fd9b5a0e00d63a0.png +0 -0
  4. package/lib/1234dcb2eec2e45f252b.png +0 -0
  5. package/lib/20899934157df4db56cb.png +0 -0
  6. package/lib/33760bf79f097f449da5.png +0 -0
  7. package/lib/578d2b6ed32e7624164e.png +0 -0
  8. package/lib/5f62a5b2b7e99b9640c7.png +0 -0
  9. package/lib/6525766ecd288ec60129.png +0 -0
  10. package/lib/7800be6f6c4b5b0f4f20.png +0 -0
  11. package/lib/976473cf5fe24d657d4b.png +0 -0
  12. package/lib/ChatWithMe.d.ts +2 -1
  13. package/lib/ChatWithMe.d.ts.map +1 -1
  14. package/lib/ChatWithMe.js +3 -3
  15. package/lib/ProfileView.d.ts +1 -1
  16. package/lib/ProfileView.d.ts.map +1 -1
  17. package/lib/ProfileView.js +71 -131
  18. package/lib/ProfileViewModelPresenter.d.ts +23 -0
  19. package/lib/ProfileViewModelPresenter.d.ts.map +1 -0
  20. package/lib/ProfileViewModelPresenter.js +37 -0
  21. package/lib/QRCodeCard.d.ts +3 -1
  22. package/lib/QRCodeCard.d.ts.map +1 -1
  23. package/lib/QRCodeCard.js +86 -66
  24. package/lib/addMeToYourFriends.d.ts +3 -3
  25. package/lib/addMeToYourFriends.d.ts.map +1 -1
  26. package/lib/addMeToYourFriends.js +14 -30
  27. package/lib/bda84f59e7216675a208.png +0 -0
  28. package/lib/buttonsHelper.js +1 -1
  29. package/lib/cd68e8f3990ba8b2139e.png +0 -0
  30. package/lib/e7074a7e2cb69e51cfd3.png +0 -0
  31. package/lib/editProfilePane/EditCVCard.d.ts +1 -0
  32. package/lib/editProfilePane/EditCVCard.d.ts.map +1 -1
  33. package/lib/editProfilePane/EditCVCard.js +2 -1
  34. package/lib/editProfilePane/EditCommunitiesCard.d.ts +1 -1
  35. package/lib/editProfilePane/EditCommunitiesCard.d.ts.map +1 -1
  36. package/lib/editProfilePane/EditCommunitiesCard.js +2 -1
  37. package/lib/editProfilePane/EditContactsCard.d.ts +1 -0
  38. package/lib/editProfilePane/EditContactsCard.d.ts.map +1 -1
  39. package/lib/editProfilePane/EditContactsCard.js +2 -0
  40. package/lib/editProfilePane/EditFriendsCard.d.ts +1 -1
  41. package/lib/editProfilePane/EditFriendsCard.d.ts.map +1 -1
  42. package/lib/editProfilePane/EditFriendsCard.js +2 -1
  43. package/lib/editProfilePane/EditOtherPreferences.d.ts +1 -0
  44. package/lib/editProfilePane/EditOtherPreferences.d.ts.map +1 -1
  45. package/lib/editProfilePane/EditOtherPreferences.js +1 -0
  46. package/lib/editProfilePane/EditProfileView.d.ts +1 -1
  47. package/lib/editProfilePane/EditProfileView.d.ts.map +1 -1
  48. package/lib/editProfilePane/EditProfileView.js +1 -1
  49. package/lib/editProfilePane/EditSocialCard.d.ts +1 -0
  50. package/lib/editProfilePane/EditSocialCard.d.ts.map +1 -1
  51. package/lib/editProfilePane/EditSocialCard.js +2 -1
  52. package/lib/editProfilePane/editProfilePresenter.d.ts +1 -0
  53. package/lib/editProfilePane/editProfilePresenter.d.ts.map +1 -1
  54. package/lib/editProfilePane/editProfilePresenter.js +2 -0
  55. package/lib/f3772696fb7ee53c23d8.png +0 -0
  56. package/lib/icons-svg/contactIcons.d.ts +3 -0
  57. package/lib/icons-svg/contactIcons.d.ts.map +1 -0
  58. package/lib/icons-svg/contactIcons.js +32 -0
  59. package/lib/icons-svg/profileIcons.d.ts +22 -0
  60. package/lib/icons-svg/profileIcons.d.ts.map +1 -0
  61. package/lib/icons-svg/profileIcons.js +309 -0
  62. package/lib/index.d.ts +1 -3
  63. package/lib/index.d.ts.map +1 -1
  64. package/lib/index.js +42 -19
  65. package/lib/profile-pane.js +15629 -5670
  66. package/lib/profile-pane.js.map +1 -1
  67. package/lib/profile-pane.min.js +2171 -230
  68. package/lib/profile-pane.min.js.map +1 -1
  69. package/lib/rdfFormsHelper.d.ts +1 -0
  70. package/lib/rdfFormsHelper.d.ts.map +1 -1
  71. package/lib/rdfFormsHelper.js +2 -0
  72. package/lib/sections/bio/BioEditDialog.d.ts +6 -0
  73. package/lib/sections/bio/BioEditDialog.d.ts.map +1 -0
  74. package/lib/sections/bio/BioEditDialog.js +119 -0
  75. package/lib/sections/bio/BioSection.d.ts +7 -0
  76. package/lib/sections/bio/BioSection.d.ts.map +1 -0
  77. package/lib/sections/bio/BioSection.js +131 -0
  78. package/lib/sections/bio/mutations.d.ts +4 -0
  79. package/lib/sections/bio/mutations.d.ts.map +1 -0
  80. package/lib/sections/bio/mutations.js +43 -0
  81. package/lib/sections/bio/selectors.d.ts +4 -0
  82. package/lib/sections/bio/selectors.d.ts.map +1 -0
  83. package/lib/sections/bio/selectors.js +15 -0
  84. package/lib/sections/bio/types.d.ts +15 -0
  85. package/lib/sections/bio/types.d.ts.map +1 -0
  86. package/lib/sections/bio/types.js +5 -0
  87. package/lib/sections/contactInfo/ContactInfoEditDialog.d.ts +7 -0
  88. package/lib/sections/contactInfo/ContactInfoEditDialog.d.ts.map +1 -0
  89. package/lib/sections/contactInfo/ContactInfoEditDialog.js +658 -0
  90. package/lib/sections/contactInfo/ContactInfoSection.d.ts +5 -0
  91. package/lib/sections/contactInfo/ContactInfoSection.d.ts.map +1 -0
  92. package/lib/sections/contactInfo/ContactInfoSection.js +229 -0
  93. package/lib/sections/contactInfo/mutations.d.ts +4 -0
  94. package/lib/sections/contactInfo/mutations.d.ts.map +1 -0
  95. package/lib/sections/contactInfo/mutations.js +150 -0
  96. package/lib/sections/contactInfo/selectors.d.ts +4 -0
  97. package/lib/sections/contactInfo/selectors.d.ts.map +1 -0
  98. package/lib/sections/contactInfo/selectors.js +104 -0
  99. package/lib/sections/contactInfo/types.d.ts +44 -0
  100. package/lib/sections/contactInfo/types.d.ts.map +1 -0
  101. package/lib/sections/contactInfo/types.js +5 -0
  102. package/lib/sections/education/EducationEditDialog.d.ts +7 -0
  103. package/lib/sections/education/EducationEditDialog.d.ts.map +1 -0
  104. package/lib/sections/education/EducationEditDialog.js +459 -0
  105. package/lib/sections/education/EducationSection.d.ts +7 -0
  106. package/lib/sections/education/EducationSection.d.ts.map +1 -0
  107. package/lib/sections/education/EducationSection.js +126 -0
  108. package/lib/sections/education/mutations.d.ts +4 -0
  109. package/lib/sections/education/mutations.d.ts.map +1 -0
  110. package/lib/sections/education/mutations.js +60 -0
  111. package/lib/sections/education/selectors.d.ts +4 -0
  112. package/lib/sections/education/selectors.d.ts.map +1 -0
  113. package/lib/sections/education/selectors.js +64 -0
  114. package/lib/sections/education/types.d.ts +20 -0
  115. package/lib/sections/education/types.d.ts.map +1 -0
  116. package/lib/sections/education/types.js +5 -0
  117. package/lib/sections/heading/HeadingEditDialog.d.ts +6 -0
  118. package/lib/sections/heading/HeadingEditDialog.d.ts.map +1 -0
  119. package/lib/sections/heading/HeadingEditDialog.js +742 -0
  120. package/lib/sections/heading/HeadingSection.d.ts +9 -0
  121. package/lib/sections/heading/HeadingSection.d.ts.map +1 -0
  122. package/lib/sections/heading/HeadingSection.js +97 -0
  123. package/lib/sections/heading/camera.d.ts +19 -0
  124. package/lib/sections/heading/camera.d.ts.map +1 -0
  125. package/lib/sections/heading/camera.js +199 -0
  126. package/lib/sections/heading/dateHelpers.d.ts +4 -0
  127. package/lib/sections/heading/dateHelpers.d.ts.map +1 -0
  128. package/lib/sections/heading/dateHelpers.js +48 -0
  129. package/lib/sections/heading/imageHelpers.d.ts +4 -0
  130. package/lib/sections/heading/imageHelpers.d.ts.map +1 -0
  131. package/lib/sections/heading/imageHelpers.js +81 -0
  132. package/lib/sections/heading/mutations.d.ts +4 -0
  133. package/lib/sections/heading/mutations.d.ts.map +1 -0
  134. package/lib/sections/heading/mutations.js +190 -0
  135. package/lib/sections/heading/selectors.d.ts +5 -0
  136. package/lib/sections/heading/selectors.d.ts.map +1 -0
  137. package/lib/sections/heading/selectors.js +157 -0
  138. package/lib/sections/heading/types.d.ts +36 -0
  139. package/lib/sections/heading/types.d.ts.map +1 -0
  140. package/lib/sections/heading/types.js +5 -0
  141. package/lib/sections/languages/LanguageEditDialog.d.ts +7 -0
  142. package/lib/sections/languages/LanguageEditDialog.d.ts.map +1 -0
  143. package/lib/sections/languages/LanguageEditDialog.js +457 -0
  144. package/lib/sections/languages/LanguageSection.d.ts +5 -0
  145. package/lib/sections/languages/LanguageSection.d.ts.map +1 -0
  146. package/lib/sections/languages/LanguageSection.js +137 -0
  147. package/lib/sections/languages/mutations.d.ts +6 -0
  148. package/lib/sections/languages/mutations.d.ts.map +1 -0
  149. package/lib/sections/languages/mutations.js +296 -0
  150. package/lib/sections/languages/selectors.d.ts +5 -0
  151. package/lib/sections/languages/selectors.d.ts.map +1 -0
  152. package/lib/sections/languages/selectors.js +146 -0
  153. package/lib/sections/languages/types.d.ts +15 -0
  154. package/lib/sections/languages/types.d.ts.map +1 -0
  155. package/lib/sections/languages/types.js +5 -0
  156. package/lib/sections/projects/ProjectEditDialog.d.ts +7 -0
  157. package/lib/sections/projects/ProjectEditDialog.d.ts.map +1 -0
  158. package/lib/sections/projects/ProjectEditDialog.js +182 -0
  159. package/lib/sections/projects/ProjectSection.d.ts +6 -0
  160. package/lib/sections/projects/ProjectSection.d.ts.map +1 -0
  161. package/lib/sections/projects/ProjectSection.js +220 -0
  162. package/lib/sections/projects/mutations.d.ts +4 -0
  163. package/lib/sections/projects/mutations.d.ts.map +1 -0
  164. package/lib/sections/projects/mutations.js +188 -0
  165. package/lib/sections/projects/selectors.d.ts +5 -0
  166. package/lib/sections/projects/selectors.d.ts.map +1 -0
  167. package/lib/sections/projects/selectors.js +163 -0
  168. package/lib/sections/projects/types.d.ts +28 -0
  169. package/lib/sections/projects/types.d.ts.map +1 -0
  170. package/lib/sections/projects/types.js +8 -0
  171. package/lib/sections/resume/ResumeEditDialog.d.ts +7 -0
  172. package/lib/sections/resume/ResumeEditDialog.d.ts.map +1 -0
  173. package/lib/sections/resume/ResumeEditDialog.js +629 -0
  174. package/lib/sections/resume/ResumeSection.d.ts +7 -0
  175. package/lib/sections/resume/ResumeSection.d.ts.map +1 -0
  176. package/lib/sections/resume/ResumeSection.js +160 -0
  177. package/lib/sections/resume/mutations.d.ts +6 -0
  178. package/lib/sections/resume/mutations.d.ts.map +1 -0
  179. package/lib/sections/resume/mutations.js +172 -0
  180. package/lib/sections/resume/selectors.d.ts +4 -0
  181. package/lib/sections/resume/selectors.d.ts.map +1 -0
  182. package/lib/sections/resume/selectors.js +142 -0
  183. package/lib/sections/resume/types.d.ts +33 -0
  184. package/lib/sections/resume/types.d.ts.map +1 -0
  185. package/lib/sections/resume/types.js +8 -0
  186. package/lib/sections/shared/collapsibleSection.d.ts +2 -0
  187. package/lib/sections/shared/collapsibleSection.d.ts.map +1 -0
  188. package/lib/sections/shared/collapsibleSection.js +24 -0
  189. package/lib/sections/shared/contactTypeUtils.d.ts +7 -0
  190. package/lib/sections/shared/contactTypeUtils.d.ts.map +1 -0
  191. package/lib/sections/shared/contactTypeUtils.js +48 -0
  192. package/lib/sections/shared/idNodeFactory.d.ts +3 -0
  193. package/lib/sections/shared/idNodeFactory.d.ts.map +1 -0
  194. package/lib/sections/shared/idNodeFactory.js +14 -0
  195. package/lib/sections/shared/phoneCountries.d.ts +20 -0
  196. package/lib/sections/shared/phoneCountries.d.ts.map +1 -0
  197. package/lib/sections/shared/phoneCountries.js +1080 -0
  198. package/lib/sections/shared/rdfList.d.ts +3 -0
  199. package/lib/sections/shared/rdfList.d.ts.map +1 -0
  200. package/lib/sections/shared/rdfList.js +34 -0
  201. package/lib/sections/shared/rdfMutationHelpers.d.ts +12 -0
  202. package/lib/sections/shared/rdfMutationHelpers.d.ts.map +1 -0
  203. package/lib/sections/shared/rdfMutationHelpers.js +82 -0
  204. package/lib/sections/shared/rowState.d.ts +21 -0
  205. package/lib/sections/shared/rowState.d.ts.map +1 -0
  206. package/lib/sections/shared/rowState.js +52 -0
  207. package/lib/sections/shared/sanitizeUtils.d.ts +5 -0
  208. package/lib/sections/shared/sanitizeUtils.d.ts.map +1 -0
  209. package/lib/sections/shared/sanitizeUtils.js +22 -0
  210. package/lib/sections/shared/sectionCardHelpers.d.ts +11 -0
  211. package/lib/sections/shared/sectionCardHelpers.d.ts.map +1 -0
  212. package/lib/sections/shared/sectionCardHelpers.js +105 -0
  213. package/lib/sections/shared/types.d.ts +7 -0
  214. package/lib/sections/shared/types.d.ts.map +1 -0
  215. package/lib/sections/shared/types.js +5 -0
  216. package/lib/sections/skills/SkillsEditDialog.d.ts +7 -0
  217. package/lib/sections/skills/SkillsEditDialog.d.ts.map +1 -0
  218. package/lib/sections/skills/SkillsEditDialog.js +340 -0
  219. package/lib/sections/skills/SkillsSection.d.ts +5 -0
  220. package/lib/sections/skills/SkillsSection.d.ts.map +1 -0
  221. package/lib/sections/skills/SkillsSection.js +169 -0
  222. package/lib/sections/skills/mutations.d.ts +6 -0
  223. package/lib/sections/skills/mutations.d.ts.map +1 -0
  224. package/lib/sections/skills/mutations.js +110 -0
  225. package/lib/sections/skills/selectors.d.ts +6 -0
  226. package/lib/sections/skills/selectors.d.ts.map +1 -0
  227. package/lib/sections/skills/selectors.js +37 -0
  228. package/lib/sections/skills/types.d.ts +14 -0
  229. package/lib/sections/skills/types.d.ts.map +1 -0
  230. package/lib/sections/skills/types.js +5 -0
  231. package/lib/sections/social/SocialEditDialog.d.ts +7 -0
  232. package/lib/sections/social/SocialEditDialog.d.ts.map +1 -0
  233. package/lib/sections/social/SocialEditDialog.js +362 -0
  234. package/lib/sections/social/SocialSection.d.ts +8 -0
  235. package/lib/sections/social/SocialSection.d.ts.map +1 -0
  236. package/lib/sections/social/SocialSection.js +201 -0
  237. package/lib/sections/social/constants.d.ts +3 -0
  238. package/lib/sections/social/constants.d.ts.map +1 -0
  239. package/lib/sections/social/constants.js +16 -0
  240. package/lib/sections/social/helpers.d.ts +15 -0
  241. package/lib/sections/social/helpers.d.ts.map +1 -0
  242. package/lib/sections/social/helpers.js +316 -0
  243. package/lib/sections/social/mutations.d.ts +4 -0
  244. package/lib/sections/social/mutations.d.ts.map +1 -0
  245. package/lib/sections/social/mutations.js +298 -0
  246. package/lib/sections/social/selectors.d.ts +4 -0
  247. package/lib/sections/social/selectors.d.ts.map +1 -0
  248. package/lib/sections/social/selectors.js +43 -0
  249. package/lib/sections/social/types.d.ts +19 -0
  250. package/lib/sections/social/types.d.ts.map +1 -0
  251. package/lib/sections/social/types.js +5 -0
  252. package/lib/styles/BioSection.css +77 -0
  253. package/lib/styles/CVCard.css +107 -2
  254. package/lib/styles/ContactInfoEditDialog.css +153 -0
  255. package/lib/styles/EditDialogs.css +1028 -0
  256. package/lib/styles/EducationCard.css +103 -0
  257. package/lib/styles/HeadingSection.css +309 -0
  258. package/lib/styles/ProfileCard.css +10 -42
  259. package/lib/styles/ProfileView.css +53 -8
  260. package/lib/styles/ProjectsCard.css +206 -0
  261. package/lib/styles/QRCodeCard.css +29 -10
  262. package/lib/styles/SocialCard.css +41 -13
  263. package/lib/styles/dialog.css +209 -0
  264. package/lib/styles/utilities.css +638 -256
  265. package/lib/textUtils.d.ts +6 -0
  266. package/lib/textUtils.d.ts.map +1 -0
  267. package/lib/textUtils.js +44 -0
  268. package/lib/texts.d.ts +45 -4
  269. package/lib/texts.d.ts.map +1 -1
  270. package/lib/texts.js +46 -5
  271. package/lib/types.d.ts +2 -0
  272. package/lib/types.d.ts.map +1 -0
  273. package/lib/types.js +5 -0
  274. package/lib/ui/dialog.d.ts +29 -0
  275. package/lib/ui/dialog.d.ts.map +1 -0
  276. package/lib/ui/dialog.js +269 -0
  277. package/lib/ui/errors.d.ts +2 -0
  278. package/lib/ui/errors.d.ts.map +1 -0
  279. package/lib/ui/errors.js +10 -0
  280. package/package.json +6 -4
  281. package/lib/CVCard.d.ts +0 -4
  282. package/lib/CVCard.d.ts.map +0 -1
  283. package/lib/CVCard.js +0 -114
  284. package/lib/CVPresenter.d.ts +0 -25
  285. package/lib/CVPresenter.d.ts.map +0 -1
  286. package/lib/CVPresenter.js +0 -119
  287. package/lib/FriendList.d.ts +0 -6
  288. package/lib/FriendList.d.ts.map +0 -1
  289. package/lib/FriendList.js +0 -27
  290. package/lib/ProfileCard.d.ts +0 -6
  291. package/lib/ProfileCard.d.ts.map +0 -1
  292. package/lib/ProfileCard.js +0 -62
  293. package/lib/SocialCard.d.ts +0 -5
  294. package/lib/SocialCard.d.ts.map +0 -1
  295. package/lib/SocialCard.js +0 -51
  296. package/lib/SocialPresenter.d.ts +0 -11
  297. package/lib/SocialPresenter.d.ts.map +0 -1
  298. package/lib/SocialPresenter.js +0 -117
  299. package/lib/StuffCard.d.ts +0 -10
  300. package/lib/StuffCard.d.ts.map +0 -1
  301. package/lib/StuffCard.js +0 -52
  302. package/lib/StuffPresenter.d.ts +0 -14
  303. package/lib/StuffPresenter.d.ts.map +0 -1
  304. package/lib/StuffPresenter.js +0 -53
  305. package/lib/presenter.d.ts +0 -14
  306. package/lib/presenter.d.ts.map +0 -1
  307. package/lib/presenter.js +0 -68
  308. package/lib/styles/FriendList.css +0 -12
  309. package/lib/styles/StuffCard.css +0 -23
  310. package/lib/styles/editProfile.css +0 -62
  311. package/lib/styles/profileRDFFormsEnforced.css +0 -431
@@ -0,0 +1,457 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createLanguageEditDialog = createLanguageEditDialog;
7
+ var _dialog = require("../../ui/dialog");
8
+ var _litHtml = require("lit-html");
9
+ require("../../styles/EditDialogs.css");
10
+ require("../../styles/ContactInfoEditDialog.css");
11
+ var _rowState = require("../shared/rowState");
12
+ var _textUtils = require("../../textUtils");
13
+ var _mutations = require("./mutations");
14
+ var _profileIcons = require("../../icons-svg/profileIcons");
15
+ var _texts = require("../../texts");
16
+ const WIKIDATA_LANGUAGE_ENDPOINT = 'https://query.wikidata.org/sparql';
17
+ const LANGUAGE_OBJECT_URI_BASE = 'https://www.w3.org/ns/iana/language-code/';
18
+ function sanitizeLanguageFieldValue(value) {
19
+ return (0, _textUtils.sanitizeTextValue)(value);
20
+ }
21
+ function rowHasContent(row) {
22
+ return [row.name, row.publicId, row.proficiency].some(_textUtils.hasNonEmptyText);
23
+ }
24
+ function normalizeLanguageCode(value) {
25
+ return (value || '').trim().toLowerCase();
26
+ }
27
+ function normalizeSuggestionKey(value) {
28
+ return sanitizeLanguageFieldValue(value).toLowerCase().replace(/\(.*?\)/g, ' ').replace(/[^a-z\s-]/g, ' ').replace(/\s+/g, ' ').trim();
29
+ }
30
+ function escapeSparqlRegex(value) {
31
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
32
+ }
33
+ function buildLanguageSearchQuery(name) {
34
+ const escapedName = escapeSparqlRegex(name);
35
+ return `SELECT ?item ?subject ?name WHERE {
36
+ ?item wdt:P305 ?subject .
37
+ OPTIONAL {
38
+ ?item rdfs:label ?name .
39
+ FILTER(langMatches(lang(?name), "en"))
40
+ }
41
+ FILTER regex(?name, "${escapedName}", "i")
42
+ FILTER regex(?subject, "^..$", "i")
43
+ } LIMIT 12`;
44
+ }
45
+ function buildLanguagePublicId(subjectValue) {
46
+ const value = (subjectValue || '').trim();
47
+ if (!value) return '';
48
+ if (value.startsWith('http://') || value.startsWith('https://')) return value;
49
+ return `${LANGUAGE_OBJECT_URI_BASE}${normalizeLanguageCode(value)}`;
50
+ }
51
+ function preferredBindingValue(binding, key) {
52
+ const value = binding?.[key]?.value;
53
+ return typeof value === 'string' ? value : '';
54
+ }
55
+ async function fetchLanguageSuggestions(term) {
56
+ const queryTerm = sanitizeLanguageFieldValue(term);
57
+ if (queryTerm.length < 2 || typeof fetch !== 'function') return [];
58
+ const params = new URLSearchParams({
59
+ query: buildLanguageSearchQuery(queryTerm),
60
+ format: 'json'
61
+ });
62
+ try {
63
+ const response = await fetch(`${WIKIDATA_LANGUAGE_ENDPOINT}?${params.toString()}`, {
64
+ headers: {
65
+ Accept: 'application/sparql-results+json, application/json'
66
+ }
67
+ });
68
+ if (!response.ok) return [];
69
+ const payload = await response.json();
70
+ const bindings = Array.isArray(payload?.results?.bindings) ? payload.results.bindings : [];
71
+ const seen = new Set();
72
+ return bindings.map(binding => {
73
+ const code = normalizeLanguageCode(preferredBindingValue(binding, 'subject'));
74
+ const publicId = buildLanguagePublicId(code);
75
+ const name = sanitizeLanguageFieldValue(preferredBindingValue(binding, 'name') || code);
76
+ return {
77
+ name,
78
+ publicId,
79
+ code
80
+ };
81
+ }).filter(item => {
82
+ if (!item.name || !item.publicId || item.code.length !== 2) return false;
83
+ const key = item.publicId.toLowerCase();
84
+ if (seen.has(key)) return false;
85
+ seen.add(key);
86
+ return true;
87
+ });
88
+ } catch {
89
+ return [];
90
+ }
91
+ }
92
+ function matchLanguageSuggestion(suggestions, value) {
93
+ const normalized = sanitizeLanguageFieldValue(value).toLowerCase();
94
+ if (!normalized) return null;
95
+ const exact = suggestions.find(suggestion => suggestion.name.toLowerCase() === normalized);
96
+ if (exact) return exact;
97
+ const normalizedKey = normalizeSuggestionKey(value);
98
+ if (!normalizedKey) return null;
99
+ return suggestions.find(suggestion => normalizeSuggestionKey(suggestion.name) === normalizedKey) || null;
100
+ }
101
+ function toFormState(details) {
102
+ const rows = (details || []).map(detail => ({
103
+ name: sanitizeLanguageFieldValue((0, _textUtils.toText)(detail.name)),
104
+ publicId: sanitizeLanguageFieldValue((0, _textUtils.toText)(detail.publicId)),
105
+ proficiency: sanitizeLanguageFieldValue((0, _textUtils.toText)(detail.proficiency)),
106
+ entryNode: (0, _textUtils.toText)(detail.entryNode),
107
+ status: (0, _textUtils.toText)(detail.entryNode) ? 'existing' : 'new'
108
+ })).filter(row => Boolean(row.name || row.entryNode || row.proficiency || row.publicId));
109
+ return {
110
+ languages: rows.length ? rows : [{
111
+ name: '',
112
+ publicId: '',
113
+ proficiency: '',
114
+ entryNode: '',
115
+ status: 'new'
116
+ }],
117
+ initialExistingOrder: []
118
+ };
119
+ }
120
+ function hasOrderChanged(rows, initialExistingOrder) {
121
+ const currentExistingOrder = rows.filter(row => row.status !== 'deleted' && Boolean((row.entryNode || '').trim())).map(row => (row.entryNode || '').trim());
122
+ if (currentExistingOrder.length !== initialExistingOrder.length) return true;
123
+ for (let i = 0; i < currentExistingOrder.length; i++) {
124
+ if (currentExistingOrder[i] !== initialExistingOrder[i]) return true;
125
+ }
126
+ return false;
127
+ }
128
+ function validateLanguagesBeforeSave(rows, initialExistingOrder) {
129
+ const ops = (0, _rowState.summarizeRowOps)(rows, rowHasContent);
130
+ const hasChanges = ops.create.length > 0 || ops.update.length > 0 || ops.remove.length > 0;
131
+ const orderChanged = hasOrderChanged(rows, initialExistingOrder);
132
+ if (!hasChanges && !orderChanged) return 'No language changes detected.';
133
+ for (let i = 0; i < rows.length; i++) {
134
+ const row = rows[i];
135
+ if (!row || row.status === 'deleted') continue;
136
+ if (!(0, _textUtils.hasNonEmptyText)(row.name)) continue;
137
+ if (!(0, _textUtils.hasNonEmptyText)(row.publicId)) {
138
+ return `Language ${i + 1}: please choose a language from the suggestions list.`;
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+ function hasInvalidLanguageSelection(rows) {
144
+ return rows.some(row => {
145
+ if (!row || row.status === 'deleted') return false;
146
+ if (!(0, _textUtils.hasNonEmptyText)(row.name)) return false;
147
+ return !(0, _textUtils.hasNonEmptyText)(row.publicId);
148
+ });
149
+ }
150
+ function updateLanguagesSubmitEnabled(rows) {
151
+ const submitButton = document.querySelector('#profile-modal #modal-buttons button.btn-primary');
152
+ if (!submitButton) return;
153
+ submitButton.disabled = hasInvalidLanguageSelection(rows);
154
+ }
155
+ function focusLanguageField(form, selector) {
156
+ const nextField = form.querySelector(selector);
157
+ if (!nextField || typeof nextField.focus !== 'function') return;
158
+ nextField.scrollIntoView({
159
+ block: 'start',
160
+ behavior: 'auto'
161
+ });
162
+ nextField.focus();
163
+ if (nextField instanceof HTMLInputElement || nextField instanceof HTMLTextAreaElement) {
164
+ nextField.select();
165
+ }
166
+ }
167
+ function renderLanguageInputRow({
168
+ rows,
169
+ index,
170
+ displayIndex,
171
+ onDelete,
172
+ onChange,
173
+ onSearch,
174
+ suggestions,
175
+ onDragStart,
176
+ onDragOver,
177
+ onDrop,
178
+ onDragEnd,
179
+ isDropTarget
180
+ }) {
181
+ const row = rows[index];
182
+ const label = `Language ${displayIndex + 1}`;
183
+ const proficiencyLabel = `Language Proficiency ${displayIndex + 1}`;
184
+ const languageName = `language-${index}`;
185
+ const proficiencyInputName = `proficiency-${index}`;
186
+ const proficiencySelectId = `proficiency-${index}`;
187
+ const datalistId = `language-suggestions-${index}`;
188
+ const hasSelectionIssue = Boolean(row && row.status !== 'deleted' && (0, _textUtils.hasNonEmptyText)(row.name) && !(0, _textUtils.hasNonEmptyText)(row.publicId));
189
+ const handleLanguageInput = field => e => {
190
+ const target = e.target;
191
+ const nextValue = sanitizeLanguageFieldValue(target.value);
192
+ if (rows[index]) {
193
+ (0, _rowState.applyRowFieldChange)(rows[index], field, nextValue, rowHasContent);
194
+ const matchedSuggestion = matchLanguageSuggestion(suggestions, nextValue);
195
+ rows[index].publicId = matchedSuggestion?.publicId || '';
196
+ if (matchedSuggestion) {
197
+ rows[index].name = sanitizeLanguageFieldValue(matchedSuggestion.name);
198
+ }
199
+ onSearch(index, nextValue);
200
+ onChange();
201
+ }
202
+ };
203
+ const handleLanguageChange = field => e => {
204
+ handleLanguageInput(field)(e);
205
+ };
206
+ const handleProficiencyInput = e => {
207
+ const target = e.target;
208
+ const nextType = target.value;
209
+ if (rows[index]) {
210
+ (0, _rowState.applyRowSelectChange)(rows[index], 'proficiency', nextType);
211
+ onChange();
212
+ }
213
+ };
214
+ const handleDelete = event => {
215
+ event.preventDefault();
216
+ onDelete();
217
+ };
218
+ return (0, _litHtml.html)`
219
+ <div
220
+ class="profile-edit-dialog__row profile-edit-dialog__row--language ${isDropTarget ? 'profile-edit-dialog__row--drop-target' : ''}"
221
+ @dragover=${event => onDragOver(event)}
222
+ @drop=${() => onDrop(index)}
223
+ >
224
+ <button
225
+ type="button"
226
+ class="profile-edit-dialog__drag-handle"
227
+ aria-label=${`Reorder language ${displayIndex + 1}`}
228
+ title="Drag to reorder"
229
+ draggable="true"
230
+ @dragstart=${() => onDragStart(index)}
231
+ @dragend=${() => onDragEnd()}
232
+ >
233
+ ${_profileIcons.bentoIcon}
234
+ </button>
235
+ <label aria-label=${`${label} Language`} class="label profile-edit-dialog__field">
236
+ <input
237
+ class="input"
238
+ type="text"
239
+ name=${languageName}
240
+ .value=${row?.name || ''}
241
+ required
242
+ data-contact-field="name"
243
+ data-entry-node=${row?.entryNode || ''}
244
+ data-row-status=${row?.status || 'n/a'}
245
+ placeholder="Language"
246
+ autocomplete="off"
247
+ list=${datalistId}
248
+ inputmode="text"
249
+ aria-invalid=${hasSelectionIssue ? 'true' : 'false'}
250
+ @input=${handleLanguageInput('name')}
251
+ @change=${handleLanguageChange('name')}
252
+ />
253
+ <datalist id=${datalistId}>
254
+ ${suggestions.map(suggestion => (0, _litHtml.html)`<option value=${suggestion.name}></option>`)}
255
+ </datalist>
256
+ <small class="profile-edit-dialog__input-help-text">Type to search and select one language suggestion.</small>
257
+ </label>
258
+ <label aria-label=${proficiencyLabel} class="label" hidden>
259
+ <select name=${proficiencyInputName} id=${proficiencySelectId} @change=${handleProficiencyInput} .value=${row?.proficiency || ''}>
260
+ <option value="Basic">Basic</option>
261
+ <option value="Intermediate">Intermediate</option>
262
+ <option value="Fluent">Fluent</option>
263
+ </select>
264
+ </label>
265
+ <div class="profile-edit-dialog__actions profile-edit-dialog__actions--edge">
266
+ <button
267
+ type="button"
268
+ class="profile-edit-dialog__delete-button"
269
+ aria-label=${`Delete language ${displayIndex + 1}`}
270
+ title=${_texts.deleteEntryButtonTitleText}
271
+ @click=${handleDelete}
272
+ >
273
+ <span class="profile-edit-dialog__delete-icon" aria-hidden="true">${_profileIcons.trashIcon}</span>
274
+ </button>
275
+ </div>
276
+ </div>
277
+ `;
278
+ }
279
+ function renderLanguageSection(rows, onAddRow, suggestionByIndex, onSearch) {
280
+ let dragSourceIndex = null;
281
+ let dropTargetIndex = null;
282
+ const reorderRows = (from, to) => {
283
+ if (from === to) return;
284
+ const row = rows[from];
285
+ if (!row) return;
286
+ rows.splice(from, 1);
287
+ rows.splice(to, 0, row);
288
+ Object.keys(suggestionByIndex).forEach(key => {
289
+ delete suggestionByIndex[Number(key)];
290
+ });
291
+ };
292
+ const handleDragStart = index => {
293
+ dragSourceIndex = index;
294
+ dropTargetIndex = index;
295
+ };
296
+ const handleDragOver = event => {
297
+ event.preventDefault();
298
+ if (event.dataTransfer) {
299
+ event.dataTransfer.dropEffect = 'move';
300
+ }
301
+ };
302
+ const handleDrop = index => {
303
+ if (dragSourceIndex === null) return;
304
+ reorderRows(dragSourceIndex, index);
305
+ dragSourceIndex = null;
306
+ dropTargetIndex = null;
307
+ onAddRow();
308
+ };
309
+ const handleDragEnd = () => {
310
+ dragSourceIndex = null;
311
+ dropTargetIndex = null;
312
+ };
313
+ const visibleRows = rows.map((row, index) => ({
314
+ row,
315
+ index
316
+ })).filter(({
317
+ row
318
+ }) => row.status !== 'deleted');
319
+ return (0, _litHtml.html)`
320
+ <section class="profile-edit-dialog__section" aria-label="Languages">
321
+ <fieldset>
322
+ <legend class="sr-only">Language entries</legend>
323
+ ${visibleRows.map(({
324
+ index
325
+ }, displayIndex) => renderLanguageInputRow({
326
+ rows,
327
+ index,
328
+ displayIndex,
329
+ onChange: onAddRow,
330
+ onSearch,
331
+ suggestions: suggestionByIndex[index] || [],
332
+ onDragStart: handleDragStart,
333
+ onDragOver: handleDragOver,
334
+ onDrop: handleDrop,
335
+ onDragEnd: handleDragEnd,
336
+ isDropTarget: dropTargetIndex === index,
337
+ onDelete: () => {
338
+ (0, _rowState.deleteRow)(rows, index);
339
+ delete suggestionByIndex[index];
340
+ onAddRow();
341
+ }
342
+ }))}
343
+ </fieldset>
344
+ </section>
345
+ `;
346
+ }
347
+ function renderLanguageEditTemplate(form, formState, viewerMode, options = {}) {
348
+ const formStateWithSearch = formState;
349
+ const suggestionByIndex = formStateWithSearch.suggestionByIndex || (formStateWithSearch.suggestionByIndex = {});
350
+ const searchSeqByIndex = formStateWithSearch.searchSeqByIndex || (formStateWithSearch.searchSeqByIndex = {});
351
+ const searchTimerByIndex = formStateWithSearch.searchTimerByIndex || (formStateWithSearch.searchTimerByIndex = {});
352
+ const rerender = (nextOptions = {}) => renderLanguageEditTemplate(form, formState, viewerMode, nextOptions);
353
+ const onSearch = (index, term) => {
354
+ if (searchTimerByIndex[index]) {
355
+ clearTimeout(searchTimerByIndex[index]);
356
+ }
357
+ const normalized = sanitizeLanguageFieldValue(term);
358
+ if (normalized.length < 2) {
359
+ suggestionByIndex[index] = [];
360
+ rerender();
361
+ return;
362
+ }
363
+ const seq = (searchSeqByIndex[index] || 0) + 1;
364
+ searchSeqByIndex[index] = seq;
365
+ searchTimerByIndex[index] = setTimeout(async () => {
366
+ const suggestions = await fetchLanguageSuggestions(normalized);
367
+ if (searchSeqByIndex[index] !== seq) return;
368
+ suggestionByIndex[index] = suggestions;
369
+ const row = formState.languages[index];
370
+ if (row) {
371
+ const matchedSuggestion = matchLanguageSuggestion(suggestions, row.name);
372
+ row.publicId = matchedSuggestion?.publicId || row.publicId;
373
+ }
374
+ rerender();
375
+ }, 220);
376
+ };
377
+ (0, _litHtml.render)((0, _litHtml.html)`
378
+ ${renderLanguageSection(formState.languages, rerender, suggestionByIndex, onSearch)}
379
+ ${viewerMode !== 'owner' ? (0, _litHtml.html)`<p class="profile-edit-dialog__login-message">${_texts.ownerLoginRequiredDialogMessageText}</p>` : null}
380
+ `, form);
381
+ updateLanguagesSubmitEnabled(formState.languages);
382
+ if (options.focusSelector) {
383
+ focusLanguageField(form, options.focusSelector);
384
+ }
385
+ }
386
+ function createLanguageEditForm(details, viewerMode) {
387
+ const form = document.createElement('form');
388
+ form.classList.add('profile__edit-form');
389
+ const formState = toFormState(details);
390
+ formState.initialExistingOrder = formState.languages.filter(row => Boolean((row.entryNode || '').trim())).map(row => (row.entryNode || '').trim());
391
+ renderLanguageEditTemplate(form, formState, viewerMode);
392
+ const addRow = () => {
393
+ formState.languages.unshift({
394
+ name: '',
395
+ publicId: '',
396
+ proficiency: '',
397
+ entryNode: '',
398
+ status: 'new'
399
+ });
400
+ const formStateWithSearch = formState;
401
+ formStateWithSearch.suggestionByIndex = {};
402
+ formStateWithSearch.searchSeqByIndex = {};
403
+ formStateWithSearch.searchTimerByIndex = {};
404
+ renderLanguageEditTemplate(form, formState, viewerMode, {
405
+ focusSelector: '[name="language-0"]'
406
+ });
407
+ };
408
+ return {
409
+ form,
410
+ formState,
411
+ addRow
412
+ };
413
+ }
414
+ async function createLanguageEditDialog(event, store, subject, languages, viewerMode, onSaved) {
415
+ const dom = event.currentTarget?.ownerDocument || document;
416
+ const {
417
+ form,
418
+ formState,
419
+ addRow
420
+ } = createLanguageEditForm(languages, viewerMode);
421
+ const result = await (0, _dialog.openInputDialog)({
422
+ title: _texts.editLanguagesDialogTitleText,
423
+ dom,
424
+ form,
425
+ headerAction: {
426
+ type: 'button',
427
+ label: '+ Add More',
428
+ ariaLabel: 'Add another language',
429
+ onClick: addRow
430
+ },
431
+ submitLabel: _texts.dialogSubmitLabelText,
432
+ cancelLabel: _texts.dialogCancelLabelText,
433
+ validate: () => {
434
+ if (viewerMode !== 'owner') {
435
+ return _texts.ownerLoginRequiredDialogMessageText;
436
+ }
437
+ return validateLanguagesBeforeSave(formState.languages, formState.initialExistingOrder);
438
+ },
439
+ onSave: async () => {
440
+ const languageOps = (0, _rowState.summarizeRowOps)(formState.languages, rowHasContent);
441
+ const plan = {
442
+ create: languageOps.create,
443
+ update: languageOps.update,
444
+ remove: languageOps.remove
445
+ };
446
+ await (0, _mutations.processLanguageMutations)(store, subject, plan, formState.languages);
447
+ },
448
+ formatSaveError: error => {
449
+ const message = error instanceof Error ? error.message : String(error);
450
+ return `${_texts.saveLanguageUpdatesFailedPrefixText} ${message}`;
451
+ }
452
+ });
453
+ if (!result) return;
454
+ if (onSaved) {
455
+ await onSaved();
456
+ }
457
+ }
@@ -0,0 +1,5 @@
1
+ import { LiveStore, NamedNode } from 'rdflib';
2
+ import { ViewerMode } from '../../types';
3
+ import { LanguageDetails } from './types';
4
+ export declare function renderLanguageSection(store: LiveStore, subject: NamedNode, languages: LanguageDetails[], viewerMode: ViewerMode, onSaved?: () => Promise<void> | void): import("lit-html").TemplateResult<1> | "";
5
+ //# sourceMappingURL=LanguageSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LanguageSection.d.ts","sourceRoot":"","sources":["../../../src/sections/languages/LanguageSection.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAwJzC,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,EAClB,SAAS,EAAE,eAAe,EAAE,EAC5B,UAAU,EAAE,UAAU,EACtB,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,6CAcrC"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.renderLanguageSection = renderLanguageSection;
7
+ var _litHtml = require("lit-html");
8
+ var _solidUi = require("solid-ui");
9
+ var _LanguageEditDialog = require("./LanguageEditDialog");
10
+ var _profileIcons = require("../../icons-svg/profileIcons");
11
+ var _texts = require("../../texts");
12
+ var _collapsibleSection = require("../shared/collapsibleSection");
13
+ function renderLan(language, asList = false) {
14
+ if (!language) return (0, _litHtml.html)``;
15
+ return asList ? (0, _litHtml.html)`<li class="languages__item-label" role="listitem">${language.name}</li>` : (0, _litHtml.html)``;
16
+ }
17
+ function renderLanguages(languages, asList = false) {
18
+ if (!languages || !languages.length || !languages[0]) return (0, _litHtml.html)``;
19
+ return (0, _litHtml.html)`${renderLan(languages[0], asList)}${languages.length > 1 ? renderLanguages(languages.slice(1), asList) : (0, _litHtml.html)``}`;
20
+ }
21
+ function renderLanguagesSectionDefault(store, subject, languages, viewerMode, onSaved) {
22
+ const hasLanguages = Array.isArray(languages) && languages.length > 0;
23
+ const hasLanguageLinks = store.each(subject, _solidUi.ns.schema('knowsLanguage')).length > 0;
24
+ const isOwner = viewerMode === 'owner';
25
+ return (0, _litHtml.html)`
26
+ <section
27
+ class="profile__section border-lighter profile-section-collapsible profile-section-collapsible--inline-mobile-actions"
28
+ aria-labelledby="languages-heading"
29
+ role="region"
30
+ tabindex="-1"
31
+ data-expanded="false"
32
+ >
33
+ <header class="profile__section-header profile-section-collapsible__header">
34
+ <h2 id="languages-heading">${_texts.languagesHeadingText}</h2>
35
+ <div class="profile-section-collapsible__actions flex-column">
36
+ ${isOwner ? (0, _litHtml.html)`
37
+ <button
38
+ type="button"
39
+ class="profile__action-button profile-action-text flex-center profile-section-collapsible__edit-button"
40
+ aria-label="Add or edit languages"
41
+ @click=${event => (0, _LanguageEditDialog.createLanguageEditDialog)(event, store, subject, languages, viewerMode, onSaved)}
42
+ >
43
+ <span class="profile-section-collapsible__edit-label profile__add-more-content inline-flex-row">
44
+ <span class="profile__add-more-icon inline-flex-row" aria-hidden="true">${_profileIcons.addIcon}</span>
45
+ Add More
46
+ </span>
47
+ <span class="profile-section-collapsible__edit-icon" aria-hidden="true">${_profileIcons.editIcon}</span>
48
+ </button>
49
+ ` : (0, _litHtml.html)``}
50
+ <button
51
+ type="button"
52
+ class="inline-flex-row"
53
+ aria-label="Toggle languages section"
54
+ aria-controls="languages-panel"
55
+ aria-expanded="false"
56
+ @click=${_collapsibleSection.toggleCollapsibleSection}
57
+ >
58
+ <span class="profile-section-collapsible__chevron" aria-hidden="true">⌄</span>
59
+ </button>
60
+ </div>
61
+ </header>
62
+ <div id="languages-panel" class="profile-section-collapsible__content" aria-hidden="true">
63
+ ${hasLanguages ? (0, _litHtml.html)`
64
+ <ul class="languages__list" role="list" aria-label="Known languages">
65
+ ${renderLanguages(languages, true)}
66
+ </ul>
67
+ ` : hasLanguageLinks ? (0, _litHtml.html)`<p>Language details are missing for one or more entries.</p>` : (0, _litHtml.html)`<p>No languages added yet.</p>`}
68
+ </div>
69
+ </section>
70
+ `;
71
+ }
72
+ function renderOwnerEmptyLanguagesContent(_store, _subject, _languages, _viewerMode, _onSaved) {
73
+ return (0, _litHtml.html)`
74
+ <div class="profile__empty-state-content flex-column-center" role="group" aria-label="Empty languages section">
75
+ <div class="languages__empty-icon-wrapper">
76
+ <span class="languages__empty-icon inline-flex-row">${_profileIcons.commentIcon}</span>
77
+ </div>
78
+ <p class="profile__empty-state-message languages__empty-message">
79
+ No languages added yet.
80
+ </p>
81
+ </div>
82
+ `;
83
+ }
84
+ function renderOwnerEmptyLanguagesSection(store, subject, languages, viewerMode, onSaved) {
85
+ return (0, _litHtml.html)`
86
+ <section
87
+ aria-labelledby="languages-heading"
88
+ data-profile-section="languages"
89
+ class="profile__section--empty border-lighter rounded-md gap-lg profile-section-collapsible profile-section-collapsible--inline-mobile-actions"
90
+ role="region"
91
+ tabindex="-1"
92
+ data-expanded="false"
93
+ >
94
+ <header class="profile__section-header profile-section-collapsible__header">
95
+ <h2 id="languages-heading" tabindex="-1">${_texts.languagesHeadingText}</h2>
96
+ <div class="profile-section-collapsible__actions flex-column">
97
+ <button
98
+ type="button"
99
+ class="profile__action-button profile-action-text flex-center profile-section-collapsible__edit-button"
100
+ aria-label="Add languages"
101
+ @click=${event => {
102
+ return (0, _LanguageEditDialog.createLanguageEditDialog)(event, store, subject, languages, viewerMode, onSaved);
103
+ }}
104
+ >
105
+ <span class="profile-section-collapsible__edit-label profile__add-more-content inline-flex-row">
106
+ <span class="profile__add-more-icon inline-flex-row" aria-hidden="true">${_profileIcons.addIcon}</span>
107
+ Add Languages
108
+ </span>
109
+ <span class="profile-section-collapsible__edit-icon profile-section-collapsible__edit-icon--add" aria-hidden="true">${_profileIcons.plusIcon}</span>
110
+ </button>
111
+ <button
112
+ type="button"
113
+ class="inline-flex-row"
114
+ aria-label="Toggle languages section"
115
+ aria-controls="languages-panel"
116
+ aria-expanded="false"
117
+ @click=${_collapsibleSection.toggleCollapsibleSection}
118
+ >
119
+ <span class="profile-section-collapsible__chevron" aria-hidden="true">⌄</span>
120
+ </button>
121
+ </div>
122
+ </header>
123
+ <div id="languages-panel" class="profile-section-collapsible__content" aria-hidden="true">
124
+ ${renderOwnerEmptyLanguagesContent(store, subject, languages, viewerMode, onSaved)}
125
+ </div>
126
+ </section>
127
+ `;
128
+ }
129
+ function renderLanguageSection(store, subject, languages, viewerMode, onSaved) {
130
+ const safeLanguages = languages || [];
131
+ const hasLanguages = Array.isArray(safeLanguages) && safeLanguages.length > 0;
132
+ const showOwnerEmptyLanguages = !hasLanguages && viewerMode === 'owner';
133
+ const showSection = true;
134
+ return showSection ? (0, _litHtml.html)`
135
+ ${showOwnerEmptyLanguages ? renderOwnerEmptyLanguagesSection(store, subject, safeLanguages, viewerMode, onSaved) : renderLanguagesSectionDefault(store, subject, safeLanguages, viewerMode, onSaved)}
136
+ ` : '';
137
+ }
@@ -0,0 +1,6 @@
1
+ import { LiveStore, NamedNode } from 'rdflib';
2
+ import { LanguageRow } from './types';
3
+ import { MutationOps } from '../shared/types';
4
+ export type LanguageMutationPlan = MutationOps<LanguageRow>;
5
+ export declare function processLanguageMutations(store: LiveStore, subject: NamedNode, mutationPlan: LanguageMutationPlan, orderedRows?: LanguageRow[]): Promise<void>;
6
+ //# sourceMappingURL=mutations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutations.d.ts","sourceRoot":"","sources":["../../../src/sections/languages/mutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,SAAS,EAAoB,MAAM,QAAQ,CAAA;AAE1E,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAM7C,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;AAqW3D,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,SAAS,EAClB,YAAY,EAAE,oBAAoB,EAClC,WAAW,CAAC,EAAE,WAAW,EAAE,iBAS5B"}