ds-one 0.2.5-alpha.8 → 0.3.0-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.
- package/DS1/0-face/device.ts +138 -0
- package/DS1/0-face/i18n.ts +36 -89
- package/DS1/0-face/scaling.ts +152 -0
- package/DS1/1-root/fonts/Iosevka-Regular.woff2 +0 -0
- package/DS1/1-root/one.css +124 -77
- package/DS1/2-core/ds-banner.ts +120 -1
- package/DS1/2-core/ds-button.ts +16 -96
- package/DS1/2-core/ds-card.ts +137 -0
- package/DS1/2-core/ds-cycle.ts +82 -184
- package/DS1/2-core/ds-date.ts +3 -10
- package/DS1/2-core/ds-gap.ts +38 -0
- package/DS1/2-core/ds-icon.ts +6 -35
- package/DS1/2-core/ds-input.ts +306 -1
- package/DS1/2-core/ds-pagedots.ts +52 -0
- package/DS1/2-core/ds-text.ts +55 -28
- package/DS1/2-core/ds-tooltip.ts +14 -66
- package/DS1/2-core/styles/ds-banner.css +77 -0
- package/DS1/2-core/styles/ds-button.css +67 -0
- package/DS1/2-core/styles/ds-cycle.css +21 -0
- package/DS1/2-core/styles/ds-date.css +9 -0
- package/DS1/2-core/styles/ds-gap.css +93 -0
- package/DS1/2-core/styles/ds-icon.css +30 -0
- package/DS1/2-core/styles/ds-input.css +46 -0
- package/DS1/2-core/styles/ds-pagedots.css +31 -0
- package/DS1/2-core/styles/ds-text.css +29 -0
- package/DS1/2-core/styles/ds-tooltip.css +49 -0
- package/DS1/3-unit/ds-accordion.ts +95 -0
- package/DS1/3-unit/ds-form.ts +304 -0
- package/DS1/3-unit/ds-list.ts +5 -14
- package/DS1/3-unit/ds-row.ts +3 -19
- package/DS1/3-unit/ds-table.ts +3 -86
- package/DS1/3-unit/styles/ds-accordion.css +46 -0
- package/DS1/3-unit/styles/ds-list.css +9 -0
- package/DS1/3-unit/styles/ds-row.css +19 -0
- package/DS1/3-unit/styles/ds-table.css +80 -0
- package/DS1/4-page/ds-container.ts +28 -0
- package/DS1/4-page/ds-grid.ts +37 -50
- package/DS1/4-page/ds-layout.ts +652 -163
- package/DS1/4-page/styles/ds-container.css +35 -0
- package/DS1/4-page/styles/ds-grid.css +56 -0
- package/DS1/4-page/styles/ds-layout.css +246 -0
- package/DS1/index.ts +9 -1
- package/DS1/vite-env.d.ts +13 -0
- package/DS1/x-icon/2x.svg +4 -0
- package/DS1/x-icon/2xdots.svg +18 -0
- package/DS1/x-icon/2xgrid.svg +6 -0
- package/DS1/x-icon/2xlines.svg +6 -0
- package/DS1/x-icon/4x4.svg +18 -0
- package/DS1/x-icon/apple.svg +4 -0
- package/DS1/x-icon/avatar.svg +4 -0
- package/DS1/x-icon/big.svg +4 -0
- package/DS1/x-icon/blank.svg +3 -0
- package/DS1/x-icon/check.svg +3 -0
- package/DS1/x-icon/close.svg +3 -0
- package/DS1/x-icon/collapse.svg +3 -0
- package/DS1/x-icon/color.svg +4 -0
- package/DS1/x-icon/column.svg +5 -0
- package/DS1/x-icon/default.svg +3 -0
- package/DS1/x-icon/delete.svg +5 -0
- package/DS1/x-icon/dictate.svg +6 -0
- package/DS1/x-icon/do.svg +3 -0
- package/DS1/x-icon/down.svg +3 -0
- package/DS1/x-icon/duplicate.svg +4 -0
- package/DS1/x-icon/gallery.svg +5 -0
- package/DS1/x-icon/google.svg +6 -0
- package/DS1/x-icon/head.svg +5 -0
- package/DS1/x-icon/home.svg +3 -0
- package/DS1/x-icon/icon.svg +4 -0
- package/DS1/x-icon/in.svg +4 -0
- package/DS1/x-icon/lock.svg +5 -0
- package/DS1/x-icon/loop.svg +5 -0
- package/DS1/x-icon/mic.svg +5 -0
- package/DS1/x-icon/minimize.svg +3 -0
- package/DS1/x-icon/more.svg +5 -0
- package/DS1/x-icon/neutral.svg +6 -0
- package/DS1/x-icon/note.svg +6 -0
- package/DS1/x-icon/page.svg +4 -0
- package/DS1/x-icon/plus.svg +3 -0
- package/DS1/x-icon/rewind.svg +4 -0
- package/DS1/x-icon/row.svg +5 -0
- package/DS1/x-icon/sdown.svg +3 -0
- package/DS1/x-icon/search.svg +4 -0
- package/DS1/x-icon/see.svg +4 -0
- package/DS1/x-icon/ship.svg +5 -0
- package/DS1/x-icon/star.svg +3 -0
- package/DS1/x-icon/status.svg +4 -0
- package/DS1/x-icon/sup.svg +3 -0
- package/DS1/x-icon/title.svg +3 -0
- package/DS1/x-icon/undo.svg +3 -0
- package/DS1/x-icon/ungroup.svg +4 -0
- package/DS1/x-icon/unhead.svg +3 -0
- package/DS1/x-icon/unicon.svg +3 -0
- package/DS1/x-icon/unlock.svg +5 -0
- package/DS1/x-icon/unmic.svg +6 -0
- package/DS1/x-icon/unsee.svg +5 -0
- package/DS1/x-icon/unstar.svg +3 -0
- package/DS1/x-icon/untitle.svg +3 -0
- package/DS1/x-icon/up.svg +3 -0
- package/LICENSE +1 -1
- package/README.md +4 -4
- package/dist/0-face/device.d.ts +5 -0
- package/dist/0-face/device.d.ts.map +1 -1
- package/dist/0-face/device.js +111 -0
- package/dist/0-face/i18n.d.ts +0 -2
- package/dist/0-face/i18n.d.ts.map +1 -1
- package/dist/0-face/i18n.js +36 -73
- package/dist/0-face/scaling.d.ts +48 -0
- package/dist/0-face/scaling.d.ts.map +1 -0
- package/dist/0-face/scaling.js +114 -0
- package/dist/2-core/ds-banner.d.ts +67 -0
- package/dist/2-core/ds-banner.d.ts.map +1 -1
- package/dist/2-core/ds-banner.js +97 -1
- package/dist/2-core/ds-button.d.ts +4 -20
- package/dist/2-core/ds-button.d.ts.map +1 -1
- package/dist/2-core/ds-button.js +14 -88
- package/dist/2-core/ds-card.d.ts +39 -0
- package/dist/2-core/ds-card.d.ts.map +1 -0
- package/dist/2-core/ds-card.js +119 -0
- package/dist/2-core/ds-cycle.d.ts +1 -5
- package/dist/2-core/ds-cycle.d.ts.map +1 -1
- package/dist/2-core/ds-cycle.js +79 -166
- package/dist/2-core/ds-date.d.ts.map +1 -1
- package/dist/2-core/ds-date.js +3 -9
- package/dist/2-core/ds-gap.d.ts +28 -0
- package/dist/2-core/ds-gap.d.ts.map +1 -0
- package/dist/2-core/ds-gap.js +25 -0
- package/dist/2-core/ds-icon.d.ts.map +1 -1
- package/dist/2-core/ds-icon.js +6 -35
- package/dist/2-core/ds-input.d.ts +127 -0
- package/dist/2-core/ds-input.d.ts.map +1 -1
- package/dist/2-core/ds-input.js +252 -1
- package/dist/2-core/ds-pagedots.d.ts +32 -0
- package/dist/2-core/ds-pagedots.d.ts.map +1 -0
- package/dist/2-core/ds-pagedots.js +36 -0
- package/dist/2-core/ds-text.d.ts +5 -3
- package/dist/2-core/ds-text.d.ts.map +1 -1
- package/dist/2-core/ds-text.js +49 -27
- package/dist/2-core/ds-tooltip.d.ts +3 -3
- package/dist/2-core/ds-tooltip.d.ts.map +1 -1
- package/dist/2-core/ds-tooltip.js +13 -65
- package/dist/2-core/styles/ds-banner.css +77 -0
- package/dist/2-core/styles/ds-button.css +67 -0
- package/dist/2-core/styles/ds-cycle.css +21 -0
- package/dist/2-core/styles/ds-date.css +9 -0
- package/dist/2-core/styles/ds-gap.css +93 -0
- package/dist/2-core/styles/ds-icon.css +30 -0
- package/dist/2-core/styles/ds-input.css +46 -0
- package/dist/2-core/styles/ds-pagedots.css +26 -0
- package/dist/2-core/styles/ds-text.css +29 -0
- package/dist/2-core/styles/ds-tooltip.css +49 -0
- package/dist/3-unit/ds-accordion.d.ts +47 -0
- package/dist/3-unit/ds-accordion.d.ts.map +1 -0
- package/dist/3-unit/ds-accordion.js +75 -0
- package/dist/3-unit/ds-form.d.ts +70 -0
- package/dist/3-unit/ds-form.d.ts.map +1 -0
- package/dist/3-unit/ds-form.js +232 -0
- package/dist/3-unit/ds-list.d.ts.map +1 -1
- package/dist/3-unit/ds-list.js +5 -11
- package/dist/3-unit/ds-row.d.ts.map +1 -1
- package/dist/3-unit/ds-row.js +3 -19
- package/dist/3-unit/ds-table.d.ts.map +1 -1
- package/dist/3-unit/ds-table.js +3 -86
- package/dist/3-unit/styles/ds-accordion.css +46 -0
- package/dist/3-unit/styles/ds-list.css +9 -0
- package/dist/3-unit/styles/ds-row.css +19 -0
- package/dist/3-unit/styles/ds-table.css +80 -0
- package/dist/{3-unit/row-v1.d.ts → 4-page/ds-container.d.ts} +3 -11
- package/dist/4-page/ds-container.d.ts.map +1 -0
- package/dist/4-page/ds-container.js +11 -0
- package/dist/4-page/ds-grid.d.ts +5 -0
- package/dist/4-page/ds-grid.d.ts.map +1 -1
- package/dist/4-page/ds-grid.js +38 -56
- package/dist/4-page/ds-layout.d.ts +3 -3
- package/dist/4-page/ds-layout.d.ts.map +1 -1
- package/dist/4-page/ds-layout.js +651 -162
- package/dist/4-page/styles/ds-container.css +35 -0
- package/dist/4-page/styles/ds-grid.css +56 -0
- package/dist/4-page/styles/ds-layout.css +251 -0
- package/dist/ds-one.bundle.css +700 -0
- package/dist/ds-one.bundle.css.map +7 -0
- package/dist/ds-one.bundle.js +2728 -1597
- package/dist/ds-one.bundle.js.map +1 -7
- package/dist/ds-one.bundle.min.css +2 -0
- package/dist/ds-one.bundle.min.css.map +7 -0
- package/dist/ds-one.bundle.min.js +3850 -546
- package/dist/ds-one.bundle.min.js.map +1 -7
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/package.json +4 -3
- package/dist/3-unit/doublenav-v1.d.ts +0 -51
- package/dist/3-unit/doublenav-v1.d.ts.map +0 -1
- package/dist/3-unit/doublenav-v1.js +0 -88
- package/dist/3-unit/ds-portfolio-doublenav.d.ts +0 -51
- package/dist/3-unit/ds-portfolio-doublenav.d.ts.map +0 -1
- package/dist/3-unit/ds-portfolio-doublenav.js +0 -88
- package/dist/3-unit/ds-portfolio-panel.d.ts +0 -11
- package/dist/3-unit/ds-portfolio-panel.d.ts.map +0 -1
- package/dist/3-unit/ds-portfolio-panel.js +0 -16
- package/dist/3-unit/ds-portfolio-singlenav.d.ts +0 -32
- package/dist/3-unit/ds-portfolio-singlenav.d.ts.map +0 -1
- package/dist/3-unit/ds-portfolio-singlenav.js +0 -62
- package/dist/3-unit/list-v1.d.ts +0 -11
- package/dist/3-unit/list-v1.d.ts.map +0 -1
- package/dist/3-unit/list-v1.js +0 -15
- package/dist/3-unit/panel-v1.d.ts +0 -11
- package/dist/3-unit/panel-v1.d.ts.map +0 -1
- package/dist/3-unit/panel-v1.js +0 -16
- package/dist/3-unit/row-v1.d.ts.map +0 -1
- package/dist/3-unit/row-v1.js +0 -32
- package/dist/3-unit/singlenav-v1.d.ts +0 -32
- package/dist/3-unit/singlenav-v1.d.ts.map +0 -1
- package/dist/3-unit/singlenav-v1.js +0 -62
package/DS1/0-face/device.ts
CHANGED
|
@@ -104,6 +104,10 @@ export function initDeviceDetection(): DeviceInfo {
|
|
|
104
104
|
scalingFactor.toFixed(3)
|
|
105
105
|
);
|
|
106
106
|
|
|
107
|
+
// Add .mobile class to html element for CSS targeting
|
|
108
|
+
document.documentElement.classList.add("mobile");
|
|
109
|
+
document.documentElement.classList.remove("desktop");
|
|
110
|
+
|
|
107
111
|
console.log(
|
|
108
112
|
`[DS one] Mobile device detected - ${deviceInfo.deviceType} (${deviceInfo.screenWidth}x${deviceInfo.screenHeight}), scaling factor: ${scalingFactor.toFixed(2)}`
|
|
109
113
|
);
|
|
@@ -113,6 +117,10 @@ export function initDeviceDetection(): DeviceInfo {
|
|
|
113
117
|
document.documentElement.style.setProperty("--sf", "1");
|
|
114
118
|
// Also set --sf for backwards compatibility
|
|
115
119
|
document.documentElement.style.setProperty("--sf", "1");
|
|
120
|
+
|
|
121
|
+
// Add .desktop class and remove .mobile class
|
|
122
|
+
document.documentElement.classList.add("desktop");
|
|
123
|
+
document.documentElement.classList.remove("mobile");
|
|
116
124
|
}
|
|
117
125
|
console.log(
|
|
118
126
|
`[DS one] Desktop device detected (${deviceInfo.screenWidth}x${deviceInfo.screenHeight})`
|
|
@@ -156,3 +164,133 @@ if (typeof window !== "undefined") {
|
|
|
156
164
|
}, 100);
|
|
157
165
|
});
|
|
158
166
|
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Disable double-tap to zoom in the browser (app-like behavior)
|
|
170
|
+
* Prevents all zoom gestures including double-tap and pinch-to-zoom
|
|
171
|
+
*/
|
|
172
|
+
export function applike(): void {
|
|
173
|
+
if (typeof document === "undefined" || typeof window === "undefined") {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Set viewport meta tag to prevent zoom - this is the most important step
|
|
178
|
+
let viewport = document.querySelector('meta[name="viewport"]');
|
|
179
|
+
if (!viewport) {
|
|
180
|
+
viewport = document.createElement("meta");
|
|
181
|
+
viewport.setAttribute("name", "viewport");
|
|
182
|
+
document.head.appendChild(viewport);
|
|
183
|
+
}
|
|
184
|
+
viewport.setAttribute(
|
|
185
|
+
"content",
|
|
186
|
+
"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
// Apply touch-action: pan-x pan-y globally to prevent zoom but allow panning
|
|
190
|
+
const style = document.createElement("style");
|
|
191
|
+
style.id = "ds-one-applike-style";
|
|
192
|
+
style.textContent = `
|
|
193
|
+
* {
|
|
194
|
+
touch-action: pan-x pan-y !important;
|
|
195
|
+
-ms-touch-action: pan-x pan-y !important;
|
|
196
|
+
}
|
|
197
|
+
html, body {
|
|
198
|
+
touch-action: pan-x pan-y !important;
|
|
199
|
+
-ms-touch-action: pan-x pan-y !important;
|
|
200
|
+
}
|
|
201
|
+
`;
|
|
202
|
+
// Remove existing style if present
|
|
203
|
+
const existingStyle = document.getElementById("ds-one-applike-style");
|
|
204
|
+
if (existingStyle) {
|
|
205
|
+
existingStyle.remove();
|
|
206
|
+
}
|
|
207
|
+
document.head.appendChild(style);
|
|
208
|
+
|
|
209
|
+
// Track touch events to prevent double-tap zoom
|
|
210
|
+
let lastTouchEnd = 0;
|
|
211
|
+
let touchStartTime = 0;
|
|
212
|
+
|
|
213
|
+
const preventZoom = (event: TouchEvent | WheelEvent | Event) => {
|
|
214
|
+
// Prevent pinch zoom (two fingers)
|
|
215
|
+
if (event instanceof TouchEvent) {
|
|
216
|
+
if (event.touches.length > 1) {
|
|
217
|
+
event.preventDefault();
|
|
218
|
+
event.stopPropagation();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const now = Date.now();
|
|
223
|
+
|
|
224
|
+
if (event.type === "touchstart") {
|
|
225
|
+
// If touchstart happens within 300ms of last touchend, it's likely a double-tap
|
|
226
|
+
if (now - lastTouchEnd < 300) {
|
|
227
|
+
event.preventDefault();
|
|
228
|
+
event.stopPropagation();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
touchStartTime = now;
|
|
232
|
+
} else if (event.type === "touchend") {
|
|
233
|
+
const touchDuration = now - touchStartTime;
|
|
234
|
+
// If this is a quick tap (< 300ms) and happened soon after previous touchend, prevent it
|
|
235
|
+
if (touchDuration < 300 && now - lastTouchEnd < 300) {
|
|
236
|
+
event.preventDefault();
|
|
237
|
+
event.stopPropagation();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
lastTouchEnd = now;
|
|
241
|
+
} else if (event.type === "touchmove") {
|
|
242
|
+
// Prevent any touchmove that might trigger zoom
|
|
243
|
+
if (event.touches.length > 1) {
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
event.stopPropagation();
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Prevent wheel zoom with ctrl/cmd key (common on trackpads)
|
|
252
|
+
if (event instanceof WheelEvent && (event.ctrlKey || event.metaKey)) {
|
|
253
|
+
event.preventDefault();
|
|
254
|
+
event.stopPropagation();
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// Use capture phase to catch events earlier
|
|
260
|
+
const options = { passive: false, capture: true };
|
|
261
|
+
|
|
262
|
+
// Prevent all zoom gestures - use capture phase
|
|
263
|
+
document.addEventListener("touchstart", preventZoom, options);
|
|
264
|
+
document.addEventListener("touchmove", preventZoom, options);
|
|
265
|
+
document.addEventListener("touchend", preventZoom, options);
|
|
266
|
+
document.addEventListener("touchcancel", preventZoom, options);
|
|
267
|
+
|
|
268
|
+
// Prevent wheel zoom
|
|
269
|
+
document.addEventListener("wheel", preventZoom, options);
|
|
270
|
+
|
|
271
|
+
// Prevent gesture events (iOS Safari) - use capture phase
|
|
272
|
+
document.addEventListener(
|
|
273
|
+
"gesturestart",
|
|
274
|
+
(e) => {
|
|
275
|
+
e.preventDefault();
|
|
276
|
+
e.stopPropagation();
|
|
277
|
+
},
|
|
278
|
+
options
|
|
279
|
+
);
|
|
280
|
+
document.addEventListener(
|
|
281
|
+
"gesturechange",
|
|
282
|
+
(e) => {
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
e.stopPropagation();
|
|
285
|
+
},
|
|
286
|
+
options
|
|
287
|
+
);
|
|
288
|
+
document.addEventListener(
|
|
289
|
+
"gestureend",
|
|
290
|
+
(e) => {
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
e.stopPropagation();
|
|
293
|
+
},
|
|
294
|
+
options
|
|
295
|
+
);
|
|
296
|
+
}
|
package/DS1/0-face/i18n.ts
CHANGED
|
@@ -15,15 +15,15 @@ let translationKeys: TranslationMap = {};
|
|
|
15
15
|
// Primary language list – prioritise the 10 requested languages when cycling
|
|
16
16
|
const LANGUAGE_PRIORITY_ORDER = [
|
|
17
17
|
"da",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"pt",
|
|
18
|
+
"de",
|
|
19
|
+
"en",
|
|
21
20
|
"es",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
21
|
+
"fr",
|
|
22
|
+
"it",
|
|
24
23
|
"ja",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
24
|
+
"pt",
|
|
25
|
+
"sv",
|
|
26
|
+
"zh",
|
|
27
27
|
] as const;
|
|
28
28
|
|
|
29
29
|
const LANGUAGE_PRIORITY_LOOKUP = new Map<string, number>(
|
|
@@ -34,27 +34,27 @@ const LANGUAGE_PRIORITY_LOOKUP = new Map<string, number>(
|
|
|
34
34
|
const FALLBACK_LANGUAGE_NAMES: Record<string, string> = {
|
|
35
35
|
da: "Danish",
|
|
36
36
|
"da-dk": "Danish",
|
|
37
|
-
nb: "Norwegian",
|
|
38
|
-
"nb-no": "Norwegian",
|
|
39
|
-
sv: "Swedish",
|
|
40
|
-
"sv-se": "Swedish",
|
|
41
37
|
de: "German",
|
|
42
38
|
"de-de": "German",
|
|
43
39
|
en: "English",
|
|
44
40
|
"en-us": "English",
|
|
45
|
-
pt: "Portuguese",
|
|
46
|
-
"pt-pt": "Portuguese",
|
|
47
|
-
"pt-br": "Portuguese (Brazil)",
|
|
48
41
|
es: "Spanish",
|
|
49
42
|
"es-es": "Spanish",
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
43
|
+
fr: "French",
|
|
44
|
+
"fr-fr": "French",
|
|
45
|
+
it: "Italian",
|
|
46
|
+
"it-it": "Italian",
|
|
54
47
|
ja: "Japanese",
|
|
55
48
|
"ja-jp": "Japanese",
|
|
56
|
-
|
|
57
|
-
"
|
|
49
|
+
pt: "Portuguese",
|
|
50
|
+
"pt-pt": "Portuguese",
|
|
51
|
+
sv: "Swedish",
|
|
52
|
+
"sv-se": "Swedish",
|
|
53
|
+
zh: "Chinese",
|
|
54
|
+
"zh-cn": "Chinese",
|
|
55
|
+
"zh-tw": "Chinese",
|
|
56
|
+
"zh-hans": "Chinese",
|
|
57
|
+
"zh-hant": "Chinese",
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const DISPLAY_NAME_CACHE = new Map<string, Intl.DisplayNames>();
|
|
@@ -263,9 +263,6 @@ function getTranslationData(): TranslationMap {
|
|
|
263
263
|
// Cached translation data - use getter to always get fresh data
|
|
264
264
|
let translationData = getTranslationData();
|
|
265
265
|
|
|
266
|
-
type NotionCache = Map<string, string>;
|
|
267
|
-
|
|
268
|
-
const notionStore = new Map<LanguageCode, NotionCache>();
|
|
269
266
|
const defaultLanguage: LanguageCode = "en";
|
|
270
267
|
|
|
271
268
|
function extractPrimarySubtag(code: LanguageCode): string {
|
|
@@ -409,33 +406,30 @@ export function getLanguageDisplayName(
|
|
|
409
406
|
const BROWSER_LANGUAGE_PREFERENCES: Record<string, LanguageCode> = {
|
|
410
407
|
da: "da",
|
|
411
408
|
"da-dk": "da",
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
"
|
|
417
|
-
sv: "sv",
|
|
418
|
-
"sv-se": "sv",
|
|
419
|
-
pt: "pt",
|
|
420
|
-
"pt-pt": "pt",
|
|
421
|
-
"pt-br": "pt",
|
|
409
|
+
de: "de",
|
|
410
|
+
"de-de": "de",
|
|
411
|
+
en: "en",
|
|
412
|
+
"en-us": "en",
|
|
413
|
+
"en-gb": "en",
|
|
422
414
|
es: "es",
|
|
423
415
|
"es-es": "es",
|
|
424
416
|
"es-mx": "es",
|
|
417
|
+
fr: "fr",
|
|
418
|
+
"fr-fr": "fr",
|
|
419
|
+
it: "it",
|
|
420
|
+
"it-it": "it",
|
|
421
|
+
ja: "ja",
|
|
422
|
+
"ja-jp": "ja",
|
|
423
|
+
pt: "pt",
|
|
424
|
+
"pt-pt": "pt",
|
|
425
|
+
"pt-br": "pt",
|
|
426
|
+
sv: "sv",
|
|
427
|
+
"sv-se": "sv",
|
|
425
428
|
zh: "zh",
|
|
426
429
|
"zh-cn": "zh",
|
|
427
430
|
"zh-hans": "zh",
|
|
428
431
|
"zh-tw": "zh",
|
|
429
432
|
"zh-hant": "zh",
|
|
430
|
-
ko: "ko",
|
|
431
|
-
"ko-kr": "ko",
|
|
432
|
-
ja: "ja",
|
|
433
|
-
"ja-jp": "ja",
|
|
434
|
-
en: "en",
|
|
435
|
-
"en-us": "en",
|
|
436
|
-
"en-gb": "en",
|
|
437
|
-
de: "de",
|
|
438
|
-
"de-de": "de",
|
|
439
433
|
};
|
|
440
434
|
|
|
441
435
|
function resolvePreferredLanguage(languageTag: string): LanguageCode | null {
|
|
@@ -532,7 +526,6 @@ if (typeof window !== "undefined") {
|
|
|
532
526
|
|
|
533
527
|
// Dispatch that translations are loaded
|
|
534
528
|
window.dispatchEvent(new CustomEvent("translations-loaded"));
|
|
535
|
-
(window as any).notionDataLoaded = true;
|
|
536
529
|
|
|
537
530
|
// Dispatch language-changed to update all components
|
|
538
531
|
const currentLang = currentLanguage.value;
|
|
@@ -551,7 +544,6 @@ if (typeof window !== "undefined") {
|
|
|
551
544
|
setTimeout(() => {
|
|
552
545
|
// Since we directly imported the data, just dispatch the events
|
|
553
546
|
window.dispatchEvent(new CustomEvent("translations-loaded"));
|
|
554
|
-
(window as any).notionDataLoaded = true;
|
|
555
547
|
|
|
556
548
|
// Also dispatch language-changed with the current language
|
|
557
549
|
const currentLang = currentLanguage.value;
|
|
@@ -614,51 +606,6 @@ export function getText(key: string): string {
|
|
|
614
606
|
return translate(key);
|
|
615
607
|
}
|
|
616
608
|
|
|
617
|
-
// Get text from translation data (async for compatibility)
|
|
618
|
-
export async function getNotionText(
|
|
619
|
-
key: string,
|
|
620
|
-
language: LanguageCode = currentLanguage.value
|
|
621
|
-
): Promise<string | null> {
|
|
622
|
-
if (!key) {
|
|
623
|
-
return null;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
if (!translationData || !translationData[language]) {
|
|
627
|
-
return null;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
const text = translationData[language][key];
|
|
631
|
-
if (text) {
|
|
632
|
-
return text;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
// Fallback to English
|
|
636
|
-
if (language !== defaultLanguage && translationData[defaultLanguage]?.[key]) {
|
|
637
|
-
return translationData[defaultLanguage][key];
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
return null;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// Store Notion text (for dynamic updates)
|
|
644
|
-
export function setNotionText(
|
|
645
|
-
key: string,
|
|
646
|
-
value: string,
|
|
647
|
-
language: LanguageCode = currentLanguage.value
|
|
648
|
-
): void {
|
|
649
|
-
if (!key) return;
|
|
650
|
-
|
|
651
|
-
const bucket = getLanguageBucket(language);
|
|
652
|
-
bucket.set(key, value);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
function getLanguageBucket(language: LanguageCode): NotionCache {
|
|
656
|
-
if (!notionStore.has(language)) {
|
|
657
|
-
notionStore.set(language, new Map());
|
|
658
|
-
}
|
|
659
|
-
return notionStore.get(language)!;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
609
|
// Get available languages - dynamically detect from loaded data
|
|
663
610
|
export function getAvailableLanguages(): Promise<LanguageCode[]> {
|
|
664
611
|
// Always get fresh translation data
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// scaling.ts
|
|
2
|
+
// Responsive scaling utilities for the design system
|
|
3
|
+
|
|
4
|
+
import { signal } from "@lit-labs/signals";
|
|
5
|
+
|
|
6
|
+
export type ScalingMode = "auto" | "fixed" | "fluid";
|
|
7
|
+
|
|
8
|
+
export interface ScalingConfig {
|
|
9
|
+
mode: ScalingMode;
|
|
10
|
+
baseWidth: number;
|
|
11
|
+
minScale: number;
|
|
12
|
+
maxScale: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const defaultConfig: ScalingConfig = {
|
|
16
|
+
mode: "auto",
|
|
17
|
+
baseWidth: 280,
|
|
18
|
+
minScale: 0.75,
|
|
19
|
+
maxScale: 2.0,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// Reactive scaling factor signal
|
|
23
|
+
export const scalingFactor = signal<number>(1);
|
|
24
|
+
|
|
25
|
+
// Current scaling configuration
|
|
26
|
+
export const scalingConfig = signal<ScalingConfig>(defaultConfig);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Calculate the scaling factor based on viewport width
|
|
30
|
+
* @param viewportWidth - Current viewport width in pixels
|
|
31
|
+
* @param config - Scaling configuration
|
|
32
|
+
* @returns The calculated scaling factor
|
|
33
|
+
*/
|
|
34
|
+
export function calculateScalingFactor(
|
|
35
|
+
viewportWidth: number,
|
|
36
|
+
config: ScalingConfig = scalingConfig.get()
|
|
37
|
+
): number {
|
|
38
|
+
if (config.mode === "fixed") {
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const rawScale = viewportWidth / config.baseWidth;
|
|
43
|
+
const clampedScale = Math.max(
|
|
44
|
+
config.minScale,
|
|
45
|
+
Math.min(config.maxScale, rawScale)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return Number(clampedScale.toFixed(3));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set the scaling configuration
|
|
53
|
+
* @param config - Partial scaling configuration to apply
|
|
54
|
+
*/
|
|
55
|
+
export function setScalingConfig(config: Partial<ScalingConfig>): void {
|
|
56
|
+
const currentConfig = scalingConfig.get();
|
|
57
|
+
const newConfig = { ...currentConfig, ...config };
|
|
58
|
+
scalingConfig.set(newConfig);
|
|
59
|
+
|
|
60
|
+
// Recalculate scaling factor if in browser
|
|
61
|
+
if (typeof window !== "undefined") {
|
|
62
|
+
updateScalingFactor();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Update the scaling factor based on current viewport
|
|
68
|
+
*/
|
|
69
|
+
export function updateScalingFactor(): void {
|
|
70
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const viewportWidth = document.documentElement.clientWidth;
|
|
75
|
+
const config = scalingConfig.get();
|
|
76
|
+
const newFactor = calculateScalingFactor(viewportWidth, config);
|
|
77
|
+
|
|
78
|
+
scalingFactor.set(newFactor);
|
|
79
|
+
|
|
80
|
+
// Update CSS custom property
|
|
81
|
+
document.documentElement.style.setProperty("--sf", newFactor.toString());
|
|
82
|
+
|
|
83
|
+
// Dispatch event for components that need to react
|
|
84
|
+
window.dispatchEvent(
|
|
85
|
+
new CustomEvent("scaling-changed", {
|
|
86
|
+
detail: { scalingFactor: newFactor, config },
|
|
87
|
+
})
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the current scaling factor
|
|
93
|
+
* @returns The current scaling factor
|
|
94
|
+
*/
|
|
95
|
+
export function getScalingFactor(): number {
|
|
96
|
+
return scalingFactor.get();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Convert a design pixel value to scaled pixels
|
|
101
|
+
* @param designPx - The design pixel value (based on 280px width)
|
|
102
|
+
* @returns The scaled pixel value
|
|
103
|
+
*/
|
|
104
|
+
export function scale(designPx: number): number {
|
|
105
|
+
return designPx * scalingFactor.get();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Convert a scaled pixel value back to design pixels
|
|
110
|
+
* @param scaledPx - The scaled pixel value
|
|
111
|
+
* @returns The design pixel value
|
|
112
|
+
*/
|
|
113
|
+
export function unscale(scaledPx: number): number {
|
|
114
|
+
const factor = scalingFactor.get();
|
|
115
|
+
return factor === 0 ? scaledPx : scaledPx / factor;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Initialize scaling system
|
|
120
|
+
* This is typically called automatically when the module loads
|
|
121
|
+
*/
|
|
122
|
+
export function initScaling(): void {
|
|
123
|
+
if (typeof window === "undefined") {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Initial calculation
|
|
128
|
+
updateScalingFactor();
|
|
129
|
+
|
|
130
|
+
// Update on resize (debounced)
|
|
131
|
+
let resizeTimeout: ReturnType<typeof setTimeout>;
|
|
132
|
+
window.addEventListener("resize", () => {
|
|
133
|
+
clearTimeout(resizeTimeout);
|
|
134
|
+
resizeTimeout = setTimeout(() => {
|
|
135
|
+
updateScalingFactor();
|
|
136
|
+
}, 100);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Update on orientation change
|
|
140
|
+
window.addEventListener("orientationchange", () => {
|
|
141
|
+
setTimeout(updateScalingFactor, 100);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Auto-initialize when module loads in browser
|
|
146
|
+
if (typeof window !== "undefined") {
|
|
147
|
+
if (document.readyState === "loading") {
|
|
148
|
+
document.addEventListener("DOMContentLoaded", initScaling);
|
|
149
|
+
} else {
|
|
150
|
+
initScaling();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
Binary file
|