ds-one 0.2.0-alpha.2 → 0.2.5-alpha.1

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 (247) hide show
  1. package/DS1/{utils/language.ts → 0-face/i18n.ts} +197 -2
  2. package/DS1/0-face/preferences.ts +23 -0
  3. package/DS1/0-face/pricing.ts +57 -0
  4. package/DS1/1-root/one.css +1 -1
  5. package/DS1/2-core/ds-button.ts +1 -1
  6. package/DS1/2-core/ds-cycle.ts +17 -18
  7. package/DS1/2-core/{ds-year.ts → ds-date.ts} +4 -4
  8. package/DS1/2-core/ds-input.ts +1 -0
  9. package/DS1/2-core/ds-text.ts +1 -1
  10. package/DS1/2-core/ds-tooltip.ts +4 -3
  11. package/DS1/3-unit/doublenav-v1.ts +105 -0
  12. package/DS1/3-unit/{ds-doublenav.ts → ds-portfolio-doublenav.ts} +4 -5
  13. package/DS1/3-unit/ds-portfolio-panel.ts +27 -0
  14. package/DS1/3-unit/ds-portfolio-singlenav.ts +79 -0
  15. package/DS1/3-unit/list-v1.ts +24 -0
  16. package/DS1/3-unit/{ds-panel.ts → panel-v1.ts} +2 -3
  17. package/DS1/3-unit/row-v1.ts +52 -0
  18. package/DS1/3-unit/{ds-singlenav.ts → singlenav-v1.ts} +4 -5
  19. package/DS1/4-page/ds-grid.ts +1 -1
  20. package/DS1/index.ts +39 -37
  21. package/README.md +3 -3
  22. package/dist/0-face/{2025-04-23-device.d.ts → device.d.ts} +1 -1
  23. package/dist/0-face/device.d.ts.map +1 -0
  24. package/dist/{utils/language.d.ts → 0-face/i18n.d.ts} +1 -1
  25. package/dist/0-face/i18n.d.ts.map +1 -0
  26. package/dist/{utils/language.js → 0-face/i18n.js} +141 -2
  27. package/dist/0-face/preferences.d.ts +9 -0
  28. package/dist/0-face/preferences.d.ts.map +1 -0
  29. package/dist/0-face/preferences.js +14 -0
  30. package/dist/0-face/pricing.d.ts +15 -0
  31. package/dist/0-face/pricing.d.ts.map +1 -0
  32. package/dist/0-face/pricing.js +46 -0
  33. package/dist/0-face/theme.d.ts.map +1 -0
  34. package/dist/2-core/ds-button.js +1 -1
  35. package/dist/2-core/ds-cycle.js +15 -15
  36. package/dist/2-core/{ds-year.d.ts → ds-date.d.ts} +4 -4
  37. package/dist/2-core/ds-date.d.ts.map +1 -0
  38. package/dist/2-core/{ds-year.js → ds-date.js} +4 -4
  39. package/dist/2-core/ds-input.d.ts +1 -0
  40. package/dist/2-core/ds-input.d.ts.map +1 -0
  41. package/dist/2-core/ds-input.js +1 -0
  42. package/dist/2-core/ds-text.js +1 -1
  43. package/dist/2-core/ds-tooltip.d.ts.map +1 -1
  44. package/dist/2-core/ds-tooltip.js +4 -2
  45. package/dist/3-unit/{ds-doublenav.d.ts → ds-portfolio-doublenav.d.ts} +4 -4
  46. package/dist/3-unit/ds-portfolio-doublenav.d.ts.map +1 -0
  47. package/dist/3-unit/{ds-doublenav.js → ds-portfolio-doublenav.js} +4 -4
  48. package/dist/3-unit/{ds-panel.d.ts → ds-portfolio-panel.d.ts} +3 -3
  49. package/dist/3-unit/ds-portfolio-panel.d.ts.map +1 -0
  50. package/dist/3-unit/{ds-panel.js → ds-portfolio-panel.js} +3 -3
  51. package/dist/3-unit/{ds-singlenav.d.ts → ds-portfolio-singlenav.d.ts} +4 -4
  52. package/dist/3-unit/ds-portfolio-singlenav.d.ts.map +1 -0
  53. package/dist/3-unit/{ds-singlenav.js → ds-portfolio-singlenav.js} +4 -4
  54. package/dist/4-page/ds-grid.js +1 -1
  55. package/dist/ds-one.bundle.js +2087 -3806
  56. package/dist/ds-one.bundle.js.map +4 -4
  57. package/dist/ds-one.bundle.min.js +74 -740
  58. package/dist/ds-one.bundle.min.js.map +4 -4
  59. package/dist/index.d.ts +16 -26
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +32 -34
  62. package/package.json +2 -2
  63. package/DS1/0-face/2025-04-23-language.ts +0 -4
  64. package/DS1/2-core/ds-article.ts +0 -454
  65. package/DS1/2-core/ds-attributes.ts +0 -155
  66. package/DS1/2-core/ds-downloadcv.ts +0 -146
  67. package/DS1/2-core/ds-header.ts +0 -82
  68. package/DS1/2-core/ds-home.ts +0 -168
  69. package/DS1/2-core/ds-link.ts +0 -121
  70. package/DS1/2-core/ds-markdown.ts +0 -252
  71. package/DS1/2-core/ds-price.ts +0 -108
  72. package/DS1/2-core/ds-squarecircle.ts +0 -155
  73. package/DS1/2-core/ds-title.ts +0 -139
  74. package/DS1/2-core/ds-viewtoggle.ts +0 -83
  75. package/DS1/utils/cdn-loader.ts +0 -232
  76. package/DS1/utils/keys.json +0 -41
  77. package/DS1/utils/pricing.ts +0 -24
  78. package/DS1/utils/scroll.ts +0 -184
  79. package/DS1/utils/settings.ts +0 -23
  80. package/DS1/utils/viewMode.ts +0 -55
  81. package/dist/0-face/2025-04-23-device.d.ts.map +0 -1
  82. package/dist/0-face/2025-04-23-language.d.ts +0 -1
  83. package/dist/0-face/2025-04-23-language.d.ts.map +0 -1
  84. package/dist/0-face/2025-04-23-language.js +0 -3
  85. package/dist/2-core/article-v1.d.ts +0 -129
  86. package/dist/2-core/article-v1.d.ts.map +0 -1
  87. package/dist/2-core/article-v1.js +0 -361
  88. package/dist/2-core/attributes-v1.d.ts +0 -47
  89. package/dist/2-core/attributes-v1.d.ts.map +0 -1
  90. package/dist/2-core/attributes-v1.js +0 -128
  91. package/dist/2-core/cycle-v1.d.ts +0 -66
  92. package/dist/2-core/cycle-v1.d.ts.map +0 -1
  93. package/dist/2-core/cycle-v1.js +0 -586
  94. package/dist/2-core/downloadcv-v1.d.ts +0 -58
  95. package/dist/2-core/downloadcv-v1.d.ts.map +0 -1
  96. package/dist/2-core/downloadcv-v1.js +0 -119
  97. package/dist/2-core/ds-article.d.ts +0 -129
  98. package/dist/2-core/ds-article.d.ts.map +0 -1
  99. package/dist/2-core/ds-article.js +0 -361
  100. package/dist/2-core/ds-attributes.d.ts +0 -47
  101. package/dist/2-core/ds-attributes.d.ts.map +0 -1
  102. package/dist/2-core/ds-attributes.js +0 -128
  103. package/dist/2-core/ds-button.figma.d.ts +0 -2
  104. package/dist/2-core/ds-button.figma.d.ts.map +0 -1
  105. package/dist/2-core/ds-button.figma.js +0 -6
  106. package/dist/2-core/ds-downloadcv.d.ts +0 -58
  107. package/dist/2-core/ds-downloadcv.d.ts.map +0 -1
  108. package/dist/2-core/ds-downloadcv.js +0 -119
  109. package/dist/2-core/ds-header.d.ts +0 -28
  110. package/dist/2-core/ds-header.d.ts.map +0 -1
  111. package/dist/2-core/ds-header.js +0 -66
  112. package/dist/2-core/ds-home.d.ts +0 -26
  113. package/dist/2-core/ds-home.d.ts.map +0 -1
  114. package/dist/2-core/ds-home.js +0 -148
  115. package/dist/2-core/ds-link.d.ts +0 -35
  116. package/dist/2-core/ds-link.d.ts.map +0 -1
  117. package/dist/2-core/ds-link.js +0 -85
  118. package/dist/2-core/ds-markdown.d.ts +0 -7
  119. package/dist/2-core/ds-markdown.d.ts.map +0 -1
  120. package/dist/2-core/ds-markdown.js +0 -240
  121. package/dist/2-core/ds-price.d.ts +0 -46
  122. package/dist/2-core/ds-price.d.ts.map +0 -1
  123. package/dist/2-core/ds-price.js +0 -72
  124. package/dist/2-core/ds-squarecircle.d.ts +0 -50
  125. package/dist/2-core/ds-squarecircle.d.ts.map +0 -1
  126. package/dist/2-core/ds-squarecircle.js +0 -133
  127. package/dist/2-core/ds-title.d.ts +0 -50
  128. package/dist/2-core/ds-title.d.ts.map +0 -1
  129. package/dist/2-core/ds-title.js +0 -103
  130. package/dist/2-core/ds-viewtoggle.d.ts +0 -27
  131. package/dist/2-core/ds-viewtoggle.d.ts.map +0 -1
  132. package/dist/2-core/ds-viewtoggle.js +0 -49
  133. package/dist/2-core/ds-year.d.ts.map +0 -1
  134. package/dist/2-core/header-v1.d.ts +0 -28
  135. package/dist/2-core/header-v1.d.ts.map +0 -1
  136. package/dist/2-core/header-v1.js +0 -66
  137. package/dist/2-core/home-v1.d.ts +0 -26
  138. package/dist/2-core/home-v1.d.ts.map +0 -1
  139. package/dist/2-core/home-v1.js +0 -148
  140. package/dist/2-core/icon-v1.d.ts +0 -28
  141. package/dist/2-core/icon-v1.d.ts.map +0 -1
  142. package/dist/2-core/icon-v1.js +0 -297
  143. package/dist/2-core/link-v1.d.ts +0 -35
  144. package/dist/2-core/link-v1.d.ts.map +0 -1
  145. package/dist/2-core/link-v1.js +0 -85
  146. package/dist/2-core/markdown-v1.d.ts +0 -7
  147. package/dist/2-core/markdown-v1.d.ts.map +0 -1
  148. package/dist/2-core/markdown-v1.js +0 -240
  149. package/dist/2-core/price-v1.d.ts +0 -46
  150. package/dist/2-core/price-v1.d.ts.map +0 -1
  151. package/dist/2-core/price-v1.js +0 -72
  152. package/dist/2-core/squarecircle-v1.d.ts +0 -50
  153. package/dist/2-core/squarecircle-v1.d.ts.map +0 -1
  154. package/dist/2-core/squarecircle-v1.js +0 -133
  155. package/dist/2-core/text-v1.d.ts +0 -48
  156. package/dist/2-core/text-v1.d.ts.map +0 -1
  157. package/dist/2-core/text-v1.js +0 -83
  158. package/dist/2-core/title-v1.d.ts +0 -50
  159. package/dist/2-core/title-v1.d.ts.map +0 -1
  160. package/dist/2-core/title-v1.js +0 -103
  161. package/dist/2-core/tooltip-v1.d.ts +0 -39
  162. package/dist/2-core/tooltip-v1.d.ts.map +0 -1
  163. package/dist/2-core/tooltip-v1.js +0 -145
  164. package/dist/2-core/viewtoggle-v1.d.ts +0 -27
  165. package/dist/2-core/viewtoggle-v1.d.ts.map +0 -1
  166. package/dist/2-core/viewtoggle-v1.js +0 -49
  167. package/dist/2-core/year-v1.d.ts +0 -16
  168. package/dist/2-core/year-v1.d.ts.map +0 -1
  169. package/dist/2-core/year-v1.js +0 -21
  170. package/dist/3-unit/ds-doublenav.d.ts.map +0 -1
  171. package/dist/3-unit/ds-panel.d.ts.map +0 -1
  172. package/dist/3-unit/ds-singlenav.d.ts.map +0 -1
  173. package/dist/utils/cdn-loader.d.ts +0 -19
  174. package/dist/utils/cdn-loader.d.ts.map +0 -1
  175. package/dist/utils/cdn-loader.js +0 -160
  176. package/dist/utils/keys.json +0 -41
  177. package/dist/utils/language.d.ts.map +0 -1
  178. package/dist/utils/pricing.d.ts +0 -8
  179. package/dist/utils/pricing.d.ts.map +0 -1
  180. package/dist/utils/pricing.js +0 -14
  181. package/dist/utils/scroll.d.ts +0 -34
  182. package/dist/utils/scroll.d.ts.map +0 -1
  183. package/dist/utils/scroll.js +0 -140
  184. package/dist/utils/settings.d.ts +0 -9
  185. package/dist/utils/settings.d.ts.map +0 -1
  186. package/dist/utils/settings.js +0 -14
  187. package/dist/utils/theme.d.ts.map +0 -1
  188. package/dist/utils/viewMode.d.ts +0 -14
  189. package/dist/utils/viewMode.d.ts.map +0 -1
  190. package/dist/utils/viewMode.js +0 -46
  191. /package/DS1/0-face/{2025-04-23-device.ts → device.ts} +0 -0
  192. /package/DS1/{utils → 0-face}/theme.ts +0 -0
  193. /package/DS1/{x Icon → x-icon}/1x.svg +0 -0
  194. /package/DS1/{x Icon → x-icon}/1xdots.svg +0 -0
  195. /package/DS1/{x Icon → x-icon}/1xgrid.svg +0 -0
  196. /package/DS1/{x Icon → x-icon}/1xlines.svg +0 -0
  197. /package/DS1/{x Icon → x-icon}/2x.svg +0 -0
  198. /package/DS1/{x Icon → x-icon}/2xdots.svg +0 -0
  199. /package/DS1/{x Icon → x-icon}/2xgrid.svg +0 -0
  200. /package/DS1/{x Icon → x-icon}/2xlines.svg +0 -0
  201. /package/DS1/{x Icon → x-icon}/big.svg +0 -0
  202. /package/DS1/{x Icon → x-icon}/blank.svg +0 -0
  203. /package/DS1/{x Icon → x-icon}/check.svg +0 -0
  204. /package/DS1/{x Icon → x-icon}/close.svg +0 -0
  205. /package/DS1/{x Icon → x-icon}/collapse.svg +0 -0
  206. /package/DS1/{x Icon → x-icon}/color.svg +0 -0
  207. /package/DS1/{x Icon → x-icon}/column.svg +0 -0
  208. /package/DS1/{x Icon → x-icon}/default.svg +0 -0
  209. /package/DS1/{x Icon → x-icon}/delete.svg +0 -0
  210. /package/DS1/{x Icon → x-icon}/do.svg +0 -0
  211. /package/DS1/{x Icon → x-icon}/down.svg +0 -0
  212. /package/DS1/{x Icon → x-icon}/duplicate.svg +0 -0
  213. /package/DS1/{x Icon → x-icon}/email.svg +0 -0
  214. /package/DS1/{x Icon → x-icon}/expand.svg +0 -0
  215. /package/DS1/{x Icon → x-icon}/gallery.svg +0 -0
  216. /package/DS1/{x Icon → x-icon}/group.svg +0 -0
  217. /package/DS1/{x Icon → x-icon}/head.svg +0 -0
  218. /package/DS1/{x Icon → x-icon}/icon.svg +0 -0
  219. /package/DS1/{x Icon → x-icon}/left.svg +0 -0
  220. /package/DS1/{x Icon → x-icon}/lock.svg +0 -0
  221. /package/DS1/{x Icon → x-icon}/mic.svg +0 -0
  222. /package/DS1/{x Icon → x-icon}/minimize.svg +0 -0
  223. /package/DS1/{x Icon → x-icon}/more.svg +0 -0
  224. /package/DS1/{x Icon → x-icon}/note.svg +0 -0
  225. /package/DS1/{x Icon → x-icon}/open.svg +0 -0
  226. /package/DS1/{x Icon → x-icon}/page.svg +0 -0
  227. /package/DS1/{x Icon → x-icon}/plus.svg +0 -0
  228. /package/DS1/{x Icon → x-icon}/rewind.svg +0 -0
  229. /package/DS1/{x Icon → x-icon}/right.svg +0 -0
  230. /package/DS1/{x Icon → x-icon}/row..svg +0 -0
  231. /package/DS1/{x Icon → x-icon}/search.svg +0 -0
  232. /package/DS1/{x Icon → x-icon}/see.svg +0 -0
  233. /package/DS1/{x Icon → x-icon}/star.svg +0 -0
  234. /package/DS1/{x Icon → x-icon}/title.svg +0 -0
  235. /package/DS1/{x Icon → x-icon}/undo.svg +0 -0
  236. /package/DS1/{x Icon → x-icon}/ungroup.svg +0 -0
  237. /package/DS1/{x Icon → x-icon}/unhead.svg +0 -0
  238. /package/DS1/{x Icon → x-icon}/unicon.svg +0 -0
  239. /package/DS1/{x Icon → x-icon}/unlock.svg +0 -0
  240. /package/DS1/{x Icon → x-icon}/unmic.svg +0 -0
  241. /package/DS1/{x Icon → x-icon}/unsee.svg +0 -0
  242. /package/DS1/{x Icon → x-icon}/unstar.svg +0 -0
  243. /package/DS1/{x Icon → x-icon}/untitle.svg +0 -0
  244. /package/DS1/{x Icon → x-icon}/up.svg +0 -0
  245. /package/dist/0-face/{2025-04-23-device.js → device.js} +0 -0
  246. /package/dist/{utils → 0-face}/theme.d.ts +0 -0
  247. /package/dist/{utils → 0-face}/theme.js +0 -0
