tyrell-components 1.0.0-TC52 → 1.0.0-TC53

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 (105) hide show
  1. package/css/tyrell-theme.css +25 -2
  2. package/css/tyrell.css +4 -0
  3. package/dist/tyrell-colors-static.css +1 -316
  4. package/dist/tyrell-theme.css +1 -1443
  5. package/dist/tyrell.css +1 -1390
  6. package/dist/tyrell.js +1 -1
  7. package/lib/base/ty-component.js +196 -196
  8. package/lib/components/button.d.ts +1 -1
  9. package/lib/components/button.js +260 -259
  10. package/lib/components/calendar-month.d.ts +2 -2
  11. package/lib/components/calendar-month.js +426 -416
  12. package/lib/components/calendar-navigation.js +238 -238
  13. package/lib/components/calendar.js +605 -602
  14. package/lib/components/checkbox.d.ts +1 -1
  15. package/lib/components/checkbox.js +273 -272
  16. package/lib/components/copy.d.ts +1 -1
  17. package/lib/components/copy.js +279 -278
  18. package/lib/components/date-picker.d.ts +1 -1
  19. package/lib/components/date-picker.js +1103 -1108
  20. package/lib/components/file-upload.js +404 -404
  21. package/lib/components/icon.js +141 -141
  22. package/lib/components/input.d.ts +1 -1
  23. package/lib/components/input.js +593 -596
  24. package/lib/components/modal.js +319 -319
  25. package/lib/components/option.js +167 -167
  26. package/lib/components/popup.js +233 -233
  27. package/lib/components/radio.d.ts +2 -2
  28. package/lib/components/radio.js +407 -406
  29. package/lib/components/resize-observer.js +67 -67
  30. package/lib/components/scroll-container.js +294 -294
  31. package/lib/components/select.d.ts +1 -1
  32. package/lib/components/select.js +1524 -1532
  33. package/lib/components/selected-tags.js +184 -184
  34. package/lib/components/step.js +62 -62
  35. package/lib/components/switch.d.ts +1 -1
  36. package/lib/components/switch.js +214 -213
  37. package/lib/components/tab.js +62 -62
  38. package/lib/components/tabs.js +507 -507
  39. package/lib/components/tag.d.ts +1 -1
  40. package/lib/components/tag.js +236 -235
  41. package/lib/components/textarea.d.ts +1 -1
  42. package/lib/components/textarea.js +457 -456
  43. package/lib/components/tooltip.js +283 -283
  44. package/lib/components/wizard.js +384 -384
  45. package/lib/icons/heroicons/micro.js +392 -392
  46. package/lib/icons/heroicons/mini.js +382 -382
  47. package/lib/icons/heroicons/outline.js +337 -337
  48. package/lib/icons/heroicons/solid.js +407 -407
  49. package/lib/icons/lucide.js +22843 -22843
  50. package/lib/icons/material/filled.js +9653 -9653
  51. package/lib/icons/material/outlined.js +10271 -10271
  52. package/lib/icons/material/round.js +10495 -10495
  53. package/lib/icons/material/sharp.js +9905 -9905
  54. package/lib/icons/material/two-tone.js +12792 -12792
  55. package/lib/index.js +21 -21
  56. package/lib/styles/button.js +176 -288
  57. package/lib/styles/calendar-month.js +123 -183
  58. package/lib/styles/calendar-navigation.js +60 -79
  59. package/lib/styles/calendar.js +8 -9
  60. package/lib/styles/checkbox.js +45 -72
  61. package/lib/styles/copy.js +67 -91
  62. package/lib/styles/custom-scrollbar.js +80 -100
  63. package/lib/styles/date-picker.js +261 -331
  64. package/lib/styles/field-size.d.ts +6 -0
  65. package/lib/styles/field-size.js +91 -0
  66. package/lib/styles/file-upload.js +139 -169
  67. package/lib/styles/icon.js +92 -156
  68. package/lib/styles/input.js +125 -241
  69. package/lib/styles/modal.js +67 -102
  70. package/lib/styles/option.d.ts +1 -1
  71. package/lib/styles/option.js +47 -67
  72. package/lib/styles/popup.js +34 -65
  73. package/lib/styles/radio.js +69 -96
  74. package/lib/styles/resize-observer.js +2 -5
  75. package/lib/styles/scroll-container.js +100 -130
  76. package/lib/styles/select-base.js +525 -778
  77. package/lib/styles/select.js +140 -228
  78. package/lib/styles/step.js +22 -29
  79. package/lib/styles/switch.js +34 -55
  80. package/lib/styles/tab.js +22 -29
  81. package/lib/styles/tabs.js +171 -252
  82. package/lib/styles/tag.js +135 -188
  83. package/lib/styles/textarea.d.ts +1 -1
  84. package/lib/styles/textarea.js +205 -271
  85. package/lib/styles/tooltip.js +3 -3
  86. package/lib/styles/wizard.js +170 -226
  87. package/lib/types/common.d.ts +2 -0
  88. package/lib/types/common.js +6 -5
  89. package/lib/utils/calendar-utils.js +100 -100
  90. package/lib/utils/custom-scrollbar.js +272 -272
  91. package/lib/utils/flavor-sheet.js +14 -14
  92. package/lib/utils/icon-registry.js +127 -127
  93. package/lib/utils/loader-registry.js +3 -3
  94. package/lib/utils/locale.js +34 -34
  95. package/lib/utils/mobile.js +1 -1
  96. package/lib/utils/number-format.js +54 -54
  97. package/lib/utils/positioning.js +212 -212
  98. package/lib/utils/property-capture.js +36 -36
  99. package/lib/utils/property-manager.js +125 -125
  100. package/lib/utils/resize-observer.js +23 -23
  101. package/lib/utils/scroll-lock.js +57 -57
  102. package/lib/utils/styles.js +17 -17
  103. package/lib/version.d.ts +1 -1
  104. package/lib/version.js +1 -1
  105. package/package.json +4 -4
