tyrell-components 1.0.0-TC45 → 1.0.0-TC46
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/dist/tyrell.js +1 -1
- package/lib/base/ty-component.d.ts +12 -7
- package/lib/base/ty-component.js +8 -139
- package/lib/components/button.d.ts +2 -16
- package/lib/components/button.js +0 -36
- package/lib/components/calendar-month.d.ts +2 -48
- package/lib/components/calendar-month.js +4 -166
- package/lib/components/calendar-navigation.d.ts +3 -48
- package/lib/components/calendar-navigation.js +3 -126
- package/lib/components/calendar.d.ts +3 -80
- package/lib/components/calendar.js +8 -230
- package/lib/components/checkbox.d.ts +4 -71
- package/lib/components/checkbox.js +7 -151
- package/lib/components/copy.d.ts +3 -56
- package/lib/components/copy.js +1 -120
- package/lib/components/date-picker.d.ts +5 -162
- package/lib/components/date-picker.js +28 -583
- package/lib/components/file-upload.d.ts +3 -15
- package/lib/components/file-upload.js +0 -37
- package/lib/components/icon.d.ts +3 -24
- package/lib/components/icon.js +1 -90
- package/lib/components/input.d.ts +7 -107
- package/lib/components/input.js +4 -193
- package/lib/components/modal.d.ts +3 -26
- package/lib/components/modal.js +1 -188
- package/lib/components/option.d.ts +2 -9
- package/lib/components/option.js +0 -48
- package/lib/components/popup.d.ts +2 -17
- package/lib/components/popup.js +3 -130
- package/lib/components/radio.d.ts +3 -23
- package/lib/components/radio.js +0 -63
- package/lib/components/resize-observer.d.ts +2 -30
- package/lib/components/resize-observer.js +0 -45
- package/lib/components/scroll-container.d.ts +2 -12
- package/lib/components/scroll-container.js +3 -46
- package/lib/components/select.d.ts +11 -150
- package/lib/components/select.js +7 -581
- package/lib/components/selected-tags.d.ts +4 -47
- package/lib/components/selected-tags.js +0 -94
- package/lib/components/step.d.ts +1 -6
- package/lib/components/step.js +0 -6
- package/lib/components/switch.d.ts +0 -11
- package/lib/components/switch.js +2 -36
- package/lib/components/tab.d.ts +1 -6
- package/lib/components/tab.js +0 -7
- package/lib/components/tabs.d.ts +3 -63
- package/lib/components/tabs.js +2 -282
- package/lib/components/tag.d.ts +2 -36
- package/lib/components/tag.js +5 -105
- package/lib/components/textarea.d.ts +6 -86
- package/lib/components/textarea.js +2 -173
- package/lib/components/tooltip.d.ts +3 -11
- package/lib/components/tooltip.js +0 -154
- package/lib/components/wizard.d.ts +4 -54
- package/lib/components/wizard.js +0 -228
- package/lib/icons/fontawesome/brands.d.ts +0 -1
- package/lib/icons/fontawesome/brands.js +0 -8
- package/lib/icons/fontawesome/regular.d.ts +0 -1
- package/lib/icons/fontawesome/regular.js +0 -8
- package/lib/icons/fontawesome/solid.d.ts +0 -1
- package/lib/icons/fontawesome/solid.js +0 -8
- package/lib/icons/heroicons/micro.d.ts +0 -1
- package/lib/icons/heroicons/micro.js +0 -8
- package/lib/icons/heroicons/mini.d.ts +0 -1
- package/lib/icons/heroicons/mini.js +0 -8
- package/lib/icons/heroicons/outline.d.ts +0 -1
- package/lib/icons/heroicons/outline.js +0 -8
- package/lib/icons/heroicons/solid.d.ts +0 -1
- package/lib/icons/heroicons/solid.js +0 -8
- package/lib/icons/lucide.d.ts +0 -1
- package/lib/icons/lucide.js +0 -1872
- package/lib/icons/material/filled.d.ts +0 -1
- package/lib/icons/material/filled.js +0 -10
- package/lib/icons/material/outlined.d.ts +0 -1
- package/lib/icons/material/outlined.js +0 -10
- package/lib/icons/material/round.d.ts +0 -1
- package/lib/icons/material/round.js +0 -10
- package/lib/icons/material/sharp.d.ts +0 -1
- package/lib/icons/material/sharp.js +0 -10
- package/lib/icons/material/two-tone.d.ts +0 -1
- package/lib/icons/material/two-tone.js +0 -10
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -20
- package/lib/styles/button.d.ts +2 -20
- package/lib/styles/button.js +13 -120
- package/lib/styles/calendar-month.d.ts +1 -5
- package/lib/styles/calendar-month.js +3 -60
- package/lib/styles/calendar-navigation.d.ts +2 -6
- package/lib/styles/calendar-navigation.js +1 -26
- package/lib/styles/calendar.d.ts +1 -2
- package/lib/styles/calendar.js +0 -13
- package/lib/styles/checkbox.d.ts +0 -1
- package/lib/styles/checkbox.js +1 -23
- package/lib/styles/copy.d.ts +0 -1
- package/lib/styles/copy.js +2 -17
- package/lib/styles/custom-scrollbar.d.ts +1 -2
- package/lib/styles/custom-scrollbar.js +3 -18
- package/lib/styles/date-picker.d.ts +1 -5
- package/lib/styles/date-picker.js +5 -35
- package/lib/styles/file-upload.d.ts +1 -2
- package/lib/styles/file-upload.js +0 -15
- package/lib/styles/icon.d.ts +2 -6
- package/lib/styles/icon.js +1 -26
- package/lib/styles/input.d.ts +1 -6
- package/lib/styles/input.js +3 -53
- package/lib/styles/modal.d.ts +1 -2
- package/lib/styles/modal.js +3 -23
- package/lib/styles/option.d.ts +2 -6
- package/lib/styles/option.js +1 -11
- package/lib/styles/popup.d.ts +1 -2
- package/lib/styles/popup.js +4 -25
- package/lib/styles/radio.d.ts +0 -1
- package/lib/styles/radio.js +1 -15
- package/lib/styles/resize-observer.d.ts +1 -2
- package/lib/styles/resize-observer.js +0 -7
- package/lib/styles/scroll-container.d.ts +1 -2
- package/lib/styles/scroll-container.js +0 -19
- package/lib/styles/select-base.d.ts +0 -1
- package/lib/styles/select-base.js +9 -70
- package/lib/styles/select.d.ts +1 -2
- package/lib/styles/select.js +2 -14
- package/lib/styles/step.d.ts +1 -2
- package/lib/styles/step.js +0 -4
- package/lib/styles/switch.d.ts +0 -1
- package/lib/styles/switch.js +2 -20
- package/lib/styles/tab.d.ts +1 -2
- package/lib/styles/tab.js +0 -5
- package/lib/styles/tabs.d.ts +3 -11
- package/lib/styles/tabs.js +4 -47
- package/lib/styles/tag.d.ts +1 -5
- package/lib/styles/tag.js +2 -31
- package/lib/styles/textarea.d.ts +1 -2
- package/lib/styles/textarea.js +0 -44
- package/lib/styles/tooltip.d.ts +0 -1
- package/lib/styles/tooltip.js +0 -10
- package/lib/styles/wizard.d.ts +5 -21
- package/lib/styles/wizard.js +5 -85
- package/lib/types/common.d.ts +0 -2
- package/lib/types/common.js +0 -12
- package/lib/utils/calendar-utils.d.ts +4 -21
- package/lib/utils/calendar-utils.js +4 -177
- package/lib/utils/custom-scrollbar.d.ts +6 -20
- package/lib/utils/custom-scrollbar.js +1 -45
- package/lib/utils/flavor-sheet.d.ts +0 -1
- package/lib/utils/flavor-sheet.js +0 -23
- package/lib/utils/icon-registry.d.ts +0 -2
- package/lib/utils/icon-registry.js +1 -107
- package/lib/utils/icons.d.ts +0 -1
- package/lib/utils/icons.js +0 -9
- package/lib/utils/loader-registry.d.ts +0 -1
- package/lib/utils/loader-registry.js +0 -32
- package/lib/utils/locale.d.ts +2 -23
- package/lib/utils/locale.js +0 -86
- package/lib/utils/mobile.d.ts +0 -1
- package/lib/utils/mobile.js +0 -17
- package/lib/utils/number-format.d.ts +0 -2
- package/lib/utils/number-format.js +2 -65
- package/lib/utils/positioning.d.ts +0 -2
- package/lib/utils/positioning.js +0 -54
- package/lib/utils/property-capture.d.ts +5 -27
- package/lib/utils/property-capture.js +0 -108
- package/lib/utils/property-manager.d.ts +0 -1
- package/lib/utils/property-manager.js +0 -70
- package/lib/utils/resize-observer.d.ts +0 -1
- package/lib/utils/resize-observer.js +0 -36
- package/lib/utils/scroll-lock.d.ts +4 -11
- package/lib/utils/scroll-lock.js +0 -107
- package/lib/utils/styles.d.ts +0 -1
- package/lib/utils/styles.js +0 -24
- package/lib/version.d.ts +1 -2
- package/lib/version.js +1 -11
- package/package.json +2 -2
- package/lib/base/ty-component.d.ts.map +0 -1
- package/lib/base/ty-component.js.map +0 -1
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js.map +0 -1
- package/lib/components/calendar-month.d.ts.map +0 -1
- package/lib/components/calendar-month.js.map +0 -1
- package/lib/components/calendar-navigation.d.ts.map +0 -1
- package/lib/components/calendar-navigation.js.map +0 -1
- package/lib/components/calendar.d.ts.map +0 -1
- package/lib/components/calendar.js.map +0 -1
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js.map +0 -1
- package/lib/components/copy.d.ts.map +0 -1
- package/lib/components/copy.js.map +0 -1
- package/lib/components/date-picker.d.ts.map +0 -1
- package/lib/components/date-picker.js.map +0 -1
- package/lib/components/file-upload.d.ts.map +0 -1
- package/lib/components/file-upload.js.map +0 -1
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js.map +0 -1
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js.map +0 -1
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js.map +0 -1
- package/lib/components/option.d.ts.map +0 -1
- package/lib/components/option.js.map +0 -1
- package/lib/components/popup.d.ts.map +0 -1
- package/lib/components/popup.js.map +0 -1
- package/lib/components/radio.d.ts.map +0 -1
- package/lib/components/radio.js.map +0 -1
- package/lib/components/resize-observer.d.ts.map +0 -1
- package/lib/components/resize-observer.js.map +0 -1
- package/lib/components/scroll-container.d.ts.map +0 -1
- package/lib/components/scroll-container.js.map +0 -1
- package/lib/components/select.d.ts.map +0 -1
- package/lib/components/select.js.map +0 -1
- package/lib/components/selected-tags.d.ts.map +0 -1
- package/lib/components/selected-tags.js.map +0 -1
- package/lib/components/step.d.ts.map +0 -1
- package/lib/components/step.js.map +0 -1
- package/lib/components/switch.d.ts.map +0 -1
- package/lib/components/switch.js.map +0 -1
- package/lib/components/tab.d.ts.map +0 -1
- package/lib/components/tab.js.map +0 -1
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/tag.d.ts.map +0 -1
- package/lib/components/tag.js.map +0 -1
- package/lib/components/textarea.d.ts.map +0 -1
- package/lib/components/textarea.js.map +0 -1
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js.map +0 -1
- package/lib/components/wizard.d.ts.map +0 -1
- package/lib/components/wizard.js.map +0 -1
- package/lib/icons/fontawesome/brands.d.ts.map +0 -1
- package/lib/icons/fontawesome/brands.js.map +0 -1
- package/lib/icons/fontawesome/regular.d.ts.map +0 -1
- package/lib/icons/fontawesome/regular.js.map +0 -1
- package/lib/icons/fontawesome/solid.d.ts.map +0 -1
- package/lib/icons/fontawesome/solid.js.map +0 -1
- package/lib/icons/heroicons/micro.d.ts.map +0 -1
- package/lib/icons/heroicons/micro.js.map +0 -1
- package/lib/icons/heroicons/mini.d.ts.map +0 -1
- package/lib/icons/heroicons/mini.js.map +0 -1
- package/lib/icons/heroicons/outline.d.ts.map +0 -1
- package/lib/icons/heroicons/outline.js.map +0 -1
- package/lib/icons/heroicons/solid.d.ts.map +0 -1
- package/lib/icons/heroicons/solid.js.map +0 -1
- package/lib/icons/lucide.d.ts.map +0 -1
- package/lib/icons/lucide.js.map +0 -1
- package/lib/icons/material/filled.d.ts.map +0 -1
- package/lib/icons/material/filled.js.map +0 -1
- package/lib/icons/material/outlined.d.ts.map +0 -1
- package/lib/icons/material/outlined.js.map +0 -1
- package/lib/icons/material/round.d.ts.map +0 -1
- package/lib/icons/material/round.js.map +0 -1
- package/lib/icons/material/sharp.d.ts.map +0 -1
- package/lib/icons/material/sharp.js.map +0 -1
- package/lib/icons/material/two-tone.d.ts.map +0 -1
- package/lib/icons/material/two-tone.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/styles/button.d.ts.map +0 -1
- package/lib/styles/button.js.map +0 -1
- package/lib/styles/calendar-month.d.ts.map +0 -1
- package/lib/styles/calendar-month.js.map +0 -1
- package/lib/styles/calendar-navigation.d.ts.map +0 -1
- package/lib/styles/calendar-navigation.js.map +0 -1
- package/lib/styles/calendar.d.ts.map +0 -1
- package/lib/styles/calendar.js.map +0 -1
- package/lib/styles/checkbox.d.ts.map +0 -1
- package/lib/styles/checkbox.js.map +0 -1
- package/lib/styles/copy.d.ts.map +0 -1
- package/lib/styles/copy.js.map +0 -1
- package/lib/styles/custom-scrollbar.d.ts.map +0 -1
- package/lib/styles/custom-scrollbar.js.map +0 -1
- package/lib/styles/date-picker.d.ts.map +0 -1
- package/lib/styles/date-picker.js.map +0 -1
- package/lib/styles/file-upload.d.ts.map +0 -1
- package/lib/styles/file-upload.js.map +0 -1
- package/lib/styles/icon.d.ts.map +0 -1
- package/lib/styles/icon.js.map +0 -1
- package/lib/styles/input.d.ts.map +0 -1
- package/lib/styles/input.js.map +0 -1
- package/lib/styles/modal.d.ts.map +0 -1
- package/lib/styles/modal.js.map +0 -1
- package/lib/styles/multiselect.d.ts +0 -8
- package/lib/styles/multiselect.d.ts.map +0 -1
- package/lib/styles/multiselect.js +0 -849
- package/lib/styles/multiselect.js.map +0 -1
- package/lib/styles/option.d.ts.map +0 -1
- package/lib/styles/option.js.map +0 -1
- package/lib/styles/popup.d.ts.map +0 -1
- package/lib/styles/popup.js.map +0 -1
- package/lib/styles/radio.d.ts.map +0 -1
- package/lib/styles/radio.js.map +0 -1
- package/lib/styles/resize-observer.d.ts.map +0 -1
- package/lib/styles/resize-observer.js.map +0 -1
- package/lib/styles/scroll-container.d.ts.map +0 -1
- package/lib/styles/scroll-container.js.map +0 -1
- package/lib/styles/select-base.d.ts.map +0 -1
- package/lib/styles/select-base.js.map +0 -1
- package/lib/styles/select.d.ts.map +0 -1
- package/lib/styles/select.js.map +0 -1
- package/lib/styles/step.d.ts.map +0 -1
- package/lib/styles/step.js.map +0 -1
- package/lib/styles/switch.d.ts.map +0 -1
- package/lib/styles/switch.js.map +0 -1
- package/lib/styles/tab.d.ts.map +0 -1
- package/lib/styles/tab.js.map +0 -1
- package/lib/styles/tabs.d.ts.map +0 -1
- package/lib/styles/tabs.js.map +0 -1
- package/lib/styles/tag.d.ts.map +0 -1
- package/lib/styles/tag.js.map +0 -1
- package/lib/styles/textarea.d.ts.map +0 -1
- package/lib/styles/textarea.js.map +0 -1
- package/lib/styles/tooltip.d.ts.map +0 -1
- package/lib/styles/tooltip.js.map +0 -1
- package/lib/styles/wizard.d.ts.map +0 -1
- package/lib/styles/wizard.js.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/common.js.map +0 -1
- package/lib/utils/calendar-utils.d.ts.map +0 -1
- package/lib/utils/calendar-utils.js.map +0 -1
- package/lib/utils/custom-scrollbar.d.ts.map +0 -1
- package/lib/utils/custom-scrollbar.js.map +0 -1
- package/lib/utils/flavor-sheet.d.ts.map +0 -1
- package/lib/utils/flavor-sheet.js.map +0 -1
- package/lib/utils/icon-registry.d.ts.map +0 -1
- package/lib/utils/icon-registry.js.map +0 -1
- package/lib/utils/icons.d.ts.map +0 -1
- package/lib/utils/icons.js.map +0 -1
- package/lib/utils/loader-registry.d.ts.map +0 -1
- package/lib/utils/loader-registry.js.map +0 -1
- package/lib/utils/locale.d.ts.map +0 -1
- package/lib/utils/locale.js.map +0 -1
- package/lib/utils/mobile.d.ts.map +0 -1
- package/lib/utils/mobile.js.map +0 -1
- package/lib/utils/number-format.d.ts.map +0 -1
- package/lib/utils/number-format.js.map +0 -1
- package/lib/utils/parse-boolean.d.ts +0 -39
- package/lib/utils/parse-boolean.d.ts.map +0 -1
- package/lib/utils/parse-boolean.js +0 -58
- package/lib/utils/parse-boolean.js.map +0 -1
- package/lib/utils/positioning.d.ts.map +0 -1
- package/lib/utils/positioning.js.map +0 -1
- package/lib/utils/property-capture.d.ts.map +0 -1
- package/lib/utils/property-capture.js.map +0 -1
- package/lib/utils/property-manager.d.ts.map +0 -1
- package/lib/utils/property-manager.js.map +0 -1
- package/lib/utils/resize-observer.d.ts.map +0 -1
- package/lib/utils/resize-observer.js.map +0 -1
- package/lib/utils/scroll-lock.d.ts.map +0 -1
- package/lib/utils/scroll-lock.js.map +0 -1
- package/lib/utils/styles.d.ts.map +0 -1
- package/lib/utils/styles.js.map +0 -1
- package/lib/version.d.ts.map +0 -1
- package/lib/version.js.map +0 -1
package/lib/utils/mobile.js
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
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
|
-
* Default mobile breakpoint (px).
|
|
11
|
-
* Matches phones in portrait and most phones in landscape.
|
|
12
|
-
*/
|
|
13
1
|
const MOBILE_BREAKPOINT = 768;
|
|
14
|
-
/**
|
|
15
|
-
* Detect mobile touch devices.
|
|
16
|
-
* Returns true when the primary pointer is coarse (touch) AND viewport is narrow.
|
|
17
|
-
*/
|
|
18
2
|
export function isMobileTouch(breakpoint = MOBILE_BREAKPOINT) {
|
|
19
3
|
return window.matchMedia(`(pointer: coarse) and (max-width: ${breakpoint}px)`).matches;
|
|
20
4
|
}
|
|
21
|
-
//# sourceMappingURL=mobile.js.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Number Formatting Utilities
|
|
3
|
-
* PORTED FROM: clj/ty/i18n/number.cljs
|
|
4
3
|
*
|
|
5
4
|
* Uses native Intl.NumberFormat for locale-aware number formatting
|
|
6
5
|
* Supports currency, percent, compact notation, and custom precision
|
|
@@ -59,4 +58,3 @@ export declare function parseNumericValue(value: string): number | null;
|
|
|
59
58
|
* ```
|
|
60
59
|
*/
|
|
61
60
|
export declare function shouldFormat(type: string): boolean;
|
|
62
|
-
//# sourceMappingURL=number-format.d.ts.map
|
|
@@ -1,34 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Number Formatting Utilities
|
|
3
|
-
* PORTED FROM: clj/ty/i18n/number.cljs
|
|
4
|
-
*
|
|
5
|
-
* Uses native Intl.NumberFormat for locale-aware number formatting
|
|
6
|
-
* Supports currency, percent, compact notation, and custom precision
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Format a number based on configuration
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* formatNumber(1234.56, { type: 'currency', currency: 'USD', locale: 'en-US' })
|
|
14
|
-
* // Returns: "$1,234.56"
|
|
15
|
-
*
|
|
16
|
-
* formatNumber(0.15, { type: 'percent', precision: 2 })
|
|
17
|
-
* // Returns: "15.00%"
|
|
18
|
-
*
|
|
19
|
-
* formatNumber(1234567, { type: 'compact' })
|
|
20
|
-
* // Returns: "1.2M"
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
1
|
export function formatNumber(value, config) {
|
|
24
2
|
const { type, locale = 'en-US', currency = 'USD', precision } = config;
|
|
25
3
|
const options = {};
|
|
26
|
-
// Add precision if specified
|
|
27
4
|
if (precision !== undefined) {
|
|
28
5
|
options.minimumFractionDigits = precision;
|
|
29
6
|
options.maximumFractionDigits = precision;
|
|
30
7
|
}
|
|
31
|
-
// Configure based on type
|
|
32
8
|
switch (type) {
|
|
33
9
|
case 'currency':
|
|
34
10
|
options.style = 'currency';
|
|
@@ -36,8 +12,6 @@ export function formatNumber(value, config) {
|
|
|
36
12
|
break;
|
|
37
13
|
case 'percent':
|
|
38
14
|
options.style = 'percent';
|
|
39
|
-
// Note: Intl.NumberFormat expects decimal (0.15 for 15%)
|
|
40
|
-
// We'll handle the division in the input component
|
|
41
15
|
break;
|
|
42
16
|
case 'compact':
|
|
43
17
|
options.notation = 'compact';
|
|
@@ -50,67 +24,30 @@ export function formatNumber(value, config) {
|
|
|
50
24
|
}
|
|
51
25
|
const formatter = new Intl.NumberFormat(locale, options);
|
|
52
26
|
const formatted = formatter.format(value);
|
|
53
|
-
// Normalize Unicode spaces for better HTML input compatibility
|
|
54
|
-
// Replace narrow no-break space (U+202F) and thin space (U+2009) with regular non-breaking space (U+00A0)
|
|
55
|
-
// This ensures proper rendering in HTML input elements
|
|
56
27
|
return formatted
|
|
57
|
-
.replace(/\u202F/g, '\u00A0')
|
|
58
|
-
.replace(/\u2009/g, '\u00A0');
|
|
28
|
+
.replace(/\u202F/g, '\u00A0')
|
|
29
|
+
.replace(/\u2009/g, '\u00A0');
|
|
59
30
|
}
|
|
60
|
-
/**
|
|
61
|
-
* Parse a numeric string to a number
|
|
62
|
-
*
|
|
63
|
-
* Simple rule: the last occurring . or , is the decimal separator.
|
|
64
|
-
* Everything else is stripped. This works for both US (1,234.56) and
|
|
65
|
-
* European (1.234,56) input, and for mobile keyboards that use , as decimal.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```typescript
|
|
69
|
-
* parseNumericValue("1,234.56") // 1234.56 (last separator is .)
|
|
70
|
-
* parseNumericValue("1.234,56") // 1234.56 (last separator is ,)
|
|
71
|
-
* parseNumericValue("12,50") // 12.5 (last separator is ,)
|
|
72
|
-
* parseNumericValue("12.50") // 12.5 (last separator is .)
|
|
73
|
-
* parseNumericValue("1234") // 1234
|
|
74
|
-
* parseNumericValue("$1,234") // 1234
|
|
75
|
-
* parseNumericValue("15%") // 15
|
|
76
|
-
* parseNumericValue("") // null
|
|
77
|
-
* ```
|
|
78
|
-
*/
|
|
79
31
|
export function parseNumericValue(value) {
|
|
80
32
|
if (!value || value.trim() === '')
|
|
81
33
|
return null;
|
|
82
|
-
// Strip everything except digits, dots, commas, and minus
|
|
83
34
|
let stripped = value
|
|
84
35
|
.replace(/[^\d.,-]/g, '')
|
|
85
36
|
.trim();
|
|
86
37
|
if (stripped === '' || stripped === '-')
|
|
87
38
|
return null;
|
|
88
|
-
// Find the last occurring . or , — that's the decimal separator
|
|
89
39
|
const lastComma = stripped.lastIndexOf(',');
|
|
90
40
|
const lastDot = stripped.lastIndexOf('.');
|
|
91
41
|
const lastSep = Math.max(lastComma, lastDot);
|
|
92
42
|
if (lastSep === -1) {
|
|
93
|
-
// No separators — pure integer
|
|
94
43
|
const parsed = parseFloat(stripped);
|
|
95
44
|
return isNaN(parsed) ? null : parsed;
|
|
96
45
|
}
|
|
97
|
-
// Split at the last separator
|
|
98
46
|
const intPart = stripped.slice(0, lastSep).replace(/[.,]/g, '');
|
|
99
47
|
const decPart = stripped.slice(lastSep + 1);
|
|
100
48
|
const parsed = parseFloat(intPart + '.' + decPart);
|
|
101
49
|
return isNaN(parsed) ? null : parsed;
|
|
102
50
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Check if input type requires numeric formatting
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```typescript
|
|
108
|
-
* shouldFormat('currency') // true
|
|
109
|
-
* shouldFormat('percent') // true
|
|
110
|
-
* shouldFormat('text') // false
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
51
|
export function shouldFormat(type) {
|
|
114
52
|
return ['number', 'currency', 'percent', 'compact'].includes(type);
|
|
115
53
|
}
|
|
116
|
-
//# sourceMappingURL=number-format.js.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Core positioning engine for floating elements
|
|
3
|
-
* Adapted from ty.positioning ClojureScript implementation
|
|
4
3
|
*
|
|
5
4
|
* Handles smart positioning of tooltips, dropdowns, popups, and other
|
|
6
5
|
* floating elements relative to anchor elements with automatic overflow
|
|
@@ -147,4 +146,3 @@ export interface AnchoredPopupPosition {
|
|
|
147
146
|
below: boolean;
|
|
148
147
|
}
|
|
149
148
|
export declare function computeAnchoredPosition(o: AnchoredPopupOptions): AnchoredPopupPosition;
|
|
150
|
-
//# sourceMappingURL=positioning.d.ts.map
|
package/lib/utils/positioning.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core positioning engine for floating elements
|
|
3
|
-
* Adapted from ty.positioning ClojureScript implementation
|
|
4
|
-
*
|
|
5
|
-
* Handles smart positioning of tooltips, dropdowns, popups, and other
|
|
6
|
-
* floating elements relative to anchor elements with automatic overflow
|
|
7
|
-
* detection and placement fallback.
|
|
8
|
-
*/
|
|
9
|
-
// ============================================================================
|
|
10
|
-
// Placement Definitions
|
|
11
|
-
// ============================================================================
|
|
12
|
-
/**
|
|
13
|
-
* Map of all placement configurations
|
|
14
|
-
*/
|
|
15
1
|
export const placements = {
|
|
16
2
|
'top-start': {
|
|
17
3
|
vertical: 'top',
|
|
@@ -68,9 +54,6 @@ export const placements = {
|
|
|
68
54
|
orientation: 'vertical',
|
|
69
55
|
},
|
|
70
56
|
};
|
|
71
|
-
/**
|
|
72
|
-
* Default placement preference lists for different use cases
|
|
73
|
-
*/
|
|
74
57
|
export const placementPreferences = {
|
|
75
58
|
default: [
|
|
76
59
|
'bottom-start', 'bottom-end', 'top-start', 'top-end',
|
|
@@ -85,12 +68,6 @@ export const placementPreferences = {
|
|
|
85
68
|
'bottom', 'top', 'right', 'left'
|
|
86
69
|
],
|
|
87
70
|
};
|
|
88
|
-
// ============================================================================
|
|
89
|
-
// DOM Measurement Helpers
|
|
90
|
-
// ============================================================================
|
|
91
|
-
/**
|
|
92
|
-
* Get element dimensions relative to viewport with calculated center points
|
|
93
|
-
*/
|
|
94
71
|
function getElementRect(el) {
|
|
95
72
|
const rect = el.getBoundingClientRect();
|
|
96
73
|
return {
|
|
@@ -104,9 +81,6 @@ function getElementRect(el) {
|
|
|
104
81
|
centerY: rect.top + rect.height / 2,
|
|
105
82
|
};
|
|
106
83
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Get viewport dimensions and scroll position
|
|
109
|
-
*/
|
|
110
84
|
function getViewportRect() {
|
|
111
85
|
return {
|
|
112
86
|
width: window.innerWidth,
|
|
@@ -115,22 +89,13 @@ function getViewportRect() {
|
|
|
115
89
|
scrollY: window.scrollY,
|
|
116
90
|
};
|
|
117
91
|
}
|
|
118
|
-
// ============================================================================
|
|
119
|
-
// Position Calculation
|
|
120
|
-
// ============================================================================
|
|
121
|
-
/**
|
|
122
|
-
* Calculate position for a specific placement
|
|
123
|
-
* Returns x, y coordinates and overflow information
|
|
124
|
-
*/
|
|
125
92
|
function calculatePlacement(options) {
|
|
126
93
|
const { targetRect, floatingRect, placement, offset, padding, scrollbarWidth, containerPadding, } = options;
|
|
127
94
|
const config = placements[placement];
|
|
128
95
|
const { vertical, horizontal, orientation } = config;
|
|
129
96
|
const viewport = getViewportRect();
|
|
130
|
-
// Calculate X position
|
|
131
97
|
let x;
|
|
132
98
|
if (orientation === 'vertical') {
|
|
133
|
-
// Left/right placements
|
|
134
99
|
if (horizontal === 'start') {
|
|
135
100
|
x = targetRect.left - floatingRect.width - offset + containerPadding;
|
|
136
101
|
}
|
|
@@ -139,7 +104,6 @@ function calculatePlacement(options) {
|
|
|
139
104
|
}
|
|
140
105
|
}
|
|
141
106
|
else {
|
|
142
|
-
// Top/bottom placements
|
|
143
107
|
if (horizontal === 'start') {
|
|
144
108
|
x = targetRect.left;
|
|
145
109
|
}
|
|
@@ -150,10 +114,8 @@ function calculatePlacement(options) {
|
|
|
150
114
|
x = targetRect.right - floatingRect.width;
|
|
151
115
|
}
|
|
152
116
|
}
|
|
153
|
-
// Calculate Y position
|
|
154
117
|
let y;
|
|
155
118
|
if (orientation === 'vertical') {
|
|
156
|
-
// Left/right placements
|
|
157
119
|
if (vertical === 'center') {
|
|
158
120
|
y = targetRect.centerY - floatingRect.height / 2;
|
|
159
121
|
}
|
|
@@ -165,7 +127,6 @@ function calculatePlacement(options) {
|
|
|
165
127
|
}
|
|
166
128
|
}
|
|
167
129
|
else {
|
|
168
|
-
// Top/bottom placements
|
|
169
130
|
if (vertical === 'top') {
|
|
170
131
|
y = targetRect.top - floatingRect.height - offset + containerPadding;
|
|
171
132
|
}
|
|
@@ -173,14 +134,12 @@ function calculatePlacement(options) {
|
|
|
173
134
|
y = targetRect.bottom + offset - containerPadding;
|
|
174
135
|
}
|
|
175
136
|
}
|
|
176
|
-
// Calculate overflow for each edge
|
|
177
137
|
const overflow = {
|
|
178
138
|
top: Math.min(0, y - padding),
|
|
179
139
|
left: Math.min(0, x - padding),
|
|
180
140
|
bottom: Math.min(0, viewport.height - (y + floatingRect.height + padding)),
|
|
181
141
|
right: Math.min(0, viewport.width - (x + floatingRect.width + padding + scrollbarWidth)),
|
|
182
142
|
};
|
|
183
|
-
// Sum of absolute overflow values
|
|
184
143
|
const overflowAmount = Object.values(overflow).reduce((sum, val) => sum + Math.abs(val), 0);
|
|
185
144
|
return {
|
|
186
145
|
x: Math.round(x),
|
|
@@ -191,16 +150,11 @@ function calculatePlacement(options) {
|
|
|
191
150
|
fits: overflowAmount === 0,
|
|
192
151
|
};
|
|
193
152
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Find the best position for the floating element
|
|
196
|
-
* Tries all preference placements and returns the one that fits best
|
|
197
|
-
*/
|
|
198
153
|
export function findBestPosition(options) {
|
|
199
154
|
const { targetEl, floatingEl, preferences = placementPreferences.default, offset = 8, padding = 8, containerPadding = 0, } = options;
|
|
200
155
|
const targetRect = getElementRect(targetEl);
|
|
201
156
|
const floatingRect = getElementRect(floatingEl);
|
|
202
157
|
const scrollbarWidth = 15;
|
|
203
|
-
// Calculate all candidate positions
|
|
204
158
|
const candidates = preferences.map(placement => calculatePlacement({
|
|
205
159
|
targetRect,
|
|
206
160
|
floatingRect,
|
|
@@ -210,10 +164,8 @@ export function findBestPosition(options) {
|
|
|
210
164
|
containerPadding,
|
|
211
165
|
scrollbarWidth,
|
|
212
166
|
}));
|
|
213
|
-
// Find first that fits, or one with least overflow
|
|
214
167
|
const bestPosition = candidates.find(c => c.fits) ||
|
|
215
168
|
candidates.reduce((best, current) => current.overflowAmount < best.overflowAmount ? current : best);
|
|
216
|
-
// Adjust for scrollbar if needed
|
|
217
169
|
if (bestPosition.overflow.right < 0) {
|
|
218
170
|
bestPosition.x += bestPosition.overflow.right;
|
|
219
171
|
}
|
|
@@ -226,12 +178,7 @@ export function computeAnchoredPosition(o) {
|
|
|
226
178
|
const vh = window.innerHeight;
|
|
227
179
|
const spaceBelow = vh - o.anchorRect.bottom;
|
|
228
180
|
const spaceAbove = o.anchorRect.top;
|
|
229
|
-
// Below when it fits — and when neither side fits, the side with MORE room
|
|
230
|
-
// instead of blindly flipping up (a trigger near the viewport top used to
|
|
231
|
-
// clip the popup off-screen).
|
|
232
181
|
const below = spaceBelow >= o.popupHeight + gap + padding || spaceBelow >= spaceAbove;
|
|
233
|
-
// Anchor to the trigger's left edge ("start") or right edge ("end"),
|
|
234
|
-
// clamped into the viewport either way.
|
|
235
182
|
const rawX = o.align === "end" ? o.anchorRect.right - o.popupWidth : o.anchorRect.left;
|
|
236
183
|
const x = Math.max(padding, Math.min(rawX, vw - o.popupWidth - padding));
|
|
237
184
|
return {
|
|
@@ -241,4 +188,3 @@ export function computeAnchoredPosition(o) {
|
|
|
241
188
|
below,
|
|
242
189
|
};
|
|
243
190
|
}
|
|
244
|
-
//# sourceMappingURL=positioning.js.map
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Property Capture Utility
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* 2. Framework sets properties: element.value = "foo"
|
|
10
|
-
* 3. Constructor runs and defines getters/setters
|
|
11
|
-
* 4. BUT properties were already set, creating instance properties
|
|
12
|
-
* 5. Instance properties shadow the class getters/setters
|
|
13
|
-
* 6. connectedCallback runs - too late!
|
|
14
|
-
*
|
|
15
|
-
* SOLUTION:
|
|
16
|
-
* In connectedCallback, capture any pre-set properties and apply them properly.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* connectedCallback(): void {
|
|
21
|
-
* const preSetProps = capturePreSetProperties(this, [
|
|
22
|
-
* 'value', 'clearable', 'disabled'
|
|
23
|
-
* ])
|
|
24
|
-
*
|
|
25
|
-
* if (preSetProps.value !== undefined) {
|
|
26
|
-
* this._value = preSetProps.value
|
|
27
|
-
* }
|
|
28
|
-
* }
|
|
29
|
-
* ```
|
|
4
|
+
* Frameworks (React, Reagent, ...) set properties on a custom element before
|
|
5
|
+
* the constructor defines its getters/setters, so those assignments become
|
|
6
|
+
* *instance* properties that permanently shadow the class accessors — by the
|
|
7
|
+
* time connectedCallback runs, the setters have never been called.
|
|
8
|
+
* Fix: in connectedCallback, capture the pre-set values and re-apply them.
|
|
30
9
|
*/
|
|
31
10
|
/**
|
|
32
11
|
* Captured property data
|
|
@@ -129,4 +108,3 @@ export declare function applyPreSetProperties(element: any, propertyNames: strin
|
|
|
129
108
|
* ```
|
|
130
109
|
*/
|
|
131
110
|
export declare function captureAndApplyProperties(element: any, propertyNames: string[], transformer?: (name: string, value: any) => any, options?: PropertyCaptureOptions): void;
|
|
132
|
-
//# sourceMappingURL=property-capture.d.ts.map
|
|
@@ -1,50 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Property Capture Utility
|
|
3
|
-
*
|
|
4
|
-
* Solves the problem of frameworks (React, Reagent, etc.) setting properties
|
|
5
|
-
* on custom elements BEFORE connectedCallback runs.
|
|
6
|
-
*
|
|
7
|
-
* PROBLEM:
|
|
8
|
-
* 1. Framework creates element: document.createElement('ty-dropdown')
|
|
9
|
-
* 2. Framework sets properties: element.value = "foo"
|
|
10
|
-
* 3. Constructor runs and defines getters/setters
|
|
11
|
-
* 4. BUT properties were already set, creating instance properties
|
|
12
|
-
* 5. Instance properties shadow the class getters/setters
|
|
13
|
-
* 6. connectedCallback runs - too late!
|
|
14
|
-
*
|
|
15
|
-
* SOLUTION:
|
|
16
|
-
* In connectedCallback, capture any pre-set properties and apply them properly.
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* connectedCallback(): void {
|
|
21
|
-
* const preSetProps = capturePreSetProperties(this, [
|
|
22
|
-
* 'value', 'clearable', 'disabled'
|
|
23
|
-
* ])
|
|
24
|
-
*
|
|
25
|
-
* if (preSetProps.value !== undefined) {
|
|
26
|
-
* this._value = preSetProps.value
|
|
27
|
-
* }
|
|
28
|
-
* }
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
/**
|
|
32
|
-
* Capture properties that were set before connectedCallback
|
|
33
|
-
*
|
|
34
|
-
* @param element - The custom element instance
|
|
35
|
-
* @param propertyNames - Array of property names to check
|
|
36
|
-
* @param options - Capture options
|
|
37
|
-
* @returns Record of captured properties with metadata
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* ```typescript
|
|
41
|
-
* const captured = capturePreSetProperties(this, ['value', 'disabled'])
|
|
42
|
-
* // {
|
|
43
|
-
* // value: { name: 'value', value: 'foo', hadProperty: true },
|
|
44
|
-
* // disabled: { name: 'disabled', value: undefined, hadProperty: false }
|
|
45
|
-
* // }
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
1
|
export function capturePreSetProperties(element, propertyNames, options = { cleanup: true }) {
|
|
49
2
|
const captured = {};
|
|
50
3
|
for (const name of propertyNames) {
|
|
@@ -54,29 +7,12 @@ export function capturePreSetProperties(element, propertyNames, options = { clea
|
|
|
54
7
|
value: descriptor?.value,
|
|
55
8
|
hadProperty: descriptor !== undefined && descriptor.value !== undefined
|
|
56
9
|
};
|
|
57
|
-
// Clean up instance property so class getter/setter works
|
|
58
10
|
if (options.cleanup && captured[name].hadProperty) {
|
|
59
11
|
delete element[name];
|
|
60
12
|
}
|
|
61
13
|
}
|
|
62
14
|
return captured;
|
|
63
15
|
}
|
|
64
|
-
/**
|
|
65
|
-
* Simpler API - just get the values that were pre-set
|
|
66
|
-
*
|
|
67
|
-
* @param element - The custom element instance
|
|
68
|
-
* @param propertyNames - Array of property names to check
|
|
69
|
-
* @param options - Capture options
|
|
70
|
-
* @returns Record of property names to values (only includes properties that were set)
|
|
71
|
-
*
|
|
72
|
-
* @example
|
|
73
|
-
* ```typescript
|
|
74
|
-
* const values = getCapturedValues(this, ['value', 'disabled'])
|
|
75
|
-
* if (values.value !== undefined) {
|
|
76
|
-
* this._value = values.value
|
|
77
|
-
* }
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
16
|
export function getCapturedValues(element, propertyNames, options) {
|
|
81
17
|
const captured = capturePreSetProperties(element, propertyNames, options);
|
|
82
18
|
const values = {};
|
|
@@ -87,58 +23,15 @@ export function getCapturedValues(element, propertyNames, options) {
|
|
|
87
23
|
}
|
|
88
24
|
return values;
|
|
89
25
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Automatically apply pre-set properties to private fields
|
|
92
|
-
*
|
|
93
|
-
* @param element - The custom element instance
|
|
94
|
-
* @param propertyNames - Array of property names to check
|
|
95
|
-
* @param propertyMap - Optional mapping of public names to private field names
|
|
96
|
-
* Default: adds underscore prefix (e.g., 'value' -> '_value')
|
|
97
|
-
* @param options - Capture options
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* // Simple usage (uses _propertyName convention)
|
|
102
|
-
* applyPreSetProperties(this, ['value', 'disabled'])
|
|
103
|
-
* // Sets this._value and this._disabled
|
|
104
|
-
*
|
|
105
|
-
* // Custom mapping
|
|
106
|
-
* applyPreSetProperties(this, ['value'], { value: 'internalValue' })
|
|
107
|
-
* // Sets this.internalValue
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
26
|
export function applyPreSetProperties(element, propertyNames, propertyMap, options) {
|
|
111
27
|
const captured = capturePreSetProperties(element, propertyNames, options);
|
|
112
28
|
for (const [name, data] of Object.entries(captured)) {
|
|
113
29
|
if (data.hadProperty) {
|
|
114
|
-
// Determine the private field name
|
|
115
30
|
const privateName = propertyMap?.[name] || `_${name}`;
|
|
116
31
|
element[privateName] = data.value;
|
|
117
32
|
}
|
|
118
33
|
}
|
|
119
34
|
}
|
|
120
|
-
/**
|
|
121
|
-
* Helper for components with standard _propertyName pattern
|
|
122
|
-
*
|
|
123
|
-
* @param element - The custom element instance
|
|
124
|
-
* @param propertyNames - Array of property names to check
|
|
125
|
-
* @param transformer - Optional function to transform values before setting
|
|
126
|
-
* @param options - Capture options
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```typescript
|
|
130
|
-
* connectedCallback(): void {
|
|
131
|
-
* // Basic usage
|
|
132
|
-
* captureAndApplyProperties(this, ['value', 'disabled', 'required'])
|
|
133
|
-
*
|
|
134
|
-
* // With transformation
|
|
135
|
-
* captureAndApplyProperties(this, ['value'], (name, value) => {
|
|
136
|
-
* if (name === 'value') return this.parseValue(value)
|
|
137
|
-
* return value
|
|
138
|
-
* })
|
|
139
|
-
* }
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
35
|
export function captureAndApplyProperties(element, propertyNames, transformer, options) {
|
|
143
36
|
const captured = capturePreSetProperties(element, propertyNames, options);
|
|
144
37
|
for (const [name, data] of Object.entries(captured)) {
|
|
@@ -149,4 +42,3 @@ export function captureAndApplyProperties(element, propertyNames, transformer, o
|
|
|
149
42
|
}
|
|
150
43
|
}
|
|
151
44
|
}
|
|
152
|
-
//# sourceMappingURL=property-capture.js.map
|
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Property Manager - Unified property lifecycle for web components
|
|
3
|
-
*
|
|
4
|
-
* Handles property/attribute synchronization, validation, coercion, and change tracking.
|
|
5
|
-
* All property updates flow through a single code path for consistency.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Manages component properties with unified lifecycle
|
|
9
|
-
*/
|
|
10
1
|
export class PropertyManager {
|
|
11
2
|
constructor(config) {
|
|
12
3
|
this._props = new Map();
|
|
13
4
|
this._config = config;
|
|
14
5
|
this._initializeDefaults();
|
|
15
6
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Initialize properties with default values
|
|
18
|
-
*/
|
|
19
7
|
_initializeDefaults() {
|
|
20
8
|
for (const [name, config] of Object.entries(this._config)) {
|
|
21
9
|
if (config.default !== undefined) {
|
|
@@ -23,38 +11,25 @@ export class PropertyManager {
|
|
|
23
11
|
}
|
|
24
12
|
}
|
|
25
13
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Check if a property name exists in the configuration
|
|
28
|
-
*/
|
|
29
14
|
hasConfig(name) {
|
|
30
15
|
return name in this._config;
|
|
31
16
|
}
|
|
32
|
-
/**
|
|
33
|
-
* Update a property value
|
|
34
|
-
* Returns PropertyChange if value changed, null otherwise
|
|
35
|
-
*/
|
|
36
17
|
updateProperty(name, value, source = 'property') {
|
|
37
18
|
const config = this._config[name];
|
|
38
19
|
if (!config) {
|
|
39
20
|
console.warn(`[PropertyManager] Unknown property: ${name}`);
|
|
40
21
|
return null;
|
|
41
22
|
}
|
|
42
|
-
// Get old value
|
|
43
23
|
const oldValue = this._props.get(name);
|
|
44
|
-
// Coerce value to correct type
|
|
45
24
|
const coercedValue = this._coerceValue(name, value, config);
|
|
46
|
-
// Validate value
|
|
47
25
|
if (!this._validateValue(name, coercedValue, config)) {
|
|
48
26
|
console.warn(`[PropertyManager] Invalid value for ${name}:`, coercedValue);
|
|
49
27
|
return null;
|
|
50
28
|
}
|
|
51
|
-
// Check if value actually changed
|
|
52
29
|
if (this._valuesEqual(oldValue, coercedValue)) {
|
|
53
30
|
return null;
|
|
54
31
|
}
|
|
55
|
-
// Update internal map
|
|
56
32
|
this._props.set(name, coercedValue);
|
|
57
|
-
// Create change object
|
|
58
33
|
const change = {
|
|
59
34
|
name,
|
|
60
35
|
oldValue,
|
|
@@ -63,35 +38,23 @@ export class PropertyManager {
|
|
|
63
38
|
};
|
|
64
39
|
return change;
|
|
65
40
|
}
|
|
66
|
-
/**
|
|
67
|
-
* Coerce value to the correct type
|
|
68
|
-
*/
|
|
69
41
|
_coerceValue(name, value, config) {
|
|
70
|
-
// Custom coercion
|
|
71
42
|
if (config.coerce) {
|
|
72
43
|
return config.coerce(value);
|
|
73
44
|
}
|
|
74
|
-
// Null/undefined handling
|
|
75
45
|
if (value === null || value === undefined) {
|
|
76
46
|
return config.default ?? null;
|
|
77
47
|
}
|
|
78
|
-
// Type coercion
|
|
79
48
|
switch (config.type) {
|
|
80
49
|
case 'boolean':
|
|
81
|
-
// HTML Standard: attribute present (even empty) = true, absent = false
|
|
82
|
-
// String handling:
|
|
83
50
|
if (typeof value === 'string') {
|
|
84
|
-
// Empty string = true (HTML boolean attribute: <input checked>)
|
|
85
51
|
if (value === '')
|
|
86
52
|
return true;
|
|
87
|
-
// Explicit false values
|
|
88
53
|
const normalized = value.toLowerCase().trim();
|
|
89
54
|
if (normalized === 'false' || normalized === '0')
|
|
90
55
|
return false;
|
|
91
|
-
// Everything else is truthy
|
|
92
56
|
return true;
|
|
93
57
|
}
|
|
94
|
-
// Non-string: standard truthy/falsy
|
|
95
58
|
return Boolean(value);
|
|
96
59
|
case 'number':
|
|
97
60
|
const num = Number(value);
|
|
@@ -114,29 +77,19 @@ export class PropertyManager {
|
|
|
114
77
|
return value;
|
|
115
78
|
}
|
|
116
79
|
}
|
|
117
|
-
/**
|
|
118
|
-
* Validate a property value
|
|
119
|
-
*/
|
|
120
80
|
_validateValue(name, value, config) {
|
|
121
81
|
if (config.validate) {
|
|
122
82
|
return config.validate(value);
|
|
123
83
|
}
|
|
124
84
|
return true;
|
|
125
85
|
}
|
|
126
|
-
/**
|
|
127
|
-
* Check if two values are equal
|
|
128
|
-
*/
|
|
129
86
|
_valuesEqual(a, b) {
|
|
130
|
-
// Simple equality for primitives
|
|
131
87
|
if (typeof a !== 'object' || typeof b !== 'object') {
|
|
132
88
|
return a === b;
|
|
133
89
|
}
|
|
134
|
-
// Null checks
|
|
135
90
|
if (a === null || b === null) {
|
|
136
91
|
return a === b;
|
|
137
92
|
}
|
|
138
|
-
// Deep equality for objects/arrays (simple implementation)
|
|
139
|
-
// For production, consider using a proper deep equality library
|
|
140
93
|
try {
|
|
141
94
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
142
95
|
}
|
|
@@ -144,47 +97,25 @@ export class PropertyManager {
|
|
|
144
97
|
return false;
|
|
145
98
|
}
|
|
146
99
|
}
|
|
147
|
-
/**
|
|
148
|
-
* Get a property value
|
|
149
|
-
*/
|
|
150
100
|
get(name) {
|
|
151
101
|
return this._props.get(name);
|
|
152
102
|
}
|
|
153
|
-
/**
|
|
154
|
-
* Get all properties as an object
|
|
155
|
-
*/
|
|
156
103
|
getAll() {
|
|
157
104
|
return Object.fromEntries(this._props);
|
|
158
105
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Get property configuration
|
|
161
|
-
*/
|
|
162
106
|
getConfig(name) {
|
|
163
107
|
return this._config[name];
|
|
164
108
|
}
|
|
165
|
-
/**
|
|
166
|
-
* Check if a property is visual (requires render)
|
|
167
|
-
*/
|
|
168
109
|
isVisual(name) {
|
|
169
110
|
return this._config[name]?.visual ?? false;
|
|
170
111
|
}
|
|
171
|
-
/**
|
|
172
|
-
* Check if a property affects form value
|
|
173
|
-
*/
|
|
174
112
|
isFormValue(name) {
|
|
175
113
|
return this._config[name]?.formValue ?? false;
|
|
176
114
|
}
|
|
177
|
-
/**
|
|
178
|
-
* Check if a property should emit change events
|
|
179
|
-
*/
|
|
180
115
|
shouldEmitChange(name) {
|
|
181
116
|
return this._config[name]?.emitChange ?? false;
|
|
182
117
|
}
|
|
183
|
-
/**
|
|
184
|
-
* Handle property aliases (e.g., not-clearable → clearable: false)
|
|
185
|
-
*/
|
|
186
118
|
handleAlias(aliasName, value) {
|
|
187
|
-
// Find property with this alias
|
|
188
119
|
for (const [propName, config] of Object.entries(this._config)) {
|
|
189
120
|
if (config.aliases && aliasName in config.aliases) {
|
|
190
121
|
const aliasedValue = config.aliases[aliasName];
|
|
@@ -194,4 +125,3 @@ export class PropertyManager {
|
|
|
194
125
|
return null;
|
|
195
126
|
}
|
|
196
127
|
}
|
|
197
|
-
//# sourceMappingURL=property-manager.js.map
|