@@ -0,0 +1,79 @@
1
+ import { LitElement, html, css } from "lit";
2
+
3
+ /**
4
+ * A component for single navigation links
5
+ *
6
+ * @element portfolio-singlenav
7
+ * @prop {string} type - Type of navigation: "projects" or "work"
8
+ * @prop {string} to - Optional custom destination URL
9
+ */
10
+ export class PortfolioSingleNav extends LitElement {
11
+ static get properties() {
12
+ return {
13
+ type: { type: String, reflect: true },
14
+ to: { type: String, reflect: true },
15
+ };
16
+ }
17
+
18
+ declare type: "projects" | "work";
19
+ declare to?: string;
20
+
21
+ constructor() {
22
+ super();
23
+ this.type = "work";
24
+ }
25
+
26
+ static styles = css`
27
+ :host {
28
+ display: flex;
29
+ justify-content: end;
30
+ gap: calc(5px * var(--scaling-factor));
31
+ padding: calc(2px * var(--scaling-factor));
32
+ align-items: center;
33
+ }
34
+
35
+ a {
36
+ display: inline-flex;
37
+ align-items: center;
38
+ gap: calc(5px * var(--scaling-factor));
39
+ text-decoration: none;
40
+ color: inherit;
41
+ }
42
+ `;
43
+
44
+ render() {
45
+ const navConfig = this.getNavConfig();
46
+ const href = this.to || navConfig.href;
47
+
48
+ return html`
49
+ <a href="${href}">
50
+ <ds-text key="${navConfig.key}"></ds-text>
51
+ <ds-icon type="right"></ds-icon>
52
+ </a>
53
+ `;
54
+ }
55
+
56
+ private getNavConfig() {
57
+ switch (this.type) {
58
+ case "projects":
59
+ return {
60
+ href: "/projects",
61
+ key: "projects",
62
+ };
63
+ case "work":
64
+ return {
65
+ href: "/",
66
+ key: "workExperience",
67
+ };
68
+ }
69
+ }
70
+ }
71
+
72
+ customElements.define("portfolio-singlenav", PortfolioSingleNav);
73
+
74
+ declare global {
75
+ interface HTMLElementTagNameMap {
76
+ "portfolio-singlenav": PortfolioSingleNav;
77
+ }
78
+ }
79
+
@@ -0,0 +1,24 @@
1
+ import { LitElement, html, css } from "lit";
2
+
3
+ export class List extends LitElement {
4
+ static styles = css`
5
+ :host {
6
+ display: flex;
7
+ flex-direction: column;
8
+ gap: 0;
9
+ width: 100%;
10
+ }
11
+ `;
12
+
13
+ render() {
14
+ return html`<slot></slot>`;
15
+ }
16
+ }
17
+
18
+ customElements.define("list-v1", List);
19
+
20
+ declare global {
21
+ interface HTMLElementTagNameMap {
22
+ "list-v1": List;
23
+ }
24
+ }
@@ -17,11 +17,10 @@ export class Panel extends LitElement {
17
17
  }