@@ -9,155 +9,155 @@ const CACHE_URL_BASE = 'https://ty-icons.local/';
9
9
  const cacheReadPromises = new Map();
10
10
  let oldCachesCleared = false;
11
11
  async function clearOldCaches() {
12
- if (oldCachesCleared || !('caches' in window))
13
- return;
14
- oldCachesCleared = true;
15
- try {
16
- const cacheNames = await caches.keys();
17
- const oldCaches = cacheNames.filter(name => name.startsWith('ty-icons-v') && name !== CACHE_NAME);
18
- await Promise.all(oldCaches.map(name => caches.delete(name)));
19
- if (oldCaches.length > 0) {
20
- console.log(`🗑️ Cleared ${oldCaches.length} old icon cache(s)`);
21
- }
22
- }
23
- catch (err) {
24
- console.warn('[ty-icons] Failed to clear old caches:', err);
25
- }
12
+ if (oldCachesCleared || !('caches' in window))
13
+ return;
14
+ oldCachesCleared = true;
15
+ try {
16
+ const cacheNames = await caches.keys();
17
+ const oldCaches = cacheNames.filter(name => name.startsWith('ty-icons-v') && name !== CACHE_NAME);
18
+ await Promise.all(oldCaches.map(name => caches.delete(name)));
19
+ if (oldCaches.length > 0) {
20
+ console.log(`🗑️ Cleared ${oldCaches.length} old icon cache(s)`);
21
+ }
22
+ }
23
+ catch (err) {
24
+ console.warn('[ty-icons] Failed to clear old caches:', err);
25
+ }
26
26
  }
27
27
  async function cacheIcon(name, svg) {
28
- if (!('caches' in window))
29
- return;
30
- try {
31
- const cache = await caches.open(CACHE_NAME);
32
- const response = new Response(svg, {
33
- headers: { 'Content-Type': 'image/svg+xml' }
34
- });
35
- await cache.put(`${CACHE_URL_BASE}${name}`, response);
36
- }
37
- catch (err) {
38
- console.warn(`[ty-icons] Failed to cache icon "${name}":`, err);
39
- }
28
+ if (!('caches' in window))
29
+ return;
30
+ try {
31
+ const cache = await caches.open(CACHE_NAME);
32
+ const response = new Response(svg, {
33
+ headers: { 'Content-Type': 'image/svg+xml' }
34
+ });
35
+ await cache.put(`${CACHE_URL_BASE}${name}`, response);
36
+ }
37
+ catch (err) {
38
+ console.warn(`[ty-icons] Failed to cache icon "${name}":`, err);
39
+ }
40
40
  }
