ds-one 0.2.0-alpha.3 → 0.2.5-alpha.10

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 (271) hide show
  1. package/DS1/0-face/{2025-04-23-device.ts → device.ts} +10 -6
  2. package/DS1/{utils/language.ts → 0-face/i18n.ts} +236 -92
  3. package/DS1/0-face/preferences.ts +23 -0
  4. package/DS1/0-face/pricing.ts +57 -0
  5. package/DS1/1-root/fonts/Iosevka-Regular.woff2 +0 -0
  6. package/DS1/1-root/one.css +76 -107
  7. package/DS1/2-core/ds-banner.ts +3 -0
  8. package/DS1/2-core/ds-button.ts +13 -16
  9. package/DS1/2-core/ds-cycle.ts +84 -39
  10. package/DS1/2-core/{ds-year.ts → ds-date.ts} +5 -6
  11. package/DS1/2-core/ds-icon.ts +4 -4
  12. package/DS1/2-core/ds-input.ts +1 -0
  13. package/DS1/2-core/ds-text.ts +27 -3
  14. package/DS1/2-core/ds-tooltip.ts +9 -14
  15. package/DS1/3-unit/ds-list.ts +7 -0
  16. package/DS1/3-unit/ds-row.ts +4 -5
  17. package/DS1/3-unit/ds-table.ts +5 -6
  18. package/DS1/4-page/ds-grid.ts +9 -59
  19. package/DS1/4-page/ds-layout.ts +123 -18
  20. package/DS1/index.ts +39 -37
  21. package/LICENSE +1 -1
  22. package/README.md +43 -133
  23. package/dist/0-face/{2025-04-23-device.d.ts → device.d.ts} +1 -1
  24. package/dist/0-face/device.d.ts.map +1 -0
  25. package/dist/0-face/{2025-04-23-device.js → device.js} +7 -3
  26. package/dist/{utils/language.d.ts → 0-face/i18n.d.ts} +1 -3
  27. package/dist/0-face/i18n.d.ts.map +1 -0
  28. package/dist/{utils/language.js → 0-face/i18n.js} +178 -76
  29. package/dist/0-face/preferences.d.ts +9 -0
  30. package/dist/0-face/preferences.d.ts.map +1 -0
  31. package/dist/0-face/preferences.js +14 -0
  32. package/dist/0-face/pricing.d.ts +15 -0
  33. package/dist/0-face/pricing.d.ts.map +1 -0
  34. package/dist/0-face/pricing.js +46 -0
  35. package/dist/0-face/theme.d.ts.map +1 -0
  36. package/dist/2-core/ds-banner.d.ts +1 -0
  37. package/dist/2-core/ds-banner.d.ts.map +1 -0
  38. package/dist/2-core/ds-banner.js +2 -0
  39. package/dist/2-core/ds-button.d.ts +2 -7
  40. package/dist/2-core/ds-button.d.ts.map +1 -1
  41. package/dist/2-core/ds-button.js +12 -14
  42. package/dist/2-core/ds-cycle.d.ts +2 -0
  43. package/dist/2-core/ds-cycle.d.ts.map +1 -1
  44. package/dist/2-core/ds-cycle.js +80 -34
  45. package/dist/2-core/{ds-year.d.ts → ds-date.d.ts} +4 -4
  46. package/dist/2-core/ds-date.d.ts.map +1 -0
  47. package/dist/2-core/{ds-year.js → ds-date.js} +5 -5
  48. package/dist/2-core/ds-icon.js +4 -4
  49. package/dist/2-core/ds-input.d.ts +1 -0
  50. package/dist/2-core/ds-input.d.ts.map +1 -0
  51. package/dist/2-core/ds-input.js +1 -0
  52. package/dist/2-core/ds-text.d.ts +2 -0
  53. package/dist/2-core/ds-text.d.ts.map +1 -1
  54. package/dist/2-core/ds-text.js +26 -3
  55. package/dist/2-core/ds-tooltip.d.ts +1 -1
  56. package/dist/2-core/ds-tooltip.d.ts.map +1 -1
  57. package/dist/2-core/ds-tooltip.js +9 -13
  58. package/dist/3-unit/ds-list.d.ts.map +1 -1
  59. package/dist/3-unit/ds-list.js +3 -0
  60. package/dist/3-unit/{ds-doublenav.d.ts → ds-portfolio-doublenav.d.ts} +4 -4
  61. package/dist/3-unit/ds-portfolio-doublenav.d.ts.map +1 -0
  62. package/dist/3-unit/{ds-doublenav.js → ds-portfolio-doublenav.js} +4 -4
  63. package/dist/3-unit/{ds-panel.d.ts → ds-portfolio-panel.d.ts} +3 -3
  64. package/dist/3-unit/ds-portfolio-panel.d.ts.map +1 -0
  65. package/dist/3-unit/{ds-panel.js → ds-portfolio-panel.js} +3 -3
  66. package/dist/3-unit/{ds-singlenav.d.ts → ds-portfolio-singlenav.d.ts} +4 -4
  67. package/dist/3-unit/ds-portfolio-singlenav.d.ts.map +1 -0
  68. package/dist/3-unit/{ds-singlenav.js → ds-portfolio-singlenav.js} +7 -7
  69. package/dist/3-unit/ds-row.js +4 -4
  70. package/dist/3-unit/ds-table.d.ts.map +1 -1
  71. package/dist/3-unit/ds-table.js +5 -6
  72. package/dist/4-page/ds-grid.d.ts +0 -7
  73. package/dist/4-page/ds-grid.d.ts.map +1 -1
  74. package/dist/4-page/ds-grid.js +9 -54
  75. package/dist/4-page/ds-layout.d.ts +1 -1
  76. package/dist/4-page/ds-layout.d.ts.map +1 -1
  77. package/dist/4-page/ds-layout.js +126 -17
  78. package/dist/ds-one.bundle.js +2515 -4132
  79. package/dist/ds-one.bundle.js.map +4 -4
  80. package/dist/ds-one.bundle.min.js +245 -787
  81. package/dist/ds-one.bundle.min.js.map +4 -4
  82. package/dist/index.d.ts +16 -26
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +32 -34
  85. package/package.json +8 -9
  86. package/DS1/0-face/2025-04-23-language.ts +0 -4
  87. package/DS1/2-core/ds-article.ts +0 -454
  88. package/DS1/2-core/ds-attributes.ts +0 -155
  89. package/DS1/2-core/ds-downloadcv.ts +0 -146
  90. package/DS1/2-core/ds-header.ts +0 -82
  91. package/DS1/2-core/ds-home.ts +0 -168
  92. package/DS1/2-core/ds-link.ts +0 -121
  93. package/DS1/2-core/ds-markdown.ts +0 -252
  94. package/DS1/2-core/ds-price.ts +0 -108
  95. package/DS1/2-core/ds-squarecircle.ts +0 -155
  96. package/DS1/2-core/ds-title.ts +0 -139
  97. package/DS1/2-core/ds-viewtoggle.ts +0 -83
  98. package/DS1/3-unit/ds-doublenav.ts +0 -106
  99. package/DS1/3-unit/ds-panel.ts +0 -27
  100. package/DS1/3-unit/ds-singlenav.ts +0 -79
  101. package/DS1/utils/cdn-loader.ts +0 -208
  102. package/DS1/utils/keys.json +0 -41
  103. package/DS1/utils/pricing.ts +0 -24
  104. package/DS1/utils/scroll.ts +0 -184
  105. package/DS1/utils/settings.ts +0 -23
  106. package/DS1/utils/viewMode.ts +0 -55
  107. package/dist/0-face/2025-04-23-device.d.ts.map +0 -1
  108. package/dist/0-face/2025-04-23-language.d.ts +0 -1
  109. package/dist/0-face/2025-04-23-language.d.ts.map +0 -1
  110. package/dist/0-face/2025-04-23-language.js +0 -3
  111. package/dist/2-core/article-v1.d.ts +0 -129
  112. package/dist/2-core/article-v1.d.ts.map +0 -1
  113. package/dist/2-core/article-v1.js +0 -361
  114. package/dist/2-core/attributes-v1.d.ts +0 -47
  115. package/dist/2-core/attributes-v1.d.ts.map +0 -1
  116. package/dist/2-core/attributes-v1.js +0 -128
  117. package/dist/2-core/cycle-v1.d.ts +0 -66
  118. package/dist/2-core/cycle-v1.d.ts.map +0 -1
  119. package/dist/2-core/cycle-v1.js +0 -586
  120. package/dist/2-core/downloadcv-v1.d.ts +0 -58
  121. package/dist/2-core/downloadcv-v1.d.ts.map +0 -1
  122. package/dist/2-core/downloadcv-v1.js +0 -119
  123. package/dist/2-core/ds-article.d.ts +0 -129
  124. package/dist/2-core/ds-article.d.ts.map +0 -1
  125. package/dist/2-core/ds-article.js +0 -361
  126. package/dist/2-core/ds-attributes.d.ts +0 -47
  127. package/dist/2-core/ds-attributes.d.ts.map +0 -1
  128. package/dist/2-core/ds-attributes.js +0 -128
  129. package/dist/2-core/ds-button.figma.d.ts +0 -2
  130. package/dist/2-core/ds-button.figma.d.ts.map +0 -1
  131. package/dist/2-core/ds-button.figma.js +0 -6
  132. package/dist/2-core/ds-downloadcv.d.ts +0 -58
  133. package/dist/2-core/ds-downloadcv.d.ts.map +0 -1
  134. package/dist/2-core/ds-downloadcv.js +0 -119
  135. package/dist/2-core/ds-header.d.ts +0 -28
  136. package/dist/2-core/ds-header.d.ts.map +0 -1
  137. package/dist/2-core/ds-header.js +0 -66
  138. package/dist/2-core/ds-home.d.ts +0 -26
  139. package/dist/2-core/ds-home.d.ts.map +0 -1
  140. package/dist/2-core/ds-home.js +0 -148
  141. package/dist/2-core/ds-link.d.ts +0 -35
  142. package/dist/2-core/ds-link.d.ts.map +0 -1
  143. package/dist/2-core/ds-link.js +0 -85
  144. package/dist/2-core/ds-markdown.d.ts +0 -7
  145. package/dist/2-core/ds-markdown.d.ts.map +0 -1
  146. package/dist/2-core/ds-markdown.js +0 -240
  147. package/dist/2-core/ds-price.d.ts +0 -46
  148. package/dist/2-core/ds-price.d.ts.map +0 -1
  149. package/dist/2-core/ds-price.js +0 -72
  150. package/dist/2-core/ds-squarecircle.d.ts +0 -50
  151. package/dist/2-core/ds-squarecircle.d.ts.map +0 -1
  152. package/dist/2-core/ds-squarecircle.js +0 -133
  153. package/dist/2-core/ds-title.d.ts +0 -50
  154. package/dist/2-core/ds-title.d.ts.map +0 -1
  155. package/dist/2-core/ds-title.js +0 -103
  156. package/dist/2-core/ds-viewtoggle.d.ts +0 -27
  157. package/dist/2-core/ds-viewtoggle.d.ts.map +0 -1
  158. package/dist/2-core/ds-viewtoggle.js +0 -49
  159. package/dist/2-core/ds-year.d.ts.map +0 -1
  160. package/dist/2-core/header-v1.d.ts +0 -28
  161. package/dist/2-core/header-v1.d.ts.map +0 -1
  162. package/dist/2-core/header-v1.js +0 -66
  163. package/dist/2-core/home-v1.d.ts +0 -26
  164. package/dist/2-core/home-v1.d.ts.map +0 -1
  165. package/dist/2-core/home-v1.js +0 -148
  166. package/dist/2-core/icon-v1.d.ts +0 -28
  167. package/dist/2-core/icon-v1.d.ts.map +0 -1
  168. package/dist/2-core/icon-v1.js +0 -297
  169. package/dist/2-core/link-v1.d.ts +0 -35
  170. package/dist/2-core/link-v1.d.ts.map +0 -1
  171. package/dist/2-core/link-v1.js +0 -85
  172. package/dist/2-core/markdown-v1.d.ts +0 -7
  173. package/dist/2-core/markdown-v1.d.ts.map +0 -1
  174. package/dist/2-core/markdown-v1.js +0 -240
  175. package/dist/2-core/price-v1.d.ts +0 -46
  176. package/dist/2-core/price-v1.d.ts.map +0 -1
  177. package/dist/2-core/price-v1.js +0 -72
  178. package/dist/2-core/squarecircle-v1.d.ts +0 -50
  179. package/dist/2-core/squarecircle-v1.d.ts.map +0 -1
  180. package/dist/2-core/squarecircle-v1.js +0 -133
  181. package/dist/2-core/text-v1.d.ts +0 -48
  182. package/dist/2-core/text-v1.d.ts.map +0 -1
  183. package/dist/2-core/text-v1.js +0 -83
  184. package/dist/2-core/title-v1.d.ts +0 -50
  185. package/dist/2-core/title-v1.d.ts.map +0 -1
  186. package/dist/2-core/title-v1.js +0 -103
  187. package/dist/2-core/tooltip-v1.d.ts +0 -39
  188. package/dist/2-core/tooltip-v1.d.ts.map +0 -1
  189. package/dist/2-core/tooltip-v1.js +0 -145
  190. package/dist/2-core/viewtoggle-v1.d.ts +0 -27
  191. package/dist/2-core/viewtoggle-v1.d.ts.map +0 -1
  192. package/dist/2-core/viewtoggle-v1.js +0 -49
  193. package/dist/2-core/year-v1.d.ts +0 -16
  194. package/dist/2-core/year-v1.d.ts.map +0 -1
  195. package/dist/2-core/year-v1.js +0 -21
  196. package/dist/3-unit/ds-doublenav.d.ts.map +0 -1
  197. package/dist/3-unit/ds-panel.d.ts.map +0 -1
  198. package/dist/3-unit/ds-singlenav.d.ts.map +0 -1
  199. package/dist/utils/cdn-loader.d.ts +0 -19
  200. package/dist/utils/cdn-loader.d.ts.map +0 -1
  201. package/dist/utils/cdn-loader.js +0 -142
  202. package/dist/utils/keys.json +0 -41
  203. package/dist/utils/language.d.ts.map +0 -1
  204. package/dist/utils/pricing.d.ts +0 -8
  205. package/dist/utils/pricing.d.ts.map +0 -1
  206. package/dist/utils/pricing.js +0 -14
  207. package/dist/utils/scroll.d.ts +0 -34
  208. package/dist/utils/scroll.d.ts.map +0 -1
  209. package/dist/utils/scroll.js +0 -140
  210. package/dist/utils/settings.d.ts +0 -9
  211. package/dist/utils/settings.d.ts.map +0 -1
  212. package/dist/utils/settings.js +0 -14
  213. package/dist/utils/theme.d.ts.map +0 -1
  214. package/dist/utils/viewMode.d.ts +0 -14
  215. package/dist/utils/viewMode.d.ts.map +0 -1
  216. package/dist/utils/viewMode.js +0 -46
  217. /package/DS1/{utils → 0-face}/theme.ts +0 -0
  218. /package/DS1/{x Icon → x-icon}/1x.svg +0 -0
  219. /package/DS1/{x Icon → x-icon}/1xdots.svg +0 -0
  220. /package/DS1/{x Icon → x-icon}/1xgrid.svg +0 -0
  221. /package/DS1/{x Icon → x-icon}/1xlines.svg +0 -0
  222. /package/DS1/{x Icon → x-icon}/2x.svg +0 -0
  223. /package/DS1/{x Icon → x-icon}/2xdots.svg +0 -0
  224. /package/DS1/{x Icon → x-icon}/2xgrid.svg +0 -0
  225. /package/DS1/{x Icon → x-icon}/2xlines.svg +0 -0
  226. /package/DS1/{x Icon → x-icon}/big.svg +0 -0
  227. /package/DS1/{x Icon → x-icon}/blank.svg +0 -0
  228. /package/DS1/{x Icon → x-icon}/check.svg +0 -0
  229. /package/DS1/{x Icon → x-icon}/close.svg +0 -0
  230. /package/DS1/{x Icon → x-icon}/collapse.svg +0 -0
  231. /package/DS1/{x Icon → x-icon}/color.svg +0 -0
  232. /package/DS1/{x Icon → x-icon}/column.svg +0 -0
  233. /package/DS1/{x Icon → x-icon}/default.svg +0 -0
  234. /package/DS1/{x Icon → x-icon}/delete.svg +0 -0
  235. /package/DS1/{x Icon → x-icon}/do.svg +0 -0
  236. /package/DS1/{x Icon → x-icon}/down.svg +0 -0
  237. /package/DS1/{x Icon → x-icon}/duplicate.svg +0 -0
  238. /package/DS1/{x Icon → x-icon}/email.svg +0 -0
  239. /package/DS1/{x Icon → x-icon}/expand.svg +0 -0
  240. /package/DS1/{x Icon → x-icon}/gallery.svg +0 -0
  241. /package/DS1/{x Icon → x-icon}/group.svg +0 -0
  242. /package/DS1/{x Icon → x-icon}/head.svg +0 -0
  243. /package/DS1/{x Icon → x-icon}/icon.svg +0 -0
  244. /package/DS1/{x Icon → x-icon}/left.svg +0 -0
  245. /package/DS1/{x Icon → x-icon}/lock.svg +0 -0
  246. /package/DS1/{x Icon → x-icon}/mic.svg +0 -0
  247. /package/DS1/{x Icon → x-icon}/minimize.svg +0 -0
  248. /package/DS1/{x Icon → x-icon}/more.svg +0 -0
  249. /package/DS1/{x Icon → x-icon}/note.svg +0 -0
  250. /package/DS1/{x Icon → x-icon}/open.svg +0 -0
  251. /package/DS1/{x Icon → x-icon}/page.svg +0 -0
  252. /package/DS1/{x Icon → x-icon}/plus.svg +0 -0
  253. /package/DS1/{x Icon → x-icon}/rewind.svg +0 -0
  254. /package/DS1/{x Icon → x-icon}/right.svg +0 -0
  255. /package/DS1/{x Icon/row..svg → x-icon/row.svg} +0 -0
  256. /package/DS1/{x Icon → x-icon}/search.svg +0 -0
  257. /package/DS1/{x Icon → x-icon}/see.svg +0 -0
  258. /package/DS1/{x Icon → x-icon}/star.svg +0 -0
  259. /package/DS1/{x Icon → x-icon}/title.svg +0 -0
  260. /package/DS1/{x Icon → x-icon}/undo.svg +0 -0
  261. /package/DS1/{x Icon → x-icon}/ungroup.svg +0 -0
  262. /package/DS1/{x Icon → x-icon}/unhead.svg +0 -0
  263. /package/DS1/{x Icon → x-icon}/unicon.svg +0 -0
  264. /package/DS1/{x Icon → x-icon}/unlock.svg +0 -0
  265. /package/DS1/{x Icon → x-icon}/unmic.svg +0 -0
  266. /package/DS1/{x Icon → x-icon}/unsee.svg +0 -0
  267. /package/DS1/{x Icon → x-icon}/unstar.svg +0 -0
  268. /package/DS1/{x Icon → x-icon}/untitle.svg +0 -0
  269. /package/DS1/{x Icon → x-icon}/up.svg +0 -0
  270. /package/dist/{utils → 0-face}/theme.d.ts +0 -0
  271. /package/dist/{utils → 0-face}/theme.js +0 -0