18
18
  }
19
19
 
20
- customElements.define("ds-panel", Panel);
20
+ customElements.define("panel-v1", Panel);
21
21
 
22
22
  declare global {
23
23
  interface HTMLElementTagNameMap {
24
- "ds-panel": Panel;
24
+ "panel-v1": Panel;
25
25
  }
26
26
  }
27
-
@@ -0,0 +1,52 @@
1
+ import { LitElement, html, css } from "lit";
2
+
3
+ declare global {
4
+ interface CustomElementRegistry {
5
+ define(name: string, constructor: typeof LitElement): void;
6
+ }
7
+ var customElements: CustomElementRegistry;
8
+ }
9
+
10
+ export class Row extends LitElement {
11
+ static properties = {
12
+ type: { type: String, reflect: true },
13
+ };
14
+
15
+ declare type: "fill" | "centered";
16
+
17
+ constructor() {
18
+ super();
19
+ this.type = "fill";
20
+ }
21
+
22
+ static styles = css`
23
+ :host {
24
+ display: flex;
25
+ align-items: end;
26
+ width: calc(240px * var(--scaling-factor));
27
+ }
28
+
29
+ :host([type="fill"]) {
30
+ justify-content: space-between;
31
+ height: calc(var(--1) * var(--scaling-factor));
32
+ }
33
+
34
+ :host([type="centered"]) {
35
+ justify-content: center;
36
+ height: calc(var(--1) * var(--scaling-factor));
37
+ gap: calc(var(--025) * var(--scaling-factor));
38
+ }
39
+ `;
40
+
41
+ render() {
42
+ return html`<slot></slot>`;
43
+ }
44
+ }
45
+
46
+ customElements.define("row-v1", Row);
47
+
48
+ declare global {
49
+ interface HTMLElementTagNameMap {
50
+ "row-v1": Row;
51
+ }
52
+ }
@@ -3,7 +3,7 @@ import { LitElement, html, css } from "lit";
3
3
  /**
4
4
  * A component for single navigation links
5
5
  *
6
- * @element ds-singlenav
6
+ * @element singlenav-v1
7
7
  * @prop {string} type - Type of navigation: "projects" or "work"
8
8
  * @prop {string} to - Optional custom destination URL
9
9
  */