41
41
  export async function getCachedIcon(name) {
42
- const existingPromise = cacheReadPromises.get(name);
43
- if (existingPromise) {
44
- return existingPromise;
45
- }
46
- const readPromise = (async () => {
47
- try {
48
- await clearOldCaches();
49
- const cache = await caches.open(CACHE_NAME);
50
- const response = await cache.match(`${CACHE_URL_BASE}${name}`);
51
- if (response) {
52
- return await response.text();
53
- }
54
- }
55
- catch (err) {
56
- console.warn(`[ty-icons] Failed to read icon "${name}" from cache:`, err);
57
- }
58
- return null;
59
- })();
60
- cacheReadPromises.set(name, readPromise);
61
- readPromise.finally(() => {
62
- cacheReadPromises.delete(name);
63
- });
64
- return readPromise;
42
+ const existingPromise = cacheReadPromises.get(name);
43
+ if (existingPromise) {
44
+ return existingPromise;
45
+ }
46
+ const readPromise = (async () => {
47
+ try {
48
+ await clearOldCaches();
49
+ const cache = await caches.open(CACHE_NAME);
50
+ const response = await cache.match(`${CACHE_URL_BASE}${name}`);
51
+ if (response) {
52
+ return await response.text();
53
+ }
54
+ }
55
+ catch (err) {
56
+ console.warn(`[ty-icons] Failed to read icon "${name}" from cache:`, err);
57
+ }
58
+ return null;
59
+ })();
60
+ cacheReadPromises.set(name, readPromise);
61
+ readPromise.finally(() => {
62
+ cacheReadPromises.delete(name);
63
+ });
64
+ return readPromise;
65
65
  }
66
66
  export function registerIcons(icons) {
67
- const changedIcons = new Set();
68
- Object.entries(icons).forEach(([name, svg]) => {
69
- iconRegistry.set(name, svg);
70
- changedIcons.add(name);
71
- });
72
- if (changedIcons.size > 0) {
73
- scheduleNotification(changedIcons);
74
- }
67
+ const changedIcons = new Set();
68
+ Object.entries(icons).forEach(([name, svg]) => {
69
+ iconRegistry.set(name, svg);
70
+ changedIcons.add(name);
71
+ });
72
+ if (changedIcons.size > 0) {
73
+ scheduleNotification(changedIcons);
74
+ }
75
75
  }
76
76
  export function getIcon(name) {
77
- return iconRegistry.get(name);
77
+ return iconRegistry.get(name);
78
78
  }
79
79
  export function hasIcon(name) {
80
- return iconRegistry.has(name);
80
+ return iconRegistry.has(name);
81
81
  }
82
82
  export async function clearIcons() {
83
- const allIcons = new Set(iconRegistry.keys());
84
- iconRegistry.clear();
85
- if ('caches' in window) {
86
- try {
87
- await caches.delete(CACHE_NAME);
88
- oldCachesCleared = false;
89
- }
90
- catch (err) {
91
- console.warn('[ty-icons] Failed to clear icon cache:', err);
92
- }
93
- }
94
- scheduleNotification(allIcons);
83
+ const allIcons = new Set(iconRegistry.keys());
84
+ iconRegistry.clear();
85
+ if ('caches' in window) {
86
+ try {
87
+ await caches.delete(CACHE_NAME);
88
+ oldCachesCleared = false;
89
+ }
90
+ catch (err) {
91
+ console.warn('[ty-icons] Failed to clear icon cache:', err);
92
+ }
93
+ }
94
+ scheduleNotification(allIcons);
95
95
  }
96
96
  export function addWatcher(id, iconName, callback) {
97
- watchers.set(id, callback);
98
- if (iconName) {
99
- watcherIconNames.set(id, iconName);
100
- }
97
+ watchers.set(id, callback);
98
+ if (iconName) {
99
+ watcherIconNames.set(id, iconName);
100
+ }
101
101
  }
