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

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 (90) hide show
  1. package/DS1/1-root/one.css +1 -1
  2. package/DS1/2-core/{article-v1.ts → ds-article.ts} +5 -4
  3. package/DS1/2-core/{attributes-v1.ts → ds-attributes.ts} +4 -3
  4. package/DS1/2-core/{cycle-v1.ts → ds-cycle.ts} +11 -10
  5. package/DS1/2-core/{downloadcv-v1.ts → ds-downloadcv.ts} +9 -8
  6. package/DS1/2-core/{header-v1.ts → ds-header.ts} +4 -3
  7. package/DS1/2-core/{home-v1.ts → ds-home.ts} +3 -2
  8. package/DS1/2-core/{icon-v1.ts → ds-icon.ts} +2 -2
  9. package/DS1/2-core/{link-v1.ts → ds-link.ts} +5 -5
  10. package/DS1/2-core/{markdown-v1.ts → ds-markdown.ts} +3 -2
  11. package/DS1/2-core/{price-v1.ts → ds-price.ts} +4 -3
  12. package/DS1/2-core/{squarecircle-v1.ts → ds-squarecircle.ts} +4 -3
  13. package/DS1/2-core/{title-v1.ts → ds-title.ts} +5 -4
  14. package/DS1/2-core/{tooltip-v1.ts → ds-tooltip.ts} +4 -3
  15. package/DS1/2-core/{viewtoggle-v1.ts → ds-viewtoggle.ts} +4 -3
  16. package/DS1/2-core/{year-v1.ts → ds-year.ts} +4 -3
  17. package/DS1/3-unit/{doublenav-v1.ts → ds-doublenav.ts} +9 -8
  18. package/DS1/3-unit/{list-v1.ts → ds-list.ts} +3 -2
  19. package/DS1/3-unit/{panel-v1.ts → ds-panel.ts} +3 -2
  20. package/DS1/3-unit/{row-v1.ts → ds-row.ts} +3 -2
  21. package/DS1/3-unit/{singlenav-v1.ts → ds-singlenav.ts} +5 -4
  22. package/DS1/index.ts +20 -20
  23. package/README.md +4 -4
  24. package/dist/2-core/ds-article.d.ts +129 -0
  25. package/dist/2-core/ds-article.d.ts.map +1 -0
  26. package/dist/2-core/ds-article.js +361 -0
  27. package/dist/2-core/ds-attributes.d.ts +47 -0
  28. package/dist/2-core/ds-attributes.d.ts.map +1 -0
  29. package/dist/2-core/ds-attributes.js +128 -0
  30. package/dist/2-core/ds-cycle.d.ts +66 -0
  31. package/dist/2-core/ds-cycle.d.ts.map +1 -0
  32. package/dist/2-core/ds-cycle.js +586 -0
  33. package/dist/2-core/ds-downloadcv.d.ts +58 -0
  34. package/dist/2-core/ds-downloadcv.d.ts.map +1 -0
  35. package/dist/2-core/ds-downloadcv.js +119 -0
  36. package/dist/2-core/ds-header.d.ts +28 -0
  37. package/dist/2-core/ds-header.d.ts.map +1 -0
  38. package/dist/2-core/ds-header.js +66 -0
  39. package/dist/2-core/ds-home.d.ts +26 -0
  40. package/dist/2-core/ds-home.d.ts.map +1 -0
  41. package/dist/2-core/ds-home.js +148 -0
  42. package/dist/2-core/ds-icon.d.ts +28 -0
  43. package/dist/2-core/ds-icon.d.ts.map +1 -0
  44. package/dist/2-core/ds-icon.js +297 -0
  45. package/dist/2-core/ds-link.d.ts +35 -0
  46. package/dist/2-core/ds-link.d.ts.map +1 -0
  47. package/dist/2-core/ds-link.js +85 -0
  48. package/dist/2-core/ds-markdown.d.ts +7 -0
  49. package/dist/2-core/ds-markdown.d.ts.map +1 -0
  50. package/dist/2-core/ds-markdown.js +240 -0
  51. package/dist/2-core/ds-price.d.ts +46 -0
  52. package/dist/2-core/ds-price.d.ts.map +1 -0
  53. package/dist/2-core/ds-price.js +72 -0
  54. package/dist/2-core/ds-squarecircle.d.ts +50 -0
  55. package/dist/2-core/ds-squarecircle.d.ts.map +1 -0
  56. package/dist/2-core/ds-squarecircle.js +133 -0
  57. package/dist/2-core/ds-title.d.ts +50 -0
  58. package/dist/2-core/ds-title.d.ts.map +1 -0
  59. package/dist/2-core/ds-title.js +103 -0
  60. package/dist/2-core/ds-tooltip.d.ts +39 -0
  61. package/dist/2-core/ds-tooltip.d.ts.map +1 -0
  62. package/dist/2-core/ds-tooltip.js +145 -0
  63. package/dist/2-core/ds-viewtoggle.d.ts +27 -0
  64. package/dist/2-core/ds-viewtoggle.d.ts.map +1 -0
  65. package/dist/2-core/ds-viewtoggle.js +49 -0
  66. package/dist/2-core/ds-year.d.ts +16 -0
  67. package/dist/2-core/ds-year.d.ts.map +1 -0
  68. package/dist/2-core/ds-year.js +21 -0
  69. package/dist/3-unit/ds-doublenav.d.ts +51 -0
  70. package/dist/3-unit/ds-doublenav.d.ts.map +1 -0
  71. package/dist/3-unit/ds-doublenav.js +88 -0
  72. package/dist/3-unit/ds-list.d.ts +11 -0
  73. package/dist/3-unit/ds-list.d.ts.map +1 -0
  74. package/dist/3-unit/ds-list.js +15 -0
  75. package/dist/3-unit/ds-panel.d.ts +11 -0
  76. package/dist/3-unit/ds-panel.d.ts.map +1 -0
  77. package/dist/3-unit/ds-panel.js +16 -0
  78. package/dist/3-unit/ds-row.d.ts +25 -0
  79. package/dist/3-unit/ds-row.d.ts.map +1 -0
  80. package/dist/3-unit/ds-row.js +32 -0
  81. package/dist/3-unit/ds-singlenav.d.ts +32 -0
  82. package/dist/3-unit/ds-singlenav.d.ts.map +1 -0
  83. package/dist/3-unit/ds-singlenav.js +62 -0
  84. package/dist/ds-one.bundle.js +63 -63
  85. package/dist/ds-one.bundle.js.map +2 -2
  86. package/dist/ds-one.bundle.min.js +27 -27
  87. package/dist/ds-one.bundle.min.js.map +2 -2
  88. package/dist/index.d.ts +20 -20
  89. package/dist/index.js +20 -20
  90. package/package.json +2 -2