@@ -1,155 +0,0 @@
1
- import { LitElement, html, css } from "lit";
2
- import { getText } from "../utils/language";
3
-
4
- /**
5
- * A component for displaying project/work attributes (year, category, status)
6
- *
7
- * @element ds-attributes
8
- * @prop {string} year - Year key for translation
9
- * @prop {string} category - Category key for translation
10
- * @prop {string} status - Status key for translation
11
- * @prop {string} type - Type of attributes: "project" or "work"
12
- */
13
- export class Attributes extends LitElement {
14
- static get properties() {
15
- return {
16
- year: { type: String, reflect: true },
17
- category: { type: String, reflect: true },
18
- status: { type: String, reflect: true },
19
- type: { type: String, reflect: true },
20
- };
21
- }
22
-
23
- declare year: string;
24
- declare category: string;
25
- declare status: string;
26
- declare type: string;
27
-
28
- private boundHandlers: { languageChanged: EventListener };
29
-
30
- static styles = css`
31
- :host {
32
- display: flex;
33
- flex-direction: row;
34
- gap: calc(16px * var(--scaling-factor));
35
- align-items: flex-start;
36
- }
37
-
38
- .attribute-row {
39
- display: inline-flex;
40
- height: calc(20px * var(--scaling-factor));
41
- padding: 0px calc(2px * var(--scaling-factor));
42
- align-items: flex-start;
43
- gap: calc(5px * var(--scaling-factor));
44
- font-family: var(--typeface);
45
- font-size: calc(14px * var(--scaling-factor));
46
- color: light-dark(var(--slate), var(--slate-dark));
47
- }
48
-
49
- .status-indicator {
50
- width: calc(8px * var(--scaling-factor));
51
- height: calc(8px * var(--scaling-factor));
52
- display: inline-block;
53
- transition:
54
- background 0.2s,
55
- border-radius 0.2s;
56
- }
57
-
58
- .status-indicator.done {
59
- background-color: green;
60
- }
61
-
62
- .status-indicator.ongoing {
63
- background-color: #30adec;
64
- }
65
-
66
- .status-indicator.pending {
67
- background-color: #f6c71c;
68
- }
69
-
70
- .status-indicator.not-started {
71
- background-color: #b1b4b9;
72
- }
73
- `;
74
-
75
- constructor() {
76
- super();
77
- this.year = "";
78
- this.category = "";
79
- this.status = "";
80
- this.type = "project";
81
-
82
- this.boundHandlers = {
83
- languageChanged: (() => {
84
- this.requestUpdate();
85
- }) as EventListener,
86
- };
87
- }
88
-
89
- connectedCallback() {
90
- super.connectedCallback();
91
- window.addEventListener(
92
- "language-changed",
93
- this.boundHandlers.languageChanged
94
- );
95
- }
96
-
97
- disconnectedCallback() {
98
- super.disconnectedCallback();
99
- window.removeEventListener(
100
- "language-changed",
101
- this.boundHandlers.languageChanged
102
- );
103
- }
104
-
105
- _getStatusClass(status: string): string {
106
- if (status.includes("Done")) return "done";
107
- if (status.includes("Ongoing")) return "ongoing";
108
- if (status.includes("Pending")) return "pending";
109
- if (status.includes("NotStarted")) return "not-started";
110
- return "pending";
111
- }
112
-
113
- render() {
114
- return html`
115
- ${this.year
116
- ? html`
117
- <div class="attribute-row">${getText(this.year) || this.year}</div>
118
- `
119
- : ""}
120
- ${this.category
121
- ? html`
122
- <div class="attribute-row">
123
- ${this.type === "work"
124
- ? html`<span
125
- class="status-indicator ${this._getStatusClass(
126
- this.status
127
- )}"
128
- ></span>`
129
- : ""}
130
- ${getText(this.category) || this.category}
131
- </div>
132
- `
133
- : ""}
134
- ${this.status && this.type === "project"
135
- ? html`
136
- <div class="attribute-row">
137
- <span
138
- class="status-indicator ${this._getStatusClass(this.status)}"
139
- ></span>
140
- ${getText(this.status) || this.status}
141
- </div>
142
- `
143
- : ""}
144
- `;
145
- }
146
- }
147
-
148
- customElements.define("ds-attributes", Attributes);
149
-
150
- declare global {
151
- interface HTMLElementTagNameMap {
152
- "ds-attributes": Attributes;
153
- }
154
- }
155
-
@@ -1,146 +0,0 @@
1
- import { LitElement, html, css } from "lit";
2
- import { currentLanguage, translate } from "../utils/language";
3
-
4
- /**
5
- * Download CV button that resolves language-specific URLs
6
- *
7
- * @element ds-downloadcv
8
- * @prop {string} urlEn - URL for English CV
9
- * @prop {string} urlDa - URL for Danish CV
10
- * @prop {string} urlJa - URL for Japanese CV
11
- * @prop {string} filename - Base filename for download (default: "cv")
12
- */
13
- export class DownloadCV extends LitElement {
14
- static properties = {
15
- urlEn: { type: String, attribute: "url-en", reflect: true },
16
- urlDa: { type: String, attribute: "url-da", reflect: true },
17
- urlJa: { type: String, attribute: "url-ja", reflect: true },
18
- filename: { type: String, reflect: true },
19
- _activeUrl: { type: String, state: true },
20
- };
21
-
22
- declare urlEn: string;
23
- declare urlDa: string;
24
- declare urlJa: string;
25
- declare filename: string;
26
- declare _activeUrl: string;
27
-
28
- constructor() {
29
- super();
30
- this.urlEn = "";
31
- this.urlDa = "";
32
- this.urlJa = "";
33
- this.filename = "cv";
34
- this._activeUrl = "";
35
- }
36
-
37
- static styles = css`
38
- :host {
39
- display: inline-flex;
40
- }
41
- `;
42
-
43
- connectedCallback() {
44
- super.connectedCallback();
45
- this._resolveUrl();
46
- window.addEventListener("language-changed", this._handleLanguageChange);
47
- }
48
-
49
- disconnectedCallback() {
50
- super.disconnectedCallback();
51
- window.removeEventListener("language-changed", this._handleLanguageChange);
52
- }
53
-
54
- updated(changed: Map<string, unknown>) {
55
- if (changed.has("urlEn") || changed.has("urlDa") || changed.has("urlJa")) {
56
- this._resolveUrl();
57
- }
58
- }
59
-
60
- private _handleLanguageChange = () => {
61
- this._resolveUrl();
62
- };
63
-
64
- private _resolveUrl() {
65
- const lang = currentLanguage.value || "en-US";
66
- const prefix = (lang.split("-")[0] || "en").toLowerCase();
67
-
68
- let url = "";
69
- if (prefix === "da") url = this.urlDa || this.urlEn || this.urlJa;
70
- else if (prefix === "ja") url = this.urlJa || this.urlEn || this.urlDa;
71
- else url = this.urlEn || this.urlDa || this.urlJa;
72
-
73
- this._activeUrl = url || "";
74
- }
75
-
76
- private async _download() {
77
- if (!this._activeUrl) {
78
- console.warn("[ds-downloadcv] No URL available");
79
- return;
80
- }
81
-
82
- console.log("[ds-downloadcv] Attempting download from:", this._activeUrl);
83
-
84
- try {
85
- // Prefer blob download (reliable filename, works cross-origin with CORS)
86
- const res = await fetch(this._activeUrl, { mode: "cors" });
87
- console.log(
88
- "[ds-downloadcv] Fetch response:",
89
- res.status,
90
- res.statusText
91
- );
92
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
93
- const blob = await res.blob();
94
- const langPrefix = (currentLanguage.value || "en-US")
95
- .split("-")[0]
96
- .toLowerCase();
97
- const fileExt = this._inferExtFromUrl(this._activeUrl) || "pdf";
98
- const name = `${this.filename || "cv"}-${langPrefix}.${fileExt}`;
99
-
100
- const url = URL.createObjectURL(blob);
101
- const a = document.createElement("a");
102
- a.href = url;
103
- a.download = name;
104
- document.body.appendChild(a);
105
- a.click();
106
- a.remove();
107
- URL.revokeObjectURL(url);
108
- console.log("[ds-downloadcv] Download triggered successfully");
109
- } catch (err) {
110
- console.error("[ds-downloadcv] Fetch failed, using fallback:", err);
111
- // Fallback: open the file directly
112
- window.open(this._activeUrl, "_blank", "noopener,noreferrer");
113
- }
114
- }
115
-
116
- private _inferExtFromUrl(u: string): string | null {
117
- const qIndex = u.indexOf("?");
118
- const clean = qIndex >= 0 ? u.slice(0, qIndex) : u;
119
- const dot = clean.lastIndexOf(".");
120
- if (dot === -1) return null;
121
- const ext = clean.slice(dot + 1).toLowerCase();
122
- if (ext.length > 5) return null;
123
- return ext;
124
- }
125
-
126
- render() {
127
- const disabled = !this._activeUrl;
128
- return html`
129
- <ds-button
130
- variant="primary"
131
- .disabled=${disabled}
132
- default-text=${translate("downloadCV")}
133
- @click=${() => this._download()}
134
- ></ds-button>
135
- `;
136
- }
137
- }
138
-
139
- customElements.define("ds-downloadcv", DownloadCV);
140
-
141
- declare global {
142
- interface HTMLElementTagNameMap {
143
- "ds-downloadcv": DownloadCV;
144
- }
145
- }
146
-
@@ -1,82 +0,0 @@
1
- import { LitElement, html, css } from "lit";
2
-
3
- /**
4
- * A component for displaying page headers
5
- *
6
- * @element ds-header
7
- * @prop {string} gridarea - Grid area placement
8
- */
9
- export class Header extends LitElement {
10
- private _gridArea = "";
11
-
12
- static get properties() {
13
- return {
14
- gridarea: { type: String, reflect: true },
15
- };
16
- }
17
-
18
- set gridarea(value: string) {
19
- const oldValue = this._gridArea;
20
- this._gridArea = value;
21
- this.style.gridArea = value;
22
- this.requestUpdate("gridarea", oldValue);
23
- }
24
-
25
- get gridarea(): string {
26
- return this._gridArea;
27
- }
28
-
29
- static styles = css`
30
- :host {
31
- display: flex;
32
- padding: calc(2px * var(--scaling-factor));
33
- align-items: flex-start;
34
- width: 100%;
35
- }
36
-
37
- h2 {
38
- display: flex;
39
- place-content: center;
40
- font-family: var(--typeface);
41
- color: light-dark(var(--black), var(--white));
42
- align-items: center;
43
- font-weight: 500;
44
- font-size: calc(14px * var(--scaling-factor));
45
- margin: 0;
46
- width: 100%;
47
- }
48
-
49
- ::slotted(*) {
50
- margin: 0;
51
- }
52
- `;
53
-
54
- constructor() {
55
- super();
56
- }
57
-
58
- firstUpdated() {
59
- if (this.hasAttribute("gridarea")) {
60
- this.style.gridArea = this.getAttribute("gridarea") || "";
61
- }
62
- }
63
-
64
- render() {
65
- return html`
66
- <h2
67
- style="display: flex; flex-wrap: nowrap; justify-content: space-between; align-items: center; width: 100%;"
68
- >
69
- <slot></slot>
70
- </h2>
71
- `;
72
- }
73
- }
74
-
75
- customElements.define("ds-header", Header);
76
-
77
- declare global {
78
- interface HTMLElementTagNameMap {
79
- "ds-header": Header;
80
- }
81
- }
82
-
@@ -1,168 +0,0 @@
1
- import { LitElement, html, css } from "lit";
2
-
3
- // Home tab button that reveals on hover (active) or stays visible and non-interactive (disabled)
4
- export class Home extends LitElement {
5
- static properties = {
6
- state: { type: String, reflect: true }, // "active" | "disabled"
7
- } as any;
8
-
9
- state: "active" | "disabled" = "active";
10
-
11
- /**
12
- * Ensure Home is always disabled on mobile devices.
13
- * Runs once when the element is connected to the DOM.
14
- */
15
- connectedCallback() {
16
- super.connectedCallback();
17
- if (this._isMobileDevice()) {
18
- this.state = "disabled";
19
- }
20
- }
21
-
22
- /**
23
- * Lightweight mobile detection. Mirrors the app's utility without importing it
24
- * to keep the design system component self-contained.
25
- */
26
- private _isMobileDevice(): boolean {
27
- const nav: any = (globalThis as any).navigator;
28
- const win: any = (globalThis as any).window;
29
- const ua: string =
30
- (nav && (nav.userAgent || nav.vendor)) || (win && win.opera) || "";
31
-
32
- const uaMatchesMobile =
33
- /Mobile|Android|iP(ad|hone|od)|IEMobile|BlackBerry|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)|Windows Phone|Phone|Tablet/i.test(
34
- ua
35
- );
36
-
37
- const touchPoints = (nav && nav.maxTouchPoints) || 0;
38
- const isTouchCapable = touchPoints > 1;
39
- const narrowViewport = win
40
- ? Math.min(win.innerWidth || 0, win.innerHeight || 0) <= 820
41
- : false;
42
-
43
- return uaMatchesMobile || (isTouchCapable && narrowViewport);
44
- }
45
-
46
- protected updated(): void {
47
- // Enforce disabled on mobile even if someone flips the state later
48
- if (this._isMobileDevice() && this.state !== "disabled") {
49
- this.state = "disabled";
50
- }
51
- }
52
-
53
- static styles = css`
54
- :host {
55
- /* local sizing vars, derived from one.css */
56
- --home-visible: calc(var(--1) * 0.1); /* 2px */
57
-
58
- position: relative;
59
- display: flex; /* expand hover zone horizontally */
60
- width: 100%; /* take the whole row width of the app container */
61
- height: calc(
62
- var(--1) * var(--scaling-factor)
63
- ); /* provide hover zone under the tab */
64
- font-family: var(--typeface);
65
- overflow: hidden; /* hide the part above the host */
66
- }
67
-
68
- /* Disabled: preserve full hover area space but keep inactive */
69
- :host([state="disabled"]) {
70
- height: var(--1); /* keep same layout height as active */
71
- overflow: hidden;
72
- }
73
-
74
- .home {
75
- position: absolute;
76
- left: 0;
77
- width: calc(var(--4) * var(--scaling-factor));
78
- height: calc(var(--1) * var(--scaling-factor));
79
- margin: 0 calc(var(--1) * var(--scaling-factor));
80
- display: flex;
81
- align-items: center;
82
- background: var(--accent-color);
83
- color: light-dark(var(--black), var(--black));
84
- user-select: none;
85
- transition: top 120ms ease;
86
- }
87
-
88
- /* Inner text spacing without affecting the 80px outer width */
89
- .home > ds-text {
90
- padding: 0 calc(var(--1) * 0.15 * var(--scaling-factor));
91
- box-sizing: border-box;
92
- height: 100%;
93
- display: inline-flex;
94
- align-items: center;
95
- }
96
-
97
- /* invisible flex filler to extend hover area to the right */
98
- .hover-fill {
99
- flex: 1 1 auto;
100
- }
101
-
102
- /* Active: hidden until hover */
103
- .home.is-active {
104
- cursor: pointer;
105
- /* Hide above, leave a 2px strip visible */
106
- top: calc(var(--home-visible) - var(--1));
107
- }
108
-
109
- /* Reveal the tab when hovering anywhere in the host area
110
- (the host is 80x20, while the tab starts hidden above) */
111
- :host(:hover) .home.is-active {
112
- top: 0;
113
- }
114
-
115
- /* Disabled: stays hidden and not interactive */
116
- .home.is-disabled {
117
- top: calc(var(--home-visible) - var(--1));
118
- cursor: default;
119
- pointer-events: none;
120
- color: var(--accent-color);
121
- }
122
-
123
- .label {
124
- font-size: var(--type-size-default);
125
- }
126
- `;
127
-
128
- // No setup needed; `state` defaults to "active" and reflects if provided
129
-
130
- private _navigateHome() {
131
- if (this.state === "disabled") return;
132
- window.location.href = "./home.html";
133
- }
134
-
135
- private _onKeyDown(e: any) {
136
- if (this.state === "disabled") return;
137
- if (e?.key === "Enter" || e?.key === " ") {
138
- e.preventDefault();
139
- this._navigateHome();
140
- }
141
- }
142
-
143
- render() {
144
- const isDisabled = this.state === "disabled";
145
- return html`
146
- <div class="hover-fill"></div>
147
- <div
148
- class="home ${isDisabled ? "is-disabled" : "is-active"}"
149
- role="button"
150
- aria-disabled="${String(isDisabled)}"
151
- tabindex="${isDisabled ? -1 : 0}"
152
- @click="${this._navigateHome}"
153
- @keydown="${this._onKeyDown}"
154
- >
155
- <ds-text key="home"></ds-text>
156
- </div>
157
- `;
158
- }
159
- }
160
-
161
- customElements.define("ds-home", Home);
162
-
163
- declare global {
164
- interface HTMLElementTagNameMap {
165
- "ds-home": Home;
166
- }
167
- }
168
-
@@ -1,121 +0,0 @@
1
- import { LitElement, html, css } from "lit";
2
- import { getText } from "../utils/language";
3
-
4
- /**
5
- * A component for creating localized links that open in new tabs
6
- *
7
- * @element ds-link
8
- * @prop {string} href - The URL to link to
9
- */
10
- export class Link extends LitElement {
11
- static get properties() {
12
- return {
13
- href: { type: String, reflect: true },
14
- _text: { type: String, state: true },
15
- };
16
- }
17
-
18
- declare href: string;
19
- declare _text: string;
20
-
21
- private boundHandlers: { languageChanged: EventListener };
22
-
23
- constructor() {
24
- super();
25
- this.href = "";
26
- this._text = "";
27
-
28
- // Create bound event handlers for proper cleanup
29
- this.boundHandlers = {
30
- languageChanged: (() => {
31
- this._loadText();
32
- }) as EventListener,
33
- };
34
- }
35
-
36
- static styles = css`
37
- :host {
38
- display: inline;
39
- font-family: var(--typeface);
40
- }
41
-
42
- a {
43
- color: inherit;
44
- text-decoration: none;
45
- }
46
-
47
- ds-icon {
48
- display: inline-block;
49
- vertical-align: middle;
50
- }
51
- `;
52
-
53
- connectedCallback() {
54
- super.connectedCallback();
55
- this._loadText();
56
-
57
- // Listen for language changes
58
- window.addEventListener(
59
- "language-changed",
60
- this.boundHandlers.languageChanged
61
- );
62
-
63
- // Also listen for translations loaded event
64
- window.addEventListener(
65
- "translations-loaded",
66
- this.boundHandlers.languageChanged
67
- );
68
- }
69
-
70
- disconnectedCallback() {
71
- super.disconnectedCallback();
72
- window.removeEventListener(
73
- "language-changed",
74
- this.boundHandlers.languageChanged
75
- );
76
- window.removeEventListener(
77
- "translations-loaded",
78
- this.boundHandlers.languageChanged
79
- );
80
- }
81
-
82
- updated(changedProperties: Map<string, unknown>) {
83
- super.updated(changedProperties);
84
-
85
- if (changedProperties.has("href")) {
86
- this._loadText();
87
- }
88
- }
89
-
90
- _loadText() {
91
- try {
92
- const text = getText("link");
93
- this._text = text || "Link";
94
- } catch (error) {
95
- console.error("Error loading text for key 'link':", error);
96
- this._text = "Link";
97
- }
98
- this.requestUpdate();
99
- }
100
-
101
- render() {
102
- if (!this.href) {
103
- return html`<span>${this._text}</span>`;
104
- }
105
-
106
- return html`
107
- <a href="${this.href}" target="_blank" rel="noopener noreferrer">
108
- ${this._text}
109
- <ds-icon type="open"></ds-icon>
110
- </a>
111
- `;
112
- }
113
- }
114
-
115
- customElements.define("ds-link", Link);
116
-
117
- declare global {
118
- interface HTMLElementTagNameMap {
119
- "ds-link": Link;
120
- }
121
- }