102
102
  export function removeWatcher(id) {
103
- watchers.delete(id);
104
- watcherIconNames.delete(id);
103
+ watchers.delete(id);
104
+ watcherIconNames.delete(id);
105
105
  }
106
106
  function scheduleNotification(changedIcons) {
107
- if (!pendingNotifications) {
108
- pendingNotifications = new Set();
109
- }
110
- changedIcons.forEach(name => pendingNotifications.add(name));
111
- if (notificationTimer !== null) {
112
- clearTimeout(notificationTimer);
113
- }
114
- const scheduleCallback = typeof requestIdleCallback !== 'undefined'
115
- ? requestIdleCallback
116
- : (cb) => setTimeout(cb, 0);
117
- notificationTimer = scheduleCallback(() => {
118
- const toNotify = pendingNotifications;
119
- pendingNotifications = null;
120
- notificationTimer = null;
121
- if (toNotify && toNotify.size > 0) {
122
- notifyWatchers(toNotify);
123
- }
124
- });
107
+ if (!pendingNotifications) {
108
+ pendingNotifications = new Set();
109
+ }
110
+ changedIcons.forEach(name => pendingNotifications.add(name));
111
+ if (notificationTimer !== null) {
112
+ clearTimeout(notificationTimer);
113
+ }
114
+ const scheduleCallback = typeof requestIdleCallback !== 'undefined'
115
+ ? requestIdleCallback
116
+ : (cb) => setTimeout(cb, 0);
117
+ notificationTimer = scheduleCallback(() => {
118
+ const toNotify = pendingNotifications;
119
+ pendingNotifications = null;
120
+ notificationTimer = null;
121
+ if (toNotify && toNotify.size > 0) {
122
+ notifyWatchers(toNotify);
123
+ }
124
+ });
125
125
  }
126
126
  function notifyWatchers(changedIcons) {
127
- watchers.forEach((callback, watcherId) => {
128
- const watchedIcon = watcherIconNames.get(watcherId);
129
- if (watchedIcon) {
130
- if (changedIcons.has(watchedIcon)) {
131
- callback(new Set([watchedIcon]));
132
- }
133
- }
134
- else {
135
- callback(changedIcons);
136
- }
137
- });
127
+ watchers.forEach((callback, watcherId) => {
128
+ const watchedIcon = watcherIconNames.get(watcherId);
129
+ if (watchedIcon) {
130
+ if (changedIcons.has(watchedIcon)) {
131
+ callback(new Set([watchedIcon]));
132
+ }
133
+ }
134
+ else {
135
+ callback(changedIcons);
136
+ }
137
+ });
138
138
  }
139
139
  export function getIconNames() {
140
- return Array.from(iconRegistry.keys());
140
+ return Array.from(iconRegistry.keys());
141
141
  }
142
142
  export async function getCacheInfo() {
143
- const info = {
144
- version: VERSION,
145
- cacheName: CACHE_NAME,
146
- available: 'caches' in window
147
- };
148
- if (!info.available)
149
- return info;
150
- try {
151
- const cache = await caches.open(CACHE_NAME);
152
- const keys = await cache.keys();
153
- const iconKeys = keys.filter(req => req.url.startsWith(CACHE_URL_BASE));
154
- return {
155
- ...info,
156
- iconCount: iconKeys.length
157
- };
158
- }
159
- catch (err) {
160
- console.warn('[ty-icons] Failed to get cache info:', err);
161
- return info;
162
- }
143
+ const info = {
144
+ version: VERSION,
145
+ cacheName: CACHE_NAME,
146
+ available: 'caches' in window
147
+ };
148
+ if (!info.available)
149
+ return info;
150
+ try {
151
+ const cache = await caches.open(CACHE_NAME);
152
+ const keys = await cache.keys();
153
+ const iconKeys = keys.filter(req => req.url.startsWith(CACHE_URL_BASE));
154
+ return {
155
+ ...info,
156
+ iconCount: iconKeys.length
157
+ };
158
+ }
159
+ catch (err) {
160
+ console.warn('[ty-icons] Failed to get cache info:', err);
161
+ return info;
162
+ }
163
163
  }