@@ -48,7 +48,7 @@ export class SingleNav extends LitElement {
48
48
  return html`
49
49
  <a href="${href}">
50
50
  <ds-text key="${navConfig.key}"></ds-text>
51
- <ds-icon type="right"></ds-icon>
51
+ <icon-v1 type="right"></icon-v1>
52
52
  </a>
53
53
  `;
54
54
  }
@@ -69,11 +69,10 @@ export class SingleNav extends LitElement {
69
69
  }
70
70
  }
71
71
 
72
- customElements.define("ds-singlenav", SingleNav);
72
+ customElements.define("singlenav-v1", SingleNav);
73
73
 
74
74
  declare global {
75
75
  interface HTMLElementTagNameMap {
76
- "ds-singlenav": SingleNav;
76
+ "singlenav-v1": SingleNav;
77
77
  }
78
78
  }
79
-
@@ -2,7 +2,7 @@
2
2
  // Simple grid layout component
3
3
 
4
4
  import { LitElement, html, css } from "lit";
5
- import { detectMobileDevice } from "../0-face/2025-04-23-device";
5
+ import { detectMobileDevice } from "../0-face/device";
6
6
 
7
7
  declare global {
8
8
  interface CustomElementRegistry {
package/DS1/index.ts CHANGED
@@ -1,50 +1,52 @@
1
- // DS one - Main entry point for all components
2
- // Export all components for easy importing
1
+ /**
2
+ * DS one - Main entry point for all components
3
+ *
4
+ * This module initializes core utilities and exports all design system components
5
+ * organized by layer: 0-face (foundation), 2-core (components), 3-unit (composites), 4-page (layouts)
6
+ */
7
+
8
+ // ============================================================================
9
+ // Initialization (side-effect imports)
10
+ // ============================================================================
3
11
 
4
12
  // Initialize device detection (will auto-detect and log on load)
5
- import "./0-face/2025-04-23-device";
13
+ import "./0-face/device";
14
+
15
+ // Initialize language utilities (will auto-load external translations if available)
16
+ import "./0-face/i18n";
17
+
18
+ // ============================================================================
19
+ // 0-face: Foundation & Utilities
20
+ // ============================================================================
21
+
22
+ export * from "./0-face/device";
23
+ export * from "./0-face/i18n";
24
+ export * from "./0-face/preferences";
25
+ export * from "./0-face/pricing";
26
+ export * from "./0-face/theme";
6
27
 
7
- // Initialize CDN loader (will auto-load external translations if available)
8
- import "./utils/cdn-loader";
28
+ // ============================================================================
29
+ // 2-core: Core Components
30
+ // ============================================================================
9
31
 
10
- // Core components
11
32
  export * from "./2-core/ds-button";
12
- export * from "./2-core/ds-text";
13
- export * from "./2-core/ds-icon";
14
- export * from "./2-core/ds-link";
15
33
  export * from "./2-core/ds-cycle";
34
+ export * from "./2-core/ds-icon";
35
+ export * from "./2-core/ds-text";
16
36
  export * from "./2-core/ds-tooltip";
17
- export * from "./2-core/ds-price";
18
- export * from "./2-core/ds-markdown";
19
- export * from "./2-core/ds-home";
20
- export * from "./2-core/ds-year";
21
- export * from "./2-core/ds-title";
22
- export * from "./2-core/ds-header";
23
- export * from "./2-core/ds-attributes";
24
- export * from "./2-core/ds-downloadcv";
25
- export * from "./2-core/ds-article";
26
- export * from "./2-core/ds-viewtoggle";
27
- export * from "./2-core/ds-squarecircle";
28
-
29
- // Unit components
37
+ export * from "./2-core/ds-date";
38
+
39
+ // ============================================================================
40
+ // 3-unit: Composite Components
41
+ // ============================================================================
42
+
30
43
  export * from "./3-unit/ds-list";
31
- export * from "./3-unit/ds-panel";
32
44
  export * from "./3-unit/ds-row";
33
- export * from "./3-unit/ds-singlenav";
34
- export * from "./3-unit/ds-doublenav";
35
45
  export * from "./3-unit/ds-table";
36
46
 
37
- // Page components
47
+ // ============================================================================
48
+ // 4-page: Layout Components
49
+ // ============================================================================
50
+
38
51
  export * from "./4-page/ds-grid";
39
52
  export * from "./4-page/ds-layout";
40
-
41
- // Utilities
42
- export * from "./utils/language";
43
- export * from "./utils/theme";
44
- export * from "./utils/viewMode";
45
- export * from "./utils/settings";
46
- export * from "./utils/pricing";
47
- export * from "./utils/scroll";
48
-
49
- // Device detection
50
- export * from "./0-face/2025-04-23-device";
package/README.md CHANGED
@@ -26,7 +26,7 @@ npm install ds-one@alpha
26
26
  yarn add ds-one@alpha
27
27
  ```
28
28
 
29
- **Note**: Currently published as alpha version `0.2.0-alpha.2`. Use `@alpha` tag to install.
29
+ **Note**: Currently published as alpha version `0.2.0-alpha.3`. Use `@alpha` tag to install.
30
30
 
31
31
  ### Basic Usage (CDN)
32
32
 
@@ -86,7 +86,7 @@ Try DS one in your browser: **[dsone.dev](https://dsone.dev)** (documentation sl
86
86
  - **[Internationalization](./docs/i18n.md)** - Language keys and Notion CMS setup
87
87
  - **[Examples](./docs/examples.md)** - Usage examples and patterns
88
88
 
89
- ## Current Status: v0.2.0-alpha.2
89
+ ## Current Status: v0.2.0-alpha.3
90
90
 
91
91
  **⚠️ Alpha Release**: This is an early alpha version. The API may change as we refine the components and architecture.
92
92
 
@@ -183,7 +183,7 @@ bun run build
183
183
 
184
184
  ```bash
185
185
  # Create a new alpha release (recommended for now)
186
- bun run release:pre:alpha # Bumps alpha version (e.g., 0.2.0-alpha.2 → 0.2.0-alpha.2)
186
+ bun run release:pre:alpha # Bumps alpha version (e.g., 0.2.0-alpha.3 → 0.2.0-alpha.3)
187
187
 
188
188
  # Other release commands (for future use)
189
189
  bun run release:patch # For patch releases
@@ -22,4 +22,4 @@ export declare function getDeviceInfo(): DeviceInfo;
22
22
  * Initialize device detection and log to console
23
23
  */
24
24
  export declare function initDeviceDetection(): DeviceInfo;
25
- //# sourceMappingURL=2025-04-23-device.d.ts.map
25
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../DS1/0-face/device.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CA0B5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,UAAU,CA6B1C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,UAAU,CA8ChD"}
@@ -26,4 +26,4 @@ export declare function getAvailableLanguagesSync(): LanguageCode[];
26
26
  export declare function loadTranslations(language: LanguageCode, translations: TranslationData): void;
27
27
  export declare function setLanguage(language: LanguageCode): void;
28
28
  export {};
29
- //# sourceMappingURL=language.d.ts.map
29
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../DS1/0-face/i18n.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC;AAGlC,KAAK,eAAe,GAAG;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAAC;AAyDF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;QACtD,wBAAwB,CAAC,EAAE,MAAM,CAAC;KACnC;CACF;AAkSD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,MAAM,CA6CR;AAwDD,wBAAgB,kBAAkB,IAAI,YAAY,CAwBjD;AAWD,eAAO,MAAM,eAAe;;gBAGL,YAAY;CAWlC,CAAC;AAyDF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAe7C;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,YAAoC,GAC7C,OAAO,CAmBT;AAGD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAGD,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,QAAQ,GAAE,YAAoC,GAC7C,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAGD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,YAAoC,GAC7C,IAAI,CAKN;AAUD,wBAAgB,qBAAqB,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAS/D;AAGD,wBAAgB,yBAAyB,IAAI,YAAY,EAAE,CAO1D;AAGD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,YAAY,EACtB,YAAY,EAAE,eAAe,GAC5B,IAAI,CAON;AAGD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAgBxD"}
@@ -1,5 +1,6 @@
1
- // Import the JSON directly to ensure it's bundled
2
- import translationKeys from "./keys.json";
1
+ // Bundled translations (keys.json may not exist - will use external translations if not available)
2
+ // This is a fallback for when external translations aren't loaded
3
+ let translationKeys = {};
3
4
  // Primary language list – prioritise the 10 requested languages when cycling
4
5
  const LANGUAGE_PRIORITY_ORDER = [
5
6
  "da",
@@ -42,6 +43,131 @@ const FALLBACK_LANGUAGE_NAMES = {
42
43
  };
43
44
  const DISPLAY_NAME_CACHE = new Map();
44
45
  let displayNameFallbackWarningShown = false;
46
+ // CDN Loader: Automatically detects and loads translation JSON files
47
+ // for CDN users who want to use external translations
48
+ const DEFAULT_TRANSLATION_FILE = "./translations.json";
49
+ let loadAttempted = false;
50
+ function normalizeCandidate(path) {
51
+ if (!path) {
52
+ return null;
53
+ }
54
+ const trimmed = path.trim();
55
+ if (!trimmed) {
56
+ return null;
57
+ }
58
+ if (trimmed.startsWith("./") ||
59
+ trimmed.startsWith("../") ||
60
+ trimmed.startsWith("/") ||
61
+ /^https?:\/\//i.test(trimmed)) {
62
+ return trimmed;
63
+ }
64
+ return `./${trimmed}`;
65
+ }
66
+ function findAttributeCandidate() {
67
+ if (typeof document === "undefined") {
68
+ return null;
69
+ }
70
+ const scriptWithAttribute = document.querySelector("script[data-ds-one-translations]");
71
+ const scriptCandidate = scriptWithAttribute?.getAttribute("data-ds-one-translations");
72
+ if (scriptCandidate) {
73
+ return scriptCandidate;
74
+ }
75
+ const metaCandidate = document
76
+ .querySelector('meta[name="ds-one:translations"]')
77
+ ?.getAttribute("content");
78
+ if (metaCandidate) {
79
+ return metaCandidate;
80
+ }
81
+ const linkCandidate = document
82
+ .querySelector('link[rel="ds-one-translations"]')
83
+ ?.getAttribute("href");
84
+ if (linkCandidate) {
85
+ return linkCandidate;
86
+ }
87
+ return null;
88
+ }
89
+ function resolveTranslationSources() {
90
+ const candidates = [];
91
+ const windowCandidate = typeof window !== "undefined" ? window.DS_ONE_TRANSLATIONS_FILE : null;
92
+ const attributeCandidate = findAttributeCandidate();
93
+ // Only use explicitly configured paths, or the single default
94
+ const windowNormalized = normalizeCandidate(windowCandidate ?? "");
95
+ if (windowNormalized) {
96
+ candidates.push(windowNormalized);
97
+ }
98
+ const attrNormalized = normalizeCandidate(attributeCandidate ?? "");
99
+ if (attrNormalized && !candidates.includes(attrNormalized)) {
100
+ candidates.push(attrNormalized);
101
+ }
102
+ // Only try default if no explicit path was configured
103
+ if (candidates.length === 0) {
104
+ candidates.push(DEFAULT_TRANSLATION_FILE);
105
+ }
106
+ return candidates;
107
+ }
108
+ function validateTranslationMap(candidate) {
109
+ if (!candidate || typeof candidate !== "object") {
110
+ return false;
111
+ }
112
+ return Object.values(candidate).every((entry) => entry && typeof entry === "object");
113
+ }
114
+ async function fetchTranslationFile(source) {
115
+ try {
116
+ const response = await fetch(source);
117
+ if (!response.ok) {
118
+ // 404 is expected if no translations file exists - don't log as error
119
+ return null;
120
+ }
121
+ const translations = await response.json();
122
+ if (!validateTranslationMap(translations)) {
123
+ console.warn(`[DS one] Invalid translation format in ${source}. Expected object with language codes as keys.`);
124
+ return null;
125
+ }
126
+ const languages = Object.keys(translations);
127
+ if (languages.length === 0) {
128
+ console.warn(`[DS one] No languages found in ${source}`);
129
+ return null;
130
+ }
131
+ return translations;
132
+ }
133
+ catch {
134
+ // Silently fail - file likely doesn't exist or isn't valid JSON
135
+ return null;
136
+ }
137
+ }
138
+ /**
139
+ * Attempts to load translations from a JSON file in the same directory
140
+ */
141
+ async function loadExternalTranslations() {
142
+ // Only attempt once
143
+ if (loadAttempted) {
144
+ return false;
145
+ }
146
+ loadAttempted = true;
147
+ if (typeof window === "undefined") {
148
+ return false;
149
+ }
150
+ // Check if translations are already loaded (e.g., by the application)
151
+ if (window.DS_ONE_TRANSLATIONS &&
152
+ Object.keys(window.DS_ONE_TRANSLATIONS).length > 0) {
153
+ console.log(`[DS one] Translations already loaded (${Object.keys(window.DS_ONE_TRANSLATIONS).length} languages), skipping auto-load`);
154
+ return true;
155
+ }
156
+ const sources = resolveTranslationSources();
157
+ for (const source of sources) {
158
+ const translations = await fetchTranslationFile(source);
159
+ if (!translations) {
160
+ continue;
161
+ }
162
+ window.DS_ONE_TRANSLATIONS = translations;
163
+ const languages = Object.keys(translations);
164
+ console.log(`[DS one] External translations loaded from ${source}: ${languages.length} language(s) – ${languages.join(", ")}`);
165
+ window.dispatchEvent(new CustomEvent("translations-ready"));
166
+ return true;
167
+ }
168
+ console.info(`[DS one] No external translations found at ${sources[0] ?? DEFAULT_TRANSLATION_FILE}. Using bundled translations.`);
169
+ return false;
170
+ }
45
171
  // Get translation data - prioritize external, fall back to bundled
46
172
  function getTranslationData() {
47
173
  // Check for externally loaded translations first (CDN usage)
@@ -245,6 +371,19 @@ export const currentLanguage = {
245
371
  }));
246
372
  },
247
373
  };
