tyrell-components 1.0.0-RC6
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/LICENSE +21 -0
- package/README.md +221 -0
- package/css/tyrell.css +1783 -0
- package/dist/tyrell.css +1783 -0
- package/dist/tyrell.js +2 -0
- package/lib/base/ty-component.d.ts +133 -0
- package/lib/base/ty-component.d.ts.map +1 -0
- package/lib/base/ty-component.js +297 -0
- package/lib/base/ty-component.js.map +1 -0
- package/lib/components/button.d.ts +126 -0
- package/lib/components/button.d.ts.map +1 -0
- package/lib/components/button.js +244 -0
- package/lib/components/button.js.map +1 -0
- package/lib/components/calendar-month.d.ts +132 -0
- package/lib/components/calendar-month.d.ts.map +1 -0
- package/lib/components/calendar-month.js +440 -0
- package/lib/components/calendar-month.js.map +1 -0
- package/lib/components/calendar-navigation.d.ts +137 -0
- package/lib/components/calendar-navigation.d.ts.map +1 -0
- package/lib/components/calendar-navigation.js +366 -0
- package/lib/components/calendar-navigation.js.map +1 -0
- package/lib/components/calendar.d.ts +166 -0
- package/lib/components/calendar.d.ts.map +1 -0
- package/lib/components/calendar.js +774 -0
- package/lib/components/calendar.js.map +1 -0
- package/lib/components/checkbox.d.ts +189 -0
- package/lib/components/checkbox.d.ts.map +1 -0
- package/lib/components/checkbox.js +400 -0
- package/lib/components/checkbox.js.map +1 -0
- package/lib/components/copy.d.ts +180 -0
- package/lib/components/copy.d.ts.map +1 -0
- package/lib/components/copy.js +393 -0
- package/lib/components/copy.js.map +1 -0
- package/lib/components/date-picker.d.ts +379 -0
- package/lib/components/date-picker.d.ts.map +1 -0
- package/lib/components/date-picker.js +1586 -0
- package/lib/components/date-picker.js.map +1 -0
- package/lib/components/dropdown.d.ts +402 -0
- package/lib/components/dropdown.d.ts.map +1 -0
- package/lib/components/dropdown.js +1552 -0
- package/lib/components/dropdown.js.map +1 -0
- package/lib/components/icon.d.ts +118 -0
- package/lib/components/icon.d.ts.map +1 -0
- package/lib/components/icon.js +245 -0
- package/lib/components/icon.js.map +1 -0
- package/lib/components/input.d.ts +270 -0
- package/lib/components/input.d.ts.map +1 -0
- package/lib/components/input.js +721 -0
- package/lib/components/input.js.map +1 -0
- package/lib/components/modal.d.ts +58 -0
- package/lib/components/modal.d.ts.map +1 -0
- package/lib/components/modal.js +473 -0
- package/lib/components/modal.js.map +1 -0
- package/lib/components/multiselect.d.ts +397 -0
- package/lib/components/multiselect.d.ts.map +1 -0
- package/lib/components/multiselect.js +1580 -0
- package/lib/components/multiselect.js.map +1 -0
- package/lib/components/option.d.ts +66 -0
- package/lib/components/option.d.ts.map +1 -0
- package/lib/components/option.js +314 -0
- package/lib/components/option.js.map +1 -0
- package/lib/components/popup.d.ts +43 -0
- package/lib/components/popup.d.ts.map +1 -0
- package/lib/components/popup.js +380 -0
- package/lib/components/popup.js.map +1 -0
- package/lib/components/radio.d.ts +198 -0
- package/lib/components/radio.d.ts.map +1 -0
- package/lib/components/radio.js +437 -0
- package/lib/components/radio.js.map +1 -0
- package/lib/components/resize-observer.d.ts +48 -0
- package/lib/components/resize-observer.d.ts.map +1 -0
- package/lib/components/resize-observer.js +108 -0
- package/lib/components/resize-observer.js.map +1 -0
- package/lib/components/scroll-container.d.ts +51 -0
- package/lib/components/scroll-container.d.ts.map +1 -0
- package/lib/components/scroll-container.js +239 -0
- package/lib/components/scroll-container.js.map +1 -0
- package/lib/components/step.d.ts +26 -0
- package/lib/components/step.d.ts.map +1 -0
- package/lib/components/step.js +75 -0
- package/lib/components/step.js.map +1 -0
- package/lib/components/switch.d.ts +111 -0
- package/lib/components/switch.d.ts.map +1 -0
- package/lib/components/switch.js +240 -0
- package/lib/components/switch.js.map +1 -0
- package/lib/components/tab.d.ts +23 -0
- package/lib/components/tab.d.ts.map +1 -0
- package/lib/components/tab.js +76 -0
- package/lib/components/tab.js.map +1 -0
- package/lib/components/tabs.d.ts +93 -0
- package/lib/components/tabs.d.ts.map +1 -0
- package/lib/components/tabs.js +653 -0
- package/lib/components/tabs.js.map +1 -0
- package/lib/components/tag.d.ts +144 -0
- package/lib/components/tag.d.ts.map +1 -0
- package/lib/components/tag.js +316 -0
- package/lib/components/tag.js.map +1 -0
- package/lib/components/textarea.d.ts +241 -0
- package/lib/components/textarea.d.ts.map +1 -0
- package/lib/components/textarea.js +585 -0
- package/lib/components/textarea.js.map +1 -0
- package/lib/components/tooltip.d.ts +40 -0
- package/lib/components/tooltip.d.ts.map +1 -0
- package/lib/components/tooltip.js +439 -0
- package/lib/components/tooltip.js.map +1 -0
- package/lib/components/wizard.d.ts +86 -0
- package/lib/components/wizard.d.ts.map +1 -0
- package/lib/components/wizard.js +636 -0
- package/lib/components/wizard.js.map +1 -0
- package/lib/icons/fontawesome/brands.d.ts +557 -0
- package/lib/icons/fontawesome/brands.d.ts.map +1 -0
- package/lib/icons/fontawesome/brands.js +557 -0
- package/lib/icons/fontawesome/brands.js.map +1 -0
- package/lib/icons/fontawesome/regular.d.ts +281 -0
- package/lib/icons/fontawesome/regular.d.ts.map +1 -0
- package/lib/icons/fontawesome/regular.js +281 -0
- package/lib/icons/fontawesome/regular.js.map +1 -0
- package/lib/icons/fontawesome/solid.d.ts +1992 -0
- package/lib/icons/fontawesome/solid.d.ts.map +1 -0
- package/lib/icons/fontawesome/solid.js +1992 -0
- package/lib/icons/fontawesome/solid.js.map +1 -0
- package/lib/icons/heroicons/micro.d.ts +324 -0
- package/lib/icons/heroicons/micro.d.ts.map +1 -0
- package/lib/icons/heroicons/micro.js +1032 -0
- package/lib/icons/heroicons/micro.js.map +1 -0
- package/lib/icons/heroicons/mini.d.ts +332 -0
- package/lib/icons/heroicons/mini.d.ts.map +1 -0
- package/lib/icons/heroicons/mini.js +1038 -0
- package/lib/icons/heroicons/mini.js.map +1 -0
- package/lib/icons/heroicons/outline.d.ts +332 -0
- package/lib/icons/heroicons/outline.d.ts.map +1 -0
- package/lib/icons/heroicons/outline.js +993 -0
- package/lib/icons/heroicons/outline.js.map +1 -0
- package/lib/icons/heroicons/solid.d.ts +332 -0
- package/lib/icons/heroicons/solid.d.ts.map +1 -0
- package/lib/icons/heroicons/solid.js +1063 -0
- package/lib/icons/heroicons/solid.js.map +1 -0
- package/lib/icons/lucide.d.ts +1872 -0
- package/lib/icons/lucide.d.ts.map +1 -0
- package/lib/icons/lucide.js +28212 -0
- package/lib/icons/lucide.js.map +1 -0
- package/lib/icons/material/filled.d.ts +2180 -0
- package/lib/icons/material/filled.d.ts.map +1 -0
- package/lib/icons/material/filled.js +14003 -0
- package/lib/icons/material/filled.js.map +1 -0
- package/lib/icons/material/outlined.d.ts +2142 -0
- package/lib/icons/material/outlined.d.ts.map +1 -0
- package/lib/icons/material/outlined.js +14545 -0
- package/lib/icons/material/outlined.js.map +1 -0
- package/lib/icons/material/round.d.ts +2147 -0
- package/lib/icons/material/round.d.ts.map +1 -0
- package/lib/icons/material/round.js +14779 -0
- package/lib/icons/material/round.js.map +1 -0
- package/lib/icons/material/sharp.d.ts +2147 -0
- package/lib/icons/material/sharp.d.ts.map +1 -0
- package/lib/icons/material/sharp.js +14189 -0
- package/lib/icons/material/sharp.js.map +1 -0
- package/lib/icons/material/two-tone.d.ts +2185 -0
- package/lib/icons/material/two-tone.d.ts.map +1 -0
- package/lib/icons/material/two-tone.js +17152 -0
- package/lib/icons/material/two-tone.js.map +1 -0
- package/lib/index.d.ts +78 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +71 -0
- package/lib/index.js.map +1 -0
- package/lib/styles/button.d.ts +14 -0
- package/lib/styles/button.d.ts.map +1 -0
- package/lib/styles/button.js +457 -0
- package/lib/styles/button.js.map +1 -0
- package/lib/styles/calendar-month.d.ts +6 -0
- package/lib/styles/calendar-month.d.ts.map +1 -0
- package/lib/styles/calendar-month.js +275 -0
- package/lib/styles/calendar-month.js.map +1 -0
- package/lib/styles/calendar-navigation.d.ts +6 -0
- package/lib/styles/calendar-navigation.d.ts.map +1 -0
- package/lib/styles/calendar-navigation.js +143 -0
- package/lib/styles/calendar-navigation.js.map +1 -0
- package/lib/styles/calendar.d.ts +6 -0
- package/lib/styles/calendar.d.ts.map +1 -0
- package/lib/styles/calendar.js +28 -0
- package/lib/styles/calendar.js.map +1 -0
- package/lib/styles/checkbox.d.ts +9 -0
- package/lib/styles/checkbox.d.ts.map +1 -0
- package/lib/styles/checkbox.js +19 -0
- package/lib/styles/checkbox.js.map +1 -0
- package/lib/styles/copy.d.ts +7 -0
- package/lib/styles/copy.d.ts.map +1 -0
- package/lib/styles/copy.js +94 -0
- package/lib/styles/copy.js.map +1 -0
- package/lib/styles/custom-scrollbar.d.ts +6 -0
- package/lib/styles/custom-scrollbar.d.ts.map +1 -0
- package/lib/styles/custom-scrollbar.js +157 -0
- package/lib/styles/custom-scrollbar.js.map +1 -0
- package/lib/styles/date-picker.d.ts +6 -0
- package/lib/styles/date-picker.d.ts.map +1 -0
- package/lib/styles/date-picker.js +435 -0
- package/lib/styles/date-picker.js.map +1 -0
- package/lib/styles/dropdown.d.ts +12 -0
- package/lib/styles/dropdown.d.ts.map +1 -0
- package/lib/styles/dropdown.js +983 -0
- package/lib/styles/dropdown.js.map +1 -0
- package/lib/styles/icon.d.ts +6 -0
- package/lib/styles/icon.d.ts.map +1 -0
- package/lib/styles/icon.js +241 -0
- package/lib/styles/icon.js.map +1 -0
- package/lib/styles/input.d.ts +7 -0
- package/lib/styles/input.d.ts.map +1 -0
- package/lib/styles/input.js +685 -0
- package/lib/styles/input.js.map +1 -0
- package/lib/styles/modal.d.ts +8 -0
- package/lib/styles/modal.d.ts.map +1 -0
- package/lib/styles/modal.js +134 -0
- package/lib/styles/modal.js.map +1 -0
- package/lib/styles/multiselect.d.ts +6 -0
- package/lib/styles/multiselect.d.ts.map +1 -0
- package/lib/styles/multiselect.js +774 -0
- package/lib/styles/multiselect.js.map +1 -0
- package/lib/styles/option.d.ts +6 -0
- package/lib/styles/option.d.ts.map +1 -0
- package/lib/styles/option.js +116 -0
- package/lib/styles/option.js.map +1 -0
- package/lib/styles/popup.d.ts +8 -0
- package/lib/styles/popup.d.ts.map +1 -0
- package/lib/styles/popup.js +95 -0
- package/lib/styles/popup.js.map +1 -0
- package/lib/styles/radio.d.ts +8 -0
- package/lib/styles/radio.d.ts.map +1 -0
- package/lib/styles/radio.js +160 -0
- package/lib/styles/radio.js.map +1 -0
- package/lib/styles/resize-observer.d.ts +6 -0
- package/lib/styles/resize-observer.d.ts.map +1 -0
- package/lib/styles/resize-observer.js +18 -0
- package/lib/styles/resize-observer.js.map +1 -0
- package/lib/styles/scroll-container.d.ts +6 -0
- package/lib/styles/scroll-container.d.ts.map +1 -0
- package/lib/styles/scroll-container.js +198 -0
- package/lib/styles/scroll-container.js.map +1 -0
- package/lib/styles/step.d.ts +5 -0
- package/lib/styles/step.d.ts.map +1 -0
- package/lib/styles/step.js +50 -0
- package/lib/styles/step.js.map +1 -0
- package/lib/styles/switch.d.ts +9 -0
- package/lib/styles/switch.d.ts.map +1 -0
- package/lib/styles/switch.js +100 -0
- package/lib/styles/switch.js.map +1 -0
- package/lib/styles/tab.d.ts +5 -0
- package/lib/styles/tab.d.ts.map +1 -0
- package/lib/styles/tab.js +51 -0
- package/lib/styles/tab.js.map +1 -0
- package/lib/styles/tabs.d.ts +13 -0
- package/lib/styles/tabs.d.ts.map +1 -0
- package/lib/styles/tabs.js +184 -0
- package/lib/styles/tabs.js.map +1 -0
- package/lib/styles/tag.d.ts +6 -0
- package/lib/styles/tag.d.ts.map +1 -0
- package/lib/styles/tag.js +420 -0
- package/lib/styles/tag.js.map +1 -0
- package/lib/styles/textarea.d.ts +6 -0
- package/lib/styles/textarea.d.ts.map +1 -0
- package/lib/styles/textarea.js +350 -0
- package/lib/styles/textarea.js.map +1 -0
- package/lib/styles/tooltip.d.ts +9 -0
- package/lib/styles/tooltip.d.ts.map +1 -0
- package/lib/styles/tooltip.js +136 -0
- package/lib/styles/tooltip.js.map +1 -0
- package/lib/styles/wizard.d.ts +25 -0
- package/lib/styles/wizard.d.ts.map +1 -0
- package/lib/styles/wizard.js +325 -0
- package/lib/styles/wizard.js.map +1 -0
- package/lib/types/common.d.ts +143 -0
- package/lib/types/common.d.ts.map +1 -0
- package/lib/types/common.js +5 -0
- package/lib/types/common.js.map +1 -0
- package/lib/utils/calendar-utils.d.ts +176 -0
- package/lib/utils/calendar-utils.d.ts.map +1 -0
- package/lib/utils/calendar-utils.js +370 -0
- package/lib/utils/calendar-utils.js.map +1 -0
- package/lib/utils/custom-scrollbar.d.ts +82 -0
- package/lib/utils/custom-scrollbar.d.ts.map +1 -0
- package/lib/utils/custom-scrollbar.js +320 -0
- package/lib/utils/custom-scrollbar.js.map +1 -0
- package/lib/utils/icon-registry.d.ts +78 -0
- package/lib/utils/icon-registry.d.ts.map +1 -0
- package/lib/utils/icon-registry.js +304 -0
- package/lib/utils/icon-registry.js.map +1 -0
- package/lib/utils/locale.d.ts +136 -0
- package/lib/utils/locale.d.ts.map +1 -0
- package/lib/utils/locale.js +213 -0
- package/lib/utils/locale.js.map +1 -0
- package/lib/utils/mobile.d.ts +14 -0
- package/lib/utils/mobile.d.ts.map +1 -0
- package/lib/utils/mobile.js +21 -0
- package/lib/utils/mobile.js.map +1 -0
- package/lib/utils/number-format.d.ts +83 -0
- package/lib/utils/number-format.d.ts.map +1 -0
- package/lib/utils/number-format.js +143 -0
- package/lib/utils/number-format.js.map +1 -0
- package/lib/utils/parse-boolean.d.ts +39 -0
- package/lib/utils/parse-boolean.d.ts.map +1 -0
- package/lib/utils/parse-boolean.js +58 -0
- package/lib/utils/parse-boolean.js.map +1 -0
- package/lib/utils/positioning.d.ts +143 -0
- package/lib/utils/positioning.d.ts.map +1 -0
- package/lib/utils/positioning.js +308 -0
- package/lib/utils/positioning.js.map +1 -0
- package/lib/utils/property-capture.d.ts +132 -0
- package/lib/utils/property-capture.d.ts.map +1 -0
- package/lib/utils/property-capture.js +152 -0
- package/lib/utils/property-capture.js.map +1 -0
- package/lib/utils/property-manager.d.ts +90 -0
- package/lib/utils/property-manager.d.ts.map +1 -0
- package/lib/utils/property-manager.js +197 -0
- package/lib/utils/property-manager.js.map +1 -0
- package/lib/utils/resize-observer.d.ts +42 -0
- package/lib/utils/resize-observer.d.ts.map +1 -0
- package/lib/utils/resize-observer.js +71 -0
- package/lib/utils/resize-observer.js.map +1 -0
- package/lib/utils/scroll-lock.d.ts +79 -0
- package/lib/utils/scroll-lock.d.ts.map +1 -0
- package/lib/utils/scroll-lock.js +197 -0
- package/lib/utils/scroll-lock.js.map +1 -0
- package/lib/utils/styles.d.ts +27 -0
- package/lib/utils/styles.d.ts.map +1 -0
- package/lib/utils/styles.js +53 -0
- package/lib/utils/styles.js.map +1 -0
- package/lib/version.d.ts +8 -0
- package/lib/version.d.ts.map +1 -0
- package/lib/version.js +11 -0
- package/lib/version.js.map +1 -0
- package/package.json +159 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icon Registry System
|
|
3
|
+
* Simple icon storage and retrieval with Cache API persistence
|
|
4
|
+
* PORTED FROM: clj/ty/icons.cljs
|
|
5
|
+
*/
|
|
6
|
+
import { VERSION } from '../version.js';
|
|
7
|
+
/** Icon registry - maps icon names to SVG strings */
|
|
8
|
+
const iconRegistry = new Map();
|
|
9
|
+
/** Watchers for registry changes - now receives Set of changed icon names */
|
|
10
|
+
const watchers = new Map();
|
|
11
|
+
/** Track which icons each watcher cares about (for selective notification) */
|
|
12
|
+
const watcherIconNames = new Map();
|
|
13
|
+
/** Pending notifications - batched for performance */
|
|
14
|
+
let pendingNotifications = null;
|
|
15
|
+
let notificationTimer = null;
|
|
16
|
+
/** Cache API configuration */
|
|
17
|
+
const CACHE_NAME = `ty-icons-v${VERSION}`;
|
|
18
|
+
// Use a fake URL base for Cache API (requires valid URL format)
|
|
19
|
+
const CACHE_URL_BASE = 'https://ty-icons.local/';
|
|
20
|
+
/** Track in-flight cache reads to avoid duplicate work */
|
|
21
|
+
const cacheReadPromises = new Map();
|
|
22
|
+
/** Flag to track if old caches have been cleared */
|
|
23
|
+
let oldCachesCleared = false;
|
|
24
|
+
/**
|
|
25
|
+
* Clear old cache versions on first use
|
|
26
|
+
* This runs lazily the first time any icon is requested
|
|
27
|
+
*/
|
|
28
|
+
async function clearOldCaches() {
|
|
29
|
+
if (oldCachesCleared || !('caches' in window))
|
|
30
|
+
return;
|
|
31
|
+
oldCachesCleared = true;
|
|
32
|
+
try {
|
|
33
|
+
const cacheNames = await caches.keys();
|
|
34
|
+
const oldCaches = cacheNames.filter(name => name.startsWith('ty-icons-v') && name !== CACHE_NAME);
|
|
35
|
+
await Promise.all(oldCaches.map(name => caches.delete(name)));
|
|
36
|
+
if (oldCaches.length > 0) {
|
|
37
|
+
console.log(`🗑️ Cleared ${oldCaches.length} old icon cache(s)`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
console.warn('[ty-icons] Failed to clear old caches:', err);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Cache an icon in Cache API (non-blocking background operation)
|
|
46
|
+
* @param name Icon name
|
|
47
|
+
* @param svg SVG string
|
|
48
|
+
*/
|
|
49
|
+
async function cacheIcon(name, svg) {
|
|
50
|
+
if (!('caches' in window))
|
|
51
|
+
return;
|
|
52
|
+
try {
|
|
53
|
+
const cache = await caches.open(CACHE_NAME);
|
|
54
|
+
const response = new Response(svg, {
|
|
55
|
+
headers: { 'Content-Type': 'image/svg+xml' }
|
|
56
|
+
});
|
|
57
|
+
// Cache API requires valid URLs
|
|
58
|
+
await cache.put(`${CACHE_URL_BASE}${name}`, response);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
// Silent fail - caching is an optimization, not critical
|
|
62
|
+
console.warn(`[ty-icons] Failed to cache icon "${name}":`, err);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Read icon directly from cache (for immediate rendering)
|
|
67
|
+
* This is the key function that prevents icon twitching!
|
|
68
|
+
* @param name Icon name
|
|
69
|
+
* @returns Promise<string | null> - SVG string from cache or null
|
|
70
|
+
*/
|
|
71
|
+
export async function getCachedIcon(name) {
|
|
72
|
+
// Check if we already have a read in progress for this icon
|
|
73
|
+
const existingPromise = cacheReadPromises.get(name);
|
|
74
|
+
if (existingPromise) {
|
|
75
|
+
return existingPromise;
|
|
76
|
+
}
|
|
77
|
+
// Create new read promise
|
|
78
|
+
const readPromise = (async () => {
|
|
79
|
+
try {
|
|
80
|
+
// Clear old caches on first cache access
|
|
81
|
+
await clearOldCaches();
|
|
82
|
+
const cache = await caches.open(CACHE_NAME);
|
|
83
|
+
const response = await cache.match(`${CACHE_URL_BASE}${name}`);
|
|
84
|
+
if (response) {
|
|
85
|
+
return await response.text();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.warn(`[ty-icons] Failed to read icon "${name}" from cache:`, err);
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
})();
|
|
93
|
+
// Store promise to avoid duplicate work
|
|
94
|
+
cacheReadPromises.set(name, readPromise);
|
|
95
|
+
// Clean up promise after completion
|
|
96
|
+
readPromise.finally(() => {
|
|
97
|
+
cacheReadPromises.delete(name);
|
|
98
|
+
});
|
|
99
|
+
return readPromise;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Register multiple icons at once
|
|
103
|
+
* Always updates memory and notifies watchers immediately
|
|
104
|
+
* Cache update happens in background (only if different from cached version)
|
|
105
|
+
* @param icons Object mapping icon names to SVG strings
|
|
106
|
+
*/
|
|
107
|
+
export function registerIcons(icons) {
|
|
108
|
+
const changedIcons = new Set();
|
|
109
|
+
Object.entries(icons).forEach(([name, svg]) => {
|
|
110
|
+
// Always set in memory registry (fast, synchronous)
|
|
111
|
+
iconRegistry.set(name, svg);
|
|
112
|
+
changedIcons.add(name);
|
|
113
|
+
// Compare with cache in background to avoid unnecessary cache writes
|
|
114
|
+
/*getCachedIcon(name).then(cachedSvg => {
|
|
115
|
+
// Only write to cache if content actually changed
|
|
116
|
+
if (cachedSvg !== svg) {
|
|
117
|
+
cacheIcon(name, svg).catch(() => {
|
|
118
|
+
// Error already logged in cacheIcon
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
// If cachedSvg === svg, skip cache write (already up to date)
|
|
122
|
+
}).catch(() => {
|
|
123
|
+
// No cached version or error reading cache - write new icon
|
|
124
|
+
cacheIcon(name, svg).catch(() => {
|
|
125
|
+
// Error already logged in cacheIcon
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
*/
|
|
129
|
+
});
|
|
130
|
+
// Notify watchers immediately (synchronous)
|
|
131
|
+
if (changedIcons.size > 0) {
|
|
132
|
+
scheduleNotification(changedIcons);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Register a single icon
|
|
137
|
+
* Always updates memory and notifies watchers immediately
|
|
138
|
+
* Cache update happens in background (only if different from cached version)
|
|
139
|
+
* @param name Icon name
|
|
140
|
+
* @param svg SVG string
|
|
141
|
+
*/
|
|
142
|
+
export function registerIcon(name, svg) {
|
|
143
|
+
// Always set in memory registry (fast, synchronous)
|
|
144
|
+
iconRegistry.set(name, svg);
|
|
145
|
+
// Notify watchers immediately (synchronous)
|
|
146
|
+
scheduleNotification(new Set([name]));
|
|
147
|
+
// Compare with cache in background to avoid unnecessary cache writes
|
|
148
|
+
getCachedIcon(name).then(cachedSvg => {
|
|
149
|
+
// Only write to cache if content actually changed
|
|
150
|
+
if (cachedSvg !== svg) {
|
|
151
|
+
cacheIcon(name, svg).catch(() => {
|
|
152
|
+
// Error already logged in cacheIcon
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// If cachedSvg === svg, skip cache write (already up to date)
|
|
156
|
+
}).catch(() => {
|
|
157
|
+
// No cached version or error reading cache - write new icon
|
|
158
|
+
cacheIcon(name, svg).catch(() => {
|
|
159
|
+
// Error already logged in cacheIcon
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Lookup an icon by name from memory
|
|
165
|
+
* NOTE: This does NOT check cache - use getCachedIcon() for that
|
|
166
|
+
* @param name Icon name
|
|
167
|
+
* @returns SVG string or undefined
|
|
168
|
+
*/
|
|
169
|
+
export function getIcon(name) {
|
|
170
|
+
return iconRegistry.get(name);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Check if an icon exists in memory
|
|
174
|
+
* NOTE: This does NOT check cache
|
|
175
|
+
* @param name Icon name
|
|
176
|
+
* @returns true if icon is registered in memory
|
|
177
|
+
*/
|
|
178
|
+
export function hasIcon(name) {
|
|
179
|
+
return iconRegistry.has(name);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Clear all registered icons from memory and cache
|
|
183
|
+
*/
|
|
184
|
+
export async function clearIcons() {
|
|
185
|
+
const allIcons = new Set(iconRegistry.keys());
|
|
186
|
+
iconRegistry.clear();
|
|
187
|
+
// Clear cache
|
|
188
|
+
if ('caches' in window) {
|
|
189
|
+
try {
|
|
190
|
+
await caches.delete(CACHE_NAME);
|
|
191
|
+
oldCachesCleared = false; // Allow re-clearing next time
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
console.warn('[ty-icons] Failed to clear icon cache:', err);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
scheduleNotification(allIcons);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Add a watcher for registry changes
|
|
201
|
+
* @param id Unique watcher ID
|
|
202
|
+
* @param iconName Optional icon name to watch (for selective notification)
|
|
203
|
+
* @param callback Function to call when watched icons change
|
|
204
|
+
*/
|
|
205
|
+
export function addWatcher(id, iconName, callback) {
|
|
206
|
+
watchers.set(id, callback);
|
|
207
|
+
if (iconName) {
|
|
208
|
+
watcherIconNames.set(id, iconName);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Remove a watcher
|
|
213
|
+
* @param id Watcher ID to remove
|
|
214
|
+
*/
|
|
215
|
+
export function removeWatcher(id) {
|
|
216
|
+
watchers.delete(id);
|
|
217
|
+
watcherIconNames.delete(id);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Schedule notification for changed icons (batched and deferred)
|
|
221
|
+
*/
|
|
222
|
+
function scheduleNotification(changedIcons) {
|
|
223
|
+
// Accumulate changed icons
|
|
224
|
+
if (!pendingNotifications) {
|
|
225
|
+
pendingNotifications = new Set();
|
|
226
|
+
}
|
|
227
|
+
changedIcons.forEach(name => pendingNotifications.add(name));
|
|
228
|
+
// Cancel existing timer
|
|
229
|
+
if (notificationTimer !== null) {
|
|
230
|
+
clearTimeout(notificationTimer);
|
|
231
|
+
}
|
|
232
|
+
// Schedule notification using requestIdleCallback or setTimeout
|
|
233
|
+
const scheduleCallback = typeof requestIdleCallback !== 'undefined'
|
|
234
|
+
? requestIdleCallback
|
|
235
|
+
: (cb) => setTimeout(cb, 0);
|
|
236
|
+
notificationTimer = scheduleCallback(() => {
|
|
237
|
+
const toNotify = pendingNotifications;
|
|
238
|
+
pendingNotifications = null;
|
|
239
|
+
notificationTimer = null;
|
|
240
|
+
// Only notify if we have icons to notify about
|
|
241
|
+
if (toNotify && toNotify.size > 0) {
|
|
242
|
+
notifyWatchers(toNotify);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Notify watchers of changed icons (selective notification)
|
|
248
|
+
*/
|
|
249
|
+
function notifyWatchers(changedIcons) {
|
|
250
|
+
watchers.forEach((callback, watcherId) => {
|
|
251
|
+
const watchedIcon = watcherIconNames.get(watcherId);
|
|
252
|
+
// If watcher is watching a specific icon, only notify if that icon changed
|
|
253
|
+
if (watchedIcon) {
|
|
254
|
+
if (changedIcons.has(watchedIcon)) {
|
|
255
|
+
callback(new Set([watchedIcon]));
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// Watcher wants all changes
|
|
260
|
+
callback(changedIcons);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Get all registered icon names (memory only, not cache)
|
|
266
|
+
* @returns Array of icon names
|
|
267
|
+
*/
|
|
268
|
+
export function getIconNames() {
|
|
269
|
+
return Array.from(iconRegistry.keys());
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get registry size (memory only)
|
|
273
|
+
* @returns Number of registered icons in memory
|
|
274
|
+
*/
|
|
275
|
+
export function getIconCount() {
|
|
276
|
+
return iconRegistry.size;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get cache statistics
|
|
280
|
+
* @returns Promise with cache info
|
|
281
|
+
*/
|
|
282
|
+
export async function getCacheInfo() {
|
|
283
|
+
const info = {
|
|
284
|
+
version: VERSION,
|
|
285
|
+
cacheName: CACHE_NAME,
|
|
286
|
+
available: 'caches' in window
|
|
287
|
+
};
|
|
288
|
+
if (!info.available)
|
|
289
|
+
return info;
|
|
290
|
+
try {
|
|
291
|
+
const cache = await caches.open(CACHE_NAME);
|
|
292
|
+
const keys = await cache.keys();
|
|
293
|
+
const iconKeys = keys.filter(req => req.url.startsWith(CACHE_URL_BASE));
|
|
294
|
+
return {
|
|
295
|
+
...info,
|
|
296
|
+
iconCount: iconKeys.length
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
console.warn('[ty-icons] Failed to get cache info:', err);
|
|
301
|
+
return info;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=icon-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon-registry.js","sourceRoot":"","sources":["../../src/utils/icon-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Resolution Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides a cascade system for resolving locale/language preferences:
|
|
5
|
+
* 1. Component's explicit `locale` attribute (highest priority)
|
|
6
|
+
* 2. Closest ancestor's `lang` attribute
|
|
7
|
+
* 3. Document root's `lang` attribute
|
|
8
|
+
* 4. Browser's language preference
|
|
9
|
+
* 5. 'en-US' fallback (lowest priority)
|
|
10
|
+
*
|
|
11
|
+
* This allows developers to set locale at any level:
|
|
12
|
+
* - Per-component: <ty-input locale="fr-FR">
|
|
13
|
+
* - Per-section: <div lang="de-DE"><ty-input></ty-input></div>
|
|
14
|
+
* - Per-page: <html lang="es-ES">
|
|
15
|
+
* - Browser default: Uses navigator.language
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // In a component
|
|
20
|
+
* class TyInput extends HTMLElement {
|
|
21
|
+
* get locale(): string {
|
|
22
|
+
* return getEffectiveLocale(this, this.getAttribute('locale'));
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Get the effective locale for an element using the resolution cascade.
|
|
29
|
+
*
|
|
30
|
+
* Resolution order:
|
|
31
|
+
* 1. Explicit locale attribute on the element
|
|
32
|
+
* 2. Closest ancestor element with a `lang` attribute
|
|
33
|
+
* 3. Document root element's `lang` attribute
|
|
34
|
+
* 4. Browser's navigator.language
|
|
35
|
+
* 5. Fallback to 'en-US'
|
|
36
|
+
*
|
|
37
|
+
* @param element - The element to get locale for
|
|
38
|
+
* @param explicitLocale - Optional explicit locale value (from component's locale attribute)
|
|
39
|
+
* @returns The resolved locale string (e.g., 'en-US', 'fr-FR')
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```html
|
|
43
|
+
* <html lang="en-US">
|
|
44
|
+
* <div lang="fr-FR">
|
|
45
|
+
* <ty-input></ty-input> <!-- Uses 'fr-FR' -->
|
|
46
|
+
* <ty-input locale="de-DE"></ty-input> <!-- Uses 'de-DE' -->
|
|
47
|
+
* </div>
|
|
48
|
+
* <ty-input></ty-input> <!-- Uses 'en-US' -->
|
|
49
|
+
* </html>
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function getEffectiveLocale(element: HTMLElement, explicitLocale?: string | null): string;
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a locale string to BCP 47 format.
|
|
55
|
+
* Handles common variations and ensures consistency.
|
|
56
|
+
*
|
|
57
|
+
* @param locale - The locale string to normalize
|
|
58
|
+
* @returns Normalized locale string
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* normalizeLocale('en') // 'en'
|
|
63
|
+
* normalizeLocale('en_US') // 'en-US'
|
|
64
|
+
* normalizeLocale('EN-us') // 'en-US'
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function normalizeLocale(locale: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Check if a locale string is valid BCP 47 format.
|
|
70
|
+
*
|
|
71
|
+
* @param locale - The locale string to validate
|
|
72
|
+
* @returns true if valid, false otherwise
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* isValidLocale('en-US') // true
|
|
77
|
+
* isValidLocale('fr') // true
|
|
78
|
+
* isValidLocale('invalid!') // false
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare function isValidLocale(locale: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Get the language code from a locale (e.g., 'en' from 'en-US').
|
|
84
|
+
*
|
|
85
|
+
* @param locale - The locale string
|
|
86
|
+
* @returns The language code
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* getLanguageCode('en-US') // 'en'
|
|
91
|
+
* getLanguageCode('fr-FR') // 'fr'
|
|
92
|
+
* getLanguageCode('de') // 'de'
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function getLanguageCode(locale: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Get the region/country code from a locale (e.g., 'US' from 'en-US').
|
|
98
|
+
*
|
|
99
|
+
* @param locale - The locale string
|
|
100
|
+
* @returns The region code, or undefined if not present
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* getRegionCode('en-US') // 'US'
|
|
105
|
+
* getRegionCode('fr-FR') // 'FR'
|
|
106
|
+
* getRegionCode('de') // undefined
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export declare function getRegionCode(locale: string): string | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* Create a MutationObserver to watch for lang attribute changes.
|
|
112
|
+
* Useful for components that need to react to dynamic locale changes.
|
|
113
|
+
*
|
|
114
|
+
* @param element - The element to observe
|
|
115
|
+
* @param callback - Function to call when lang changes
|
|
116
|
+
* @returns Cleanup function to disconnect the observer
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* class TyInput extends HTMLElement {
|
|
121
|
+
* private _localeObserver?: () => void;
|
|
122
|
+
*
|
|
123
|
+
* connectedCallback() {
|
|
124
|
+
* this._localeObserver = observeLocaleChanges(this, () => {
|
|
125
|
+
* this.render(); // Re-render when locale changes
|
|
126
|
+
* });
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* disconnectedCallback() {
|
|
130
|
+
* this._localeObserver?.();
|
|
131
|
+
* }
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export declare function observeLocaleChanges(element: HTMLElement, callback: (newLocale: string) => void): () => void;
|
|
136
|
+
//# sourceMappingURL=locale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/utils/locale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,WAAW,EACpB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAC7B,MAAM,CA0BR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoBtD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGtD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIhE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACpC,MAAM,IAAI,CAyBZ"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale Resolution Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides a cascade system for resolving locale/language preferences:
|
|
5
|
+
* 1. Component's explicit `locale` attribute (highest priority)
|
|
6
|
+
* 2. Closest ancestor's `lang` attribute
|
|
7
|
+
* 3. Document root's `lang` attribute
|
|
8
|
+
* 4. Browser's language preference
|
|
9
|
+
* 5. 'en-US' fallback (lowest priority)
|
|
10
|
+
*
|
|
11
|
+
* This allows developers to set locale at any level:
|
|
12
|
+
* - Per-component: <ty-input locale="fr-FR">
|
|
13
|
+
* - Per-section: <div lang="de-DE"><ty-input></ty-input></div>
|
|
14
|
+
* - Per-page: <html lang="es-ES">
|
|
15
|
+
* - Browser default: Uses navigator.language
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // In a component
|
|
20
|
+
* class TyInput extends HTMLElement {
|
|
21
|
+
* get locale(): string {
|
|
22
|
+
* return getEffectiveLocale(this, this.getAttribute('locale'));
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Get the effective locale for an element using the resolution cascade.
|
|
29
|
+
*
|
|
30
|
+
* Resolution order:
|
|
31
|
+
* 1. Explicit locale attribute on the element
|
|
32
|
+
* 2. Closest ancestor element with a `lang` attribute
|
|
33
|
+
* 3. Document root element's `lang` attribute
|
|
34
|
+
* 4. Browser's navigator.language
|
|
35
|
+
* 5. Fallback to 'en-US'
|
|
36
|
+
*
|
|
37
|
+
* @param element - The element to get locale for
|
|
38
|
+
* @param explicitLocale - Optional explicit locale value (from component's locale attribute)
|
|
39
|
+
* @returns The resolved locale string (e.g., 'en-US', 'fr-FR')
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```html
|
|
43
|
+
* <html lang="en-US">
|
|
44
|
+
* <div lang="fr-FR">
|
|
45
|
+
* <ty-input></ty-input> <!-- Uses 'fr-FR' -->
|
|
46
|
+
* <ty-input locale="de-DE"></ty-input> <!-- Uses 'de-DE' -->
|
|
47
|
+
* </div>
|
|
48
|
+
* <ty-input></ty-input> <!-- Uses 'en-US' -->
|
|
49
|
+
* </html>
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function getEffectiveLocale(element, explicitLocale) {
|
|
53
|
+
// 1. Explicit locale attribute takes highest priority
|
|
54
|
+
if (explicitLocale) {
|
|
55
|
+
return explicitLocale;
|
|
56
|
+
}
|
|
57
|
+
// 2. Check closest ancestor with lang attribute
|
|
58
|
+
// This allows per-section locale overrides
|
|
59
|
+
const langElement = element.closest('[lang]');
|
|
60
|
+
if (langElement) {
|
|
61
|
+
const lang = langElement.getAttribute('lang');
|
|
62
|
+
if (lang)
|
|
63
|
+
return lang;
|
|
64
|
+
}
|
|
65
|
+
// 3. Check document root (html element)
|
|
66
|
+
if (document.documentElement.lang) {
|
|
67
|
+
return document.documentElement.lang;
|
|
68
|
+
}
|
|
69
|
+
// 4. Use browser's language preference
|
|
70
|
+
if (navigator.language) {
|
|
71
|
+
return navigator.language;
|
|
72
|
+
}
|
|
73
|
+
// 5. Ultimate fallback
|
|
74
|
+
return 'en-US';
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Normalize a locale string to BCP 47 format.
|
|
78
|
+
* Handles common variations and ensures consistency.
|
|
79
|
+
*
|
|
80
|
+
* @param locale - The locale string to normalize
|
|
81
|
+
* @returns Normalized locale string
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* normalizeLocale('en') // 'en'
|
|
86
|
+
* normalizeLocale('en_US') // 'en-US'
|
|
87
|
+
* normalizeLocale('EN-us') // 'en-US'
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export function normalizeLocale(locale) {
|
|
91
|
+
if (!locale)
|
|
92
|
+
return 'en-US';
|
|
93
|
+
// Replace underscores with hyphens (en_US -> en-US)
|
|
94
|
+
let normalized = locale.replace(/_/g, '-');
|
|
95
|
+
// Split into parts
|
|
96
|
+
const parts = normalized.split('-');
|
|
97
|
+
if (parts.length === 0)
|
|
98
|
+
return 'en-US';
|
|
99
|
+
// Lowercase language code (EN -> en)
|
|
100
|
+
parts[0] = parts[0].toLowerCase();
|
|
101
|
+
// Uppercase country code if present (us -> US)
|
|
102
|
+
if (parts.length > 1) {
|
|
103
|
+
parts[1] = parts[1].toUpperCase();
|
|
104
|
+
}
|
|
105
|
+
return parts.join('-');
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check if a locale string is valid BCP 47 format.
|
|
109
|
+
*
|
|
110
|
+
* @param locale - The locale string to validate
|
|
111
|
+
* @returns true if valid, false otherwise
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* isValidLocale('en-US') // true
|
|
116
|
+
* isValidLocale('fr') // true
|
|
117
|
+
* isValidLocale('invalid!') // false
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export function isValidLocale(locale) {
|
|
121
|
+
if (!locale)
|
|
122
|
+
return false;
|
|
123
|
+
// BCP 47 language tag pattern
|
|
124
|
+
// Simplified: allows language-region format
|
|
125
|
+
const pattern = /^[a-z]{2,3}(-[A-Z]{2})?$/;
|
|
126
|
+
return pattern.test(locale);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get the language code from a locale (e.g., 'en' from 'en-US').
|
|
130
|
+
*
|
|
131
|
+
* @param locale - The locale string
|
|
132
|
+
* @returns The language code
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* getLanguageCode('en-US') // 'en'
|
|
137
|
+
* getLanguageCode('fr-FR') // 'fr'
|
|
138
|
+
* getLanguageCode('de') // 'de'
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export function getLanguageCode(locale) {
|
|
142
|
+
if (!locale)
|
|
143
|
+
return 'en';
|
|
144
|
+
return locale.split('-')[0].toLowerCase();
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get the region/country code from a locale (e.g., 'US' from 'en-US').
|
|
148
|
+
*
|
|
149
|
+
* @param locale - The locale string
|
|
150
|
+
* @returns The region code, or undefined if not present
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* getRegionCode('en-US') // 'US'
|
|
155
|
+
* getRegionCode('fr-FR') // 'FR'
|
|
156
|
+
* getRegionCode('de') // undefined
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
export function getRegionCode(locale) {
|
|
160
|
+
if (!locale)
|
|
161
|
+
return undefined;
|
|
162
|
+
const parts = locale.split('-');
|
|
163
|
+
return parts.length > 1 ? parts[1].toUpperCase() : undefined;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create a MutationObserver to watch for lang attribute changes.
|
|
167
|
+
* Useful for components that need to react to dynamic locale changes.
|
|
168
|
+
*
|
|
169
|
+
* @param element - The element to observe
|
|
170
|
+
* @param callback - Function to call when lang changes
|
|
171
|
+
* @returns Cleanup function to disconnect the observer
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* class TyInput extends HTMLElement {
|
|
176
|
+
* private _localeObserver?: () => void;
|
|
177
|
+
*
|
|
178
|
+
* connectedCallback() {
|
|
179
|
+
* this._localeObserver = observeLocaleChanges(this, () => {
|
|
180
|
+
* this.render(); // Re-render when locale changes
|
|
181
|
+
* });
|
|
182
|
+
* }
|
|
183
|
+
*
|
|
184
|
+
* disconnectedCallback() {
|
|
185
|
+
* this._localeObserver?.();
|
|
186
|
+
* }
|
|
187
|
+
* }
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export function observeLocaleChanges(element, callback) {
|
|
191
|
+
let currentLocale = getEffectiveLocale(element);
|
|
192
|
+
// Create observer for lang attribute changes on ancestors
|
|
193
|
+
const observer = new MutationObserver((mutations) => {
|
|
194
|
+
for (const mutation of mutations) {
|
|
195
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'lang') {
|
|
196
|
+
const newLocale = getEffectiveLocale(element);
|
|
197
|
+
if (newLocale !== currentLocale) {
|
|
198
|
+
currentLocale = newLocale;
|
|
199
|
+
callback(newLocale);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
// Observe document and all ancestors
|
|
205
|
+
observer.observe(document.documentElement, {
|
|
206
|
+
attributes: true,
|
|
207
|
+
attributeFilter: ['lang'],
|
|
208
|
+
subtree: true
|
|
209
|
+
});
|
|
210
|
+
// Return cleanup function
|
|
211
|
+
return () => observer.disconnect();
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=locale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locale.js","sourceRoot":"","sources":["../../src/utils/locale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAoB,EACpB,cAA8B;IAE9B,sDAAsD;IACtD,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,gDAAgD;IAChD,2CAA2C;IAC3C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACxB,CAAC;IAED,wCAAwC;IACxC,IAAI,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;QAClC,OAAO,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC;IACvC,CAAC;IAED,uCAAuC;IACvC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,uBAAuB;IACvB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAE5B,oDAAoD;IACpD,IAAI,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE3C,mBAAmB;IACnB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAEvC,qCAAqC;IACrC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAElC,+CAA+C;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAE1B,8BAA8B;IAC9B,4CAA4C;IAC5C,MAAM,OAAO,GAAG,0BAA0B,CAAC;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAoB,EACpB,QAAqC;IAErC,IAAI,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEhD,0DAA0D;IAC1D,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;QAClD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,IAAI,QAAQ,CAAC,aAAa,KAAK,MAAM,EAAE,CAAC;gBACxE,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBAC9C,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;oBAChC,aAAa,GAAG,SAAS,CAAC;oBAC1B,QAAQ,CAAC,SAAS,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,EAAE;QACzC,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,CAAC,MAAM,CAAC;QACzB,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,0BAA0B;IAC1B,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mobile detection utility
|
|
3
|
+
*
|
|
4
|
+
* Uses CSS media query via matchMedia for reliable detection:
|
|
5
|
+
* - `pointer: coarse` identifies touch-primary devices (not laptops with touchscreens)
|
|
6
|
+
* - Breakpoint is evaluated by the browser, always in sync with CSS
|
|
7
|
+
* - Called on each use (not cached), so it responds to viewport changes and rotation
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Detect mobile touch devices.
|
|
11
|
+
* Returns true when the primary pointer is coarse (touch) AND viewport is narrow.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isMobileTouch(breakpoint?: number): boolean;
|
|
14
|
+
//# sourceMappingURL=mobile.d.ts.map
|