@@ -1,11 +1,11 @@
1
1
  const DEFAULT_LOADER_SVG = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3" stroke-opacity="0.25"/><path d="M22 12a10 10 0 0 1-10 10" stroke="currentColor" stroke-width="3" stroke-linecap="round"/></svg>`;
2
2
  let customLoaderSvg = null;
3
3
  export function setLoaderSvg(svg) {
4
- customLoaderSvg = svg && svg.trim() ? svg : null;
4
+ customLoaderSvg = svg && svg.trim() ? svg : null;
5
5
  }
6
6
  export function getLoaderSvg() {
7
- return customLoaderSvg ?? DEFAULT_LOADER_SVG;
7
+ return customLoaderSvg ?? DEFAULT_LOADER_SVG;
8
8
  }
9
9
  export function resetLoaderSvg() {
10
- customLoaderSvg = null;
10
+ customLoaderSvg = null;
11
11
  }
@@ -1,38 +1,38 @@
1
1
  export function getEffectiveLocale(element, explicitLocale) {
2
- if (explicitLocale) {
3
- return explicitLocale;
4
- }
5
- const langElement = element.closest('[lang]');
6
- if (langElement) {
7
- const lang = langElement.getAttribute('lang');
8
- if (lang)
9
- return lang;
10
- }
11
- if (document.documentElement.lang) {
12
- return document.documentElement.lang;
13
- }
14
- if (navigator.language) {
15
- return navigator.language;
16
- }
17
- return 'en-US';
2
+ if (explicitLocale) {
3
+ return explicitLocale;
4
+ }
5
+ const langElement = element.closest('[lang]');
6
+ if (langElement) {
7
+ const lang = langElement.getAttribute('lang');
8
+ if (lang)
9
+ return lang;
10
+ }
11
+ if (document.documentElement.lang) {
12
+ return document.documentElement.lang;
13
+ }
14
+ if (navigator.language) {
15
+ return navigator.language;
16
+ }
17
+ return 'en-US';
18
18
  }
19
19
  export function observeLocaleChanges(element, callback) {
20
- let currentLocale = getEffectiveLocale(element);
21
- const observer = new MutationObserver((mutations) => {
22
- for (const mutation of mutations) {
23
- if (mutation.type === 'attributes' && mutation.attributeName === 'lang') {
24
- const newLocale = getEffectiveLocale(element);
25
- if (newLocale !== currentLocale) {
26
- currentLocale = newLocale;
27
- callback(newLocale);
28
- }
29
- }
30
- }
31
- });
32
- observer.observe(document.documentElement, {
33
- attributes: true,
34
- attributeFilter: ['lang'],
35
- subtree: true
36
- });
37
- return () => observer.disconnect();
20
+ let currentLocale = getEffectiveLocale(element);
21
+ const observer = new MutationObserver((mutations) => {
22
+ for (const mutation of mutations) {
23
+ if (mutation.type === 'attributes' && mutation.attributeName === 'lang') {
24
+ const newLocale = getEffectiveLocale(element);
25
+ if (newLocale !== currentLocale) {
26
+ currentLocale = newLocale;
27
+ callback(newLocale);
28
+ }
29
+ }
30
+ }
31
+ });
32
+ observer.observe(document.documentElement, {
33
+ attributes: true,
34
+ attributeFilter: ['lang'],
35
+ subtree: true
36
+ });
37
+ return () => observer.disconnect();
38
38
  }
@@ -1,4 +1,4 @@
1
1
  const MOBILE_BREAKPOINT = 768;
2
2
  export function isMobileTouch(breakpoint = MOBILE_BREAKPOINT) {
3
- return window.matchMedia(`(pointer: coarse) and (max-width: ${breakpoint}px)`).matches;
3
+ return window.matchMedia(`(pointer: coarse) and (max-width: ${breakpoint}px)`).matches;
4
4
  }