@@ -0,0 +1,129 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * A component for displaying article content with image/text toggle
4
+ *
5
+ * @element ds-article
6
+ */
7
+ export declare class Article extends LitElement {
8
+ static get properties(): {
9
+ imgLightDesktop: {
10
+ type: StringConstructor;
11
+ reflect: boolean;
12
+ attribute: string;
13
+ };
14
+ imgDarkDesktop: {
15
+ type: StringConstructor;
16
+ reflect: boolean;
17
+ attribute: string;
18
+ };
19
+ imgLightMobile: {
20
+ type: StringConstructor;
21
+ reflect: boolean;
22
+ attribute: string;
23
+ };
24
+ imgDarkMobile: {
25
+ type: StringConstructor;
26
+ reflect: boolean;
27
+ attribute: string;
28
+ };
29
+ src: {
30
+ type: StringConstructor;
31
+ reflect: boolean;
32
+ };
33
+ alt: {
34
+ type: StringConstructor;
35
+ reflect: boolean;
36
+ };
37
+ imageToggle: {
38
+ type: BooleanConstructor;
39
+ reflect: boolean;
40
+ attribute: string;
41
+ };
42
+ imageOnlyWidth: {
43
+ type: NumberConstructor;
44
+ reflect: boolean;
45
+ attribute: string;
46
+ };
47
+ priority: {
48
+ type: BooleanConstructor;
49
+ reflect: boolean;
50
+ };
51
+ externalToggle: {
52
+ type: BooleanConstructor;
53
+ reflect: boolean;
54
+ attribute: string;
55
+ };
56
+ mobileKey: {
57
+ type: StringConstructor;
58
+ reflect: boolean;
59
+ attribute: string;
60
+ };
61
+ desktopKey: {
62
+ type: StringConstructor;
63
+ reflect: boolean;
64
+ attribute: string;
65
+ };
66
+ textKey: {
67
+ type: StringConstructor;
68
+ reflect: boolean;
69
+ attribute: string;
70
+ };
71
+ defaultValue: {
72
+ type: StringConstructor;
73
+ reflect: boolean;
74
+ attribute: string;
75
+ };
76
+ _text: {
77
+ type: StringConstructor;
78
+ state: boolean;
79
+ };
80
+ _currentImage: {
81
+ type: StringConstructor;
82
+ state: boolean;
83
+ };
84
+ _imageVisible: {
85
+ type: BooleanConstructor;
86
+ state: boolean;
87
+ };
88
+ _shouldAnimate: {
89
+ type: BooleanConstructor;
90
+ state: boolean;
91
+ };
92
+ };
93
+ imgLightDesktop: string;
94
+ imgDarkDesktop: string;
95
+ imgLightMobile: string;
96
+ imgDarkMobile: string;
97
+ src: string;
98
+ alt: string;
99
+ imageToggle: boolean;
100
+ imageOnlyWidth: number;
101
+ priority: boolean;
102
+ externalToggle: boolean;
103
+ mobileKey: string;
104
+ desktopKey: string;
105
+ textKey: string;
106
+ defaultValue: string;
107
+ _text: string;
108
+ _currentImage: string;
109
+ _imageVisible: boolean;
110
+ _shouldAnimate: boolean;
111
+ private _mql;
112
+ private boundHandlers;
113
+ constructor();
114
+ static styles: import("lit").CSSResult;
115
+ updated(changed: Map<string, unknown>): void;
116
+ connectedCallback(): void;
117
+ disconnectedCallback(): void;
118
+ private _loadText;
119
+ private _resolveImage;
120
+ private _toggleImage;
121
+ private _handleImageLoad;
122
+ render(): import("lit-html").TemplateResult<1>;
123
+ }
124
+ declare global {
125
+ interface HTMLElementTagNameMap {
126
+ "ds-article": Article;
127
+ }
128
+ }
129
+ //# sourceMappingURL=ds-article.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ds-article.d.ts","sourceRoot":"","sources":["../../DS1/2-core/ds-article.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAI5C;;;;GAIG;AACH,qBAAa,OAAQ,SAAQ,UAAU;IACrC,MAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6CpB;IAEO,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IAEhC,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,aAAa,CAKnB;;IAiDF,MAAM,CAAC,MAAM,0BAmEX;IAEF,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAkCrC,iBAAiB;IAuDjB,oBAAoB;IA+BpB,OAAO,CAAC,SAAS;IAsCjB,OAAO,CAAC,aAAa;IAwCrB,OAAO,CAAC,YAAY,CAIlB;IAEF,OAAO,CAAC,gBAAgB,CAGtB;IAEF,MAAM;CAmCP;AAID,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,YAAY,EAAE,OAAO,CAAC;KACvB;CACF"}
@@ -0,0 +1,361 @@
1
+ import { LitElement, css, html } from "lit";
2
+ import { getText } from "../utils/language";
3
+ import { getViewMode } from "../utils/viewMode";
4
+ /**
5
+ * A component for displaying article content with image/text toggle
6
+ *
7
+ * @element ds-article
8
+ */
9
+ export class Article extends LitElement {
10
+ static get properties() {
11
+ return {
12
+ imgLightDesktop: {
13
+ type: String,
14
+ reflect: true,
15
+ attribute: "img-light-desktop",
16
+ },
17
+ imgDarkDesktop: {
18
+ type: String,
19
+ reflect: true,
20
+ attribute: "img-dark-desktop",
21
+ },
22
+ imgLightMobile: {
23
+ type: String,
24
+ reflect: true,
25
+ attribute: "img-light-mobile",
26
+ },
27
+ imgDarkMobile: {
28
+ type: String,
29
+ reflect: true,
30
+ attribute: "img-dark-mobile",
31
+ },
32
+ src: { type: String, reflect: true },
33
+ alt: { type: String, reflect: true },
34
+ imageToggle: { type: Boolean, reflect: true, attribute: "image-toggle" },
35
+ imageOnlyWidth: {
36
+ type: Number,
37
+ reflect: true,
38
+ attribute: "image-only-width",
39
+ },
40
+ priority: { type: Boolean, reflect: true },
41
+ externalToggle: {
42
+ type: Boolean,
43
+ reflect: true,
44
+ attribute: "external-toggle",
45
+ },
46
+ mobileKey: { type: String, reflect: true, attribute: "mobile-key" },
47
+ desktopKey: { type: String, reflect: true, attribute: "desktop-key" },
48
+ textKey: { type: String, reflect: true, attribute: "text-key" },
49
+ defaultValue: { type: String, reflect: true, attribute: "default-value" },
50
+ _text: { type: String, state: true },
51
+ _currentImage: { type: String, state: true },
52
+ _imageVisible: { type: Boolean, state: true },
53
+ _shouldAnimate: { type: Boolean, state: true },
54
+ };
55
+ }
56
+ constructor() {
57
+ super();
58
+ this._toggleImage = () => {
59
+ this._shouldAnimate = true;
60
+ this._imageVisible = !this._imageVisible;
61
+ this.requestUpdate();
62
+ };
63
+ this._handleImageLoad = (e) => {
64
+ const img = e.target;
65
+ img.classList.add("loaded");
66
+ };
67
+ this.imgLightDesktop = "";
68
+ this.imgDarkDesktop = "";
69
+ this.imgLightMobile = "";
70
+ this.imgDarkMobile = "";
71
+ this.src = "";
72
+ this.alt = "";
73
+ this.imageToggle = false;
74
+ this.imageOnlyWidth = 480;
75
+ this.priority = false;
76
+ this.externalToggle = false;
77
+ this.mobileKey = "";
78
+ this.desktopKey = "";
79
+ this.textKey = "";
80
+ this.defaultValue = "";
81
+ this._text = "";
82
+ this._currentImage = "";
83
+ this._imageVisible = true;
84
+ this._shouldAnimate = false;
85
+ this._mql = null;
86
+ this.boundHandlers = {
87
+ languageChanged: (() => {
88
+ this._loadText();
89
+ }),
90
+ themeChanged: (() => {
91
+ this._resolveImage();
92
+ }),
93
+ viewportChanged: (e) => {
94
+ this._resolveImage();
95
+ this._loadText();
96
+ },
97
+ viewModeChanged: ((e) => {
98
+ if (this.imageToggle && this.externalToggle) {
99
+ const newMode = e.detail;
100
+ const shouldShowImage = newMode === "image";
101
+ if (this._imageVisible !== shouldShowImage) {
102
+ this._shouldAnimate = true;
103
+ this._imageVisible = shouldShowImage;
104
+ this.requestUpdate();
105
+ }
106
+ }
107
+ }),
108
+ };
109
+ }
110
+ updated(changed) {
111
+ if (changed.has("imageOnlyWidth")) {
112
+ const opx = Number(this.imageOnlyWidth) || 480;
113
+ this.style.setProperty("--image-only-width", `${opx}px`);
114
+ }
115
+ if (changed.has("imgLightDesktop") ||
116
+ changed.has("imgDarkDesktop") ||
117
+ changed.has("imgLightMobile") ||
118
+ changed.has("imgDarkMobile") ||
119
+ changed.has("src")) {
120
+ this._resolveImage();
121
+ }
122
+ if (changed.has("textKey") ||
123
+ changed.has("defaultValue") ||
124
+ changed.has("mobileKey") ||
125
+ changed.has("desktopKey")) {
126
+ this._loadText();
127
+ }
128
+ if (changed.has("imageToggle")) {
129
+ const isExternallyControlled = this.imageToggle && this.externalToggle;
130
+ if (!isExternallyControlled) {
131
+ const newImageVisible = !this.imageToggle;
132
+ if (this._imageVisible !== newImageVisible) {
133
+ this._shouldAnimate = true;
134
+ this._imageVisible = newImageVisible;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ connectedCallback() {
140
+ super.connectedCallback();
141
+ this._loadText();
142
+ this._resolveImage();
143
+ if (this.imageToggle && this.externalToggle) {
144
+ const currentMode = getViewMode();
145
+ this._imageVisible = currentMode === "image";
146
+ }
147
+ else {
148
+ this._imageVisible = !this.imageToggle;
149
+ }
150
+ this.style.setProperty("--image-only-width", `${this.imageOnlyWidth}px`);
151
+ try {
152
+ this._mql = window.matchMedia("(max-width: 720px)");
153
+ if (this._mql && this.boundHandlers.viewportChanged) {
154
+ this._mql.addEventListener("change", this.boundHandlers.viewportChanged);
155
+ }
156
+ }
157
+ catch (err) {
158
+ // no-op
159
+ }
160
+ window.addEventListener("language-changed", this.boundHandlers.languageChanged);
161
+ window.addEventListener("theme-changed", this.boundHandlers.themeChanged);
162
+ if (this.imageToggle && this.externalToggle) {
163
+ window.addEventListener("view-mode-changed", this.boundHandlers.viewModeChanged);
164
+ setTimeout(() => {
165
+ const currentMode = getViewMode();
166
+ const shouldShowImage = currentMode === "image";
167
+ if (this._imageVisible !== shouldShowImage) {
168
+ this._shouldAnimate = true;
169
+ this._imageVisible = shouldShowImage;
170
+ this.requestUpdate();
171
+ }
172
+ }, 100);
173
+ }
174
+ else if (this.imageToggle) {
175
+ window.addEventListener("article-toggle", this._toggleImage);
176
+ }
177
+ }
178
+ disconnectedCallback() {
179
+ super.disconnectedCallback();
180
+ window.removeEventListener("language-changed", this.boundHandlers.languageChanged);
181
+ window.removeEventListener("theme-changed", this.boundHandlers.themeChanged);
182
+ window.removeEventListener("article-toggle", this._toggleImage);
183
+ window.removeEventListener("view-mode-changed", this.boundHandlers.viewModeChanged);
184
+ if (this._mql && this.boundHandlers.viewportChanged) {
185
+ try {
186
+ this._mql.removeEventListener("change", this.boundHandlers.viewportChanged);
187
+ }
188
+ catch (err) {
189
+ // no-op
190
+ }
191
+ }
192
+ }
193
+ _loadText() {
194
+ const isMobile = (() => {
195
+ try {
196
+ return (window.matchMedia && window.matchMedia("(max-width: 720px)").matches);
197
+ }
198
+ catch (err) {
199
+ return false;
200
+ }
201
+ })();
202
+ const selectedKey = (() => {
203
+ const mobile = (this.mobileKey || "").trim();
204
+ const desktop = (this.desktopKey || "").trim();
205
+ const base = (this.textKey || "").trim();
206
+ if (mobile || desktop) {
207
+ return isMobile ? mobile || base : desktop || base;
208
+ }
209
+ return base;
210
+ })();
211
+ if (!selectedKey) {
212
+ this._text = this.defaultValue || "";
213
+ return;
214
+ }
215
+ try {
216
+ const text = getText(selectedKey);
217
+ this._text = text || this.defaultValue || selectedKey;
218
+ }
219
+ catch (error) {
220
+ console.error(`[ds-article] Error loading text for key "${selectedKey}":`, error);
221
+ this._text = this.defaultValue || selectedKey;
222
+ }
223
+ }
224
+ _resolveImage() {
225
+ if (this.src && typeof this.src === "string") {
226
+ const direct = this.src.startsWith("@") ? this.src.slice(1) : this.src;
227
+ this._currentImage = direct;
228
+ return;
229
+ }
230
+ const theme = document.documentElement.getAttribute("data-theme") || "light";
231
+ const isMobile = (() => {
232
+ try {
233
+ return (window.matchMedia && window.matchMedia("(max-width: 720px)").matches);
234
+ }
235
+ catch (err) {
236
+ return false;
237
+ }
238
+ })();
239
+ let chosen = "";
240
+ if (isMobile) {
241
+ if (theme === "dark") {
242
+ chosen = this.imgDarkMobile || this.imgLightMobile;
243
+ }
244
+ else {
245
+ chosen = this.imgLightMobile || this.imgDarkMobile;
246
+ }
247
+ }
248
+ else {
249
+ if (theme === "dark") {
250
+ chosen = this.imgDarkDesktop || this.imgLightDesktop;
251
+ }
252
+ else {
253
+ chosen = this.imgLightDesktop || this.imgDarkDesktop;
254
+ }
255
+ }
256
+ if (typeof chosen === "string" && chosen.startsWith("@")) {
257
+ chosen = chosen.slice(1);
258
+ }
259
+ this._currentImage = chosen || "";
260
+ }
261
+ render() {
262
+ const showImage = (this.imageToggle ? this._imageVisible : true) && !!this._currentImage;
263
+ const animationClass = this._shouldAnimate ? "fade-in" : "";
264
+ if (this._shouldAnimate) {
265
+ this._shouldAnimate = false;
266
+ }
267
+ const buttonText = this._imageVisible
268
+ ? getText("hideImage")
269
+ : getText("viewImage");
270
+ return html `
271
+ <div class="container">
272
+ ${this.imageToggle && !this.externalToggle
273
+ ? html `<button @click="${this._toggleImage}" class="toggle-button">
274
+ ${buttonText}
275
+ </button>`
276
+ : ""}
277
+ ${showImage
278
+ ? html `<figure class="media ${animationClass}">
279
+ <img
280
+ src="${this._currentImage}"
281
+ alt="${this.alt || ""}"
282
+ loading="${this.priority ? "eager" : "lazy"}"
283
+ fetchpriority="${this.priority ? "high" : "auto"}"
284
+ decoding="async"
285
+ @load="${this._handleImageLoad}"
286
+ />
287
+ </figure>`
288
+ : html `<p class="copy ${animationClass}">${this._text}</p>`}
289
+ </div>
290
+ `;
291
+ }
292
+ }
293
+ Article.styles = css `
294
+ :host {
295
+ display: block;
296
+ font-family: var(--typeface);
297
+ overflow-wrap: break-word;
298
+ word-wrap: break-word;
299
+ word-break: break-word;
300
+ hyphens: auto;
301
+ color: light-dark(var(--black), var(--white));
302
+ line-height: calc(20px * var(--scaling-factor));
303
+ padding: calc(2px * var(--scaling-factor));
304
+ }
305
+
306
+ .container {
307
+ position: relative;
308
+ width: min(100%, var(--image-only-width));
309
+ }
310
+
311
+ figure.media,
312
+ .copy {
313
+ margin: 0;
314
+ width: 100%;
315
+ overflow: hidden;
316
+ display: block;
317
+ margin-bottom: calc(8px * var(--scaling-factor));
318
+ }
319
+
320
+ .fade-in {
321
+ animation: fade-in 0.25s ease;
322
+ }
323
+
324
+ @keyframes fade-in {
325
+ from {
326
+ opacity: 0;
327
+ }
328
+ to {
329
+ opacity: 1;
330
+ }
331
+ }
332
+
333
+ img {
334
+ display: block;
335
+ width: 100%;
336
+ height: auto;
337
+ opacity: 0;
338
+ transition: opacity 0.2s ease-in-out;
339
+ }
340
+
341
+ img.loaded {
342
+ opacity: 1;
343
+ }
344
+
345
+ .toggle-button {
346
+ background: none;
347
+ border: none;
348
+ color: inherit;
349
+ cursor: pointer;
350
+ font-family: var(--typeface);
351
+ font-size: calc(14px * var(--scaling-factor));
352
+ margin-bottom: calc(8px * var(--scaling-factor));
353
+ padding: 0;
354
+ text-decoration: underline;
355
+ }
356
+
357
+ .toggle-button:hover {
358
+ opacity: 0.7;
359
+ }
360
+ `;
361
+ customElements.define("ds-article", Article);
@@ -0,0 +1,47 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * A component for displaying project/work attributes (year, category, status)
4
+ *
5
+ * @element ds-attributes
6
+ * @prop {string} year - Year key for translation
7
+ * @prop {string} category - Category key for translation
8
+ * @prop {string} status - Status key for translation
9
+ * @prop {string} type - Type of attributes: "project" or "work"
10
+ */
11
+ export declare class Attributes extends LitElement {
12
+ static get properties(): {
13
+ year: {
14
+ type: StringConstructor;
15
+ reflect: boolean;
16
+ };
17
+ category: {
18
+ type: StringConstructor;
19
+ reflect: boolean;
20
+ };
21
+ status: {
22
+ type: StringConstructor;
23
+ reflect: boolean;
24
+ };
25
+ type: {
26
+ type: StringConstructor;
27
+ reflect: boolean;
28
+ };
29
+ };
30
+ year: string;
31
+ category: string;
32
+ status: string;
33
+ type: string;
34
+ private boundHandlers;
35
+ static styles: import("lit").CSSResult;
36
+ constructor();
37
+ connectedCallback(): void;
38
+ disconnectedCallback(): void;
39
+ _getStatusClass(status: string): string;
40
+ render(): import("lit-html").TemplateResult<1>;
41
+ }
42
+ declare global {
43
+ interface HTMLElementTagNameMap {
44
+ "ds-attributes": Attributes;
45
+ }
46
+ }
47
+ //# sourceMappingURL=ds-attributes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ds-attributes.d.ts","sourceRoot":"","sources":["../../DS1/2-core/ds-attributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAG5C;;;;;;;;GAQG;AACH,qBAAa,UAAW,SAAQ,UAAU;IACxC,MAAM,KAAK,UAAU;;;;;;;;;;;;;;;;;MAOpB;IAEO,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IAErB,OAAO,CAAC,aAAa,CAAqC;IAE1D,MAAM,CAAC,MAAM,0BA2CX;;IAgBF,iBAAiB;IAQjB,oBAAoB;IAQpB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQvC,MAAM;CAiCP;AAID,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,UAAU,CAAC;KAC7B;CACF"}
@@ -0,0 +1,128 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { getText } from "../utils/language";
3
+ /**
4
+ * A component for displaying project/work attributes (year, category, status)
5
+ *
6
+ * @element ds-attributes
7
+ * @prop {string} year - Year key for translation
8
+ * @prop {string} category - Category key for translation
9
+ * @prop {string} status - Status key for translation
10
+ * @prop {string} type - Type of attributes: "project" or "work"
11
+ */
12
+ export class Attributes extends LitElement {
13
+ static get properties() {
14
+ return {
15
+ year: { type: String, reflect: true },
16
+ category: { type: String, reflect: true },
17
+ status: { type: String, reflect: true },
18
+ type: { type: String, reflect: true },
19
+ };
20
+ }
21
+ constructor() {
22
+ super();
23
+ this.year = "";
24
+ this.category = "";
25
+ this.status = "";
26
+ this.type = "project";
27
+ this.boundHandlers = {
28
+ languageChanged: (() => {
29
+ this.requestUpdate();
30
+ }),
31
+ };
32
+ }
33
+ connectedCallback() {
34
+ super.connectedCallback();
35
+ window.addEventListener("language-changed", this.boundHandlers.languageChanged);
36
+ }
37
+ disconnectedCallback() {
38
+ super.disconnectedCallback();
39
+ window.removeEventListener("language-changed", this.boundHandlers.languageChanged);
40
+ }
41
+ _getStatusClass(status) {
42
+ if (status.includes("Done"))
43
+ return "done";
44
+ if (status.includes("Ongoing"))
45
+ return "ongoing";
46
+ if (status.includes("Pending"))
47
+ return "pending";
48
+ if (status.includes("NotStarted"))
49
+ return "not-started";
50
+ return "pending";
51
+ }
52
+ render() {
53
+ return html `
54
+ ${this.year
55
+ ? html `
56
+ <div class="attribute-row">${getText(this.year) || this.year}</div>
57
+ `
58
+ : ""}
59
+ ${this.category
60
+ ? html `
61
+ <div class="attribute-row">
62
+ ${this.type === "work"
63
+ ? html `<span
64
+ class="status-indicator ${this._getStatusClass(this.status)}"
65
+ ></span>`
66
+ : ""}
67
+ ${getText(this.category) || this.category}
68
+ </div>
69
+ `
70
+ : ""}
71
+ ${this.status && this.type === "project"
72
+ ? html `
73
+ <div class="attribute-row">
74
+ <span
75
+ class="status-indicator ${this._getStatusClass(this.status)}"
76
+ ></span>
77
+ ${getText(this.status) || this.status}
78
+ </div>
79
+ `
80
+ : ""}
81
+ `;
82
+ }
83
+ }
84
+ Attributes.styles = css `
85
+ :host {
86
+ display: flex;
87
+ flex-direction: row;
88
+ gap: calc(16px * var(--scaling-factor));
89
+ align-items: flex-start;
90
+ }
91
+
92
+ .attribute-row {
93
+ display: inline-flex;
94
+ height: calc(20px * var(--scaling-factor));
95
+ padding: 0px calc(2px * var(--scaling-factor));
96
+ align-items: flex-start;
97
+ gap: calc(5px * var(--scaling-factor));
98
+ font-family: var(--typeface);
99
+ font-size: calc(14px * var(--scaling-factor));
100
+ color: light-dark(var(--slate), var(--slate-dark));
101
+ }
102
+
103
+ .status-indicator {
104
+ width: calc(8px * var(--scaling-factor));
105
+ height: calc(8px * var(--scaling-factor));
106
+ display: inline-block;
107
+ transition:
108
+ background 0.2s,
109
+ border-radius 0.2s;
110
+ }
111
+
112
+ .status-indicator.done {
113
+ background-color: green;
114
+ }
115
+
116
+ .status-indicator.ongoing {
117
+ background-color: #30adec;
118
+ }
119
+
120
+ .status-indicator.pending {
121
+ background-color: #f6c71c;
122
+ }
123
+
124
+ .status-indicator.not-started {
125
+ background-color: #b1b4b9;
126
+ }
127
+ `;
128
+ customElements.define("ds-attributes", Attributes);