374
+ // Auto-load translations when this module is imported (for CDN bundle)
375
+ if (typeof window !== "undefined") {
376
+ // Wait a bit to ensure the DOM is ready
377
+ if (document.readyState === "loading") {
378
+ document.addEventListener("DOMContentLoaded", () => {
379
+ loadExternalTranslations();
380
+ });
381
+ }
382
+ else {
383
+ // DOM is already ready
384
+ loadExternalTranslations();
385
+ }
386
+ }
248
387
  // Listen for external translations being loaded
249
388
  if (typeof window !== "undefined") {
250
389
  window.addEventListener("translations-ready", () => {
@@ -0,0 +1,9 @@
1
+ import type { LanguageCode } from "./i18n";
2
+ import type { ThemeType } from "./theme";
3
+ export type Preferences = {
4
+ language?: LanguageCode;
5
+ theme?: ThemeType;
6
+ [key: string]: unknown;
7
+ };
8
+ export declare function savePreferences(preferences: Preferences): void;
9
+ //# sourceMappingURL=preferences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../DS1/0-face/preferences.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAgB,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAa9D"}
@@ -0,0 +1,14 @@
1
+ export function savePreferences(preferences) {
2
+ if (typeof window === "undefined") {
3
+ return;
4
+ }
5
+ try {
6
+ const raw = window.localStorage?.getItem("ds-one:preferences");
7
+ const existing = raw ? JSON.parse(raw) : {};
8
+ const next = { ...existing, ...preferences };
9
+ window.localStorage?.setItem("ds-one:preferences", JSON.stringify(next));
10
+ }
11
+ catch (error) {
12
+ console.warn("ds-one: unable to persist preferences", error);
13
+ }
14
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Currency label utilities for regional price display
3
+ *
4
+ * Note: This module provides currency symbols/labels based on language and region.
5
+ * Consider moving this functionality into i18n.ts as it's region/locale-related.
6
+ * Actual price values will be stored in a database or managed via Stripe.
7
+ */
8
+ import type { LanguageCode } from "./i18n";
9
+ type PriceLabelOptions = {
10
+ language: LanguageCode;
11
+ country?: string;
12
+ };
13
+ export declare function getPriceLabel(options: PriceLabelOptions): string;
14
+ export {};
15
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../DS1/0-face/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,KAAK,iBAAiB,GAAG;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAgBF,wBAAgB,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA2BhE"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Currency label utilities for regional price display
3
+ *
4
+ * Note: This module provides currency symbols/labels based on language and region.
5
+ * Consider moving this functionality into i18n.ts as it's region/locale-related.
6
+ * Actual price values will be stored in a database or managed via Stripe.
7
+ */
8
+ // Simple price label mapping based on language/country
9
+ const PRICE_LABELS = {
10
+ da: "kr.",
11
+ nb: "kr.",
12
+ sv: "kr.",
13
+ de: "€",
14
+ en: "$",
15
+ pt: "€",
16
+ es: "€",
17
+ zh: "¥",
18
+ ja: "¥",
19
+ ko: "₩",
20
+ };
21
+ export function getPriceLabel(options) {
22
+ const { language, country } = options;
23
+ // If country is provided, try to map it to a currency
24
+ if (country) {
25
+ const countryUpper = country.toUpperCase();
26
+ // Add country-specific mappings if needed
27
+ if (countryUpper === "US" || countryUpper === "USA") {
28
+ return "$";
29
+ }
30
+ if (countryUpper === "GB" || countryUpper === "UK") {
31
+ return "£";
32
+ }
33
+ if (countryUpper === "JP" || countryUpper === "JPN") {
34
+ return "¥";
35
+ }
36
+ if (countryUpper === "CN" || countryUpper === "CHN") {
37
+ return "¥";
38
+ }
39
+ if (countryUpper === "KR" || countryUpper === "KOR") {
40
+ return "₩";
41
+ }
42
+ }
43
+ // Fall back to language-based mapping
44
+ const primaryLang = language.toLowerCase().split(/[-_]/)[0];
45
+ return PRICE_LABELS[primaryLang] || "$";
46
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../DS1/0-face/theme.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAiBzC,eAAO,MAAM,YAAY,qDAAuC,CAAC;AAEjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAwB/C"}
@@ -1,7 +1,7 @@
1
1
  // ds-button.ts
2
2
  // Core button component
3
3
  import { LitElement, html, css } from "lit";
4
- import { getText } from "../utils/language";
4
+ import { getText } from "../0-face/i18n";
5
5
  export class Button extends LitElement {
6
6
  constructor() {
7
7
  super();