@@ -1,60 +1,60 @@
1
1
  export function formatNumber(value, config) {
2
- const { type, locale = 'en-US', currency = 'USD', precision } = config;
3
- const options = {};
4
- if (precision !== undefined) {
5
- options.minimumFractionDigits = precision;
6
- options.maximumFractionDigits = precision;
7
- }
8
- switch (type) {
9
- case 'currency':
10
- options.style = 'currency';
11
- options.currency = currency;
12
- break;
13
- case 'percent':
14
- options.style = 'percent';
15
- break;
16
- case 'compact':
17
- options.notation = 'compact';
18
- options.compactDisplay = 'short';
19
- break;
20
- case 'number':
21
- default:
22
- options.style = 'decimal';
23
- break;
24
- }
25
- const formatter = new Intl.NumberFormat(locale, options);
26
- const formatted = formatter.format(value);
27
- return formatted
28
- .replace(/\u202F/g, '\u00A0')
29
- .replace(/\u2009/g, '\u00A0');
2
+ const { type, locale = 'en-US', currency = 'USD', precision } = config;
3
+ const options = {};
4
+ if (precision !== undefined) {
5
+ options.minimumFractionDigits = precision;
6
+ options.maximumFractionDigits = precision;
7
+ }
8
+ switch (type) {
9
+ case 'currency':
10
+ options.style = 'currency';
11
+ options.currency = currency;
12
+ break;
13
+ case 'percent':
14
+ options.style = 'percent';
15
+ break;
16
+ case 'compact':
17
+ options.notation = 'compact';
18
+ options.compactDisplay = 'short';
19
+ break;
20
+ case 'number':
21
+ default:
22
+ options.style = 'decimal';
23
+ break;
24
+ }
25
+ const formatter = new Intl.NumberFormat(locale, options);
26
+ const formatted = formatter.format(value);
27
+ return formatted
28
+ .replace(/\u202F/g, '\u00A0')
29
+ .replace(/\u2009/g, '\u00A0');
30
30
  }
31
31
  export function parseNumericValue(value) {
32
- if (!value || value.trim() === '')
33
- return null;
34
- let stripped = value
35
- .replace(/[^\d.,-]/g, '')
36
- .trim();
37
- if (stripped === '' || stripped === '-')
38
- return null;
39
- const lastComma = stripped.lastIndexOf(',');
40
- const lastDot = stripped.lastIndexOf('.');
41
- const lastSep = Math.max(lastComma, lastDot);
42
- if (lastSep === -1) {
43
- const parsed = parseFloat(stripped);
44
- return isNaN(parsed) ? null : parsed;
45
- }
46
- const sepChar = stripped[lastSep];
47
- const before = stripped.slice(0, lastSep);
48
- const after = stripped.slice(lastSep + 1);
49
- if (before.includes(sepChar)) {
50
- const parsed = parseFloat(stripped.replace(/[.,]/g, ''));
51
- return isNaN(parsed) ? null : parsed;
52
- }
53
- const intPart = before.replace(/[.,]/g, '');
54
- const decPart = after;
55
- const parsed = parseFloat(intPart + '.' + decPart);
56
- return isNaN(parsed) ? null : parsed;
32
+ if (!value || value.trim() === '')
33
+ return null;
34
+ let stripped = value
35
+ .replace(/[^\d.,-]/g, '')
36
+ .trim();
37
+ if (stripped === '' || stripped === '-')
38
+ return null;
39
+ const lastComma = stripped.lastIndexOf(',');
40
+ const lastDot = stripped.lastIndexOf('.');
41
+ const lastSep = Math.max(lastComma, lastDot);
42
+ if (lastSep === -1) {
43
+ const parsed = parseFloat(stripped);
44
+ return isNaN(parsed) ? null : parsed;
45
+ }
46
+ const sepChar = stripped[lastSep];
47
+ const before = stripped.slice(0, lastSep);
48
+ const after = stripped.slice(lastSep + 1);
49
+ if (before.includes(sepChar)) {
50
+ const parsed = parseFloat(stripped.replace(/[.,]/g, ''));
51
+ return isNaN(parsed) ? null : parsed;
52
+ }
53
+ const intPart = before.replace(/[.,]/g, '');
54
+ const decPart = after;
55
+ const parsed = parseFloat(intPart + '.' + decPart);
56
+ return isNaN(parsed) ? null : parsed;
57
57
  }
58
58
  export function shouldFormat(type) {
59
- return ['number', 'currency', 'percent', 'compact'].includes(type);
59
+ return ['number', 'currency', 'percent', 'compact'].includes(type);
60
60
  }