@number10/jsx-core 5.0.0
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 +667 -0
- package/README.md +38 -0
- package/dist/animation/animated-signal.cjs +19 -0
- package/dist/animation/animated-signal.cjs.map +1 -0
- package/dist/animation/animated-signal.d.ts +35 -0
- package/dist/animation/animated-signal.d.ts.map +1 -0
- package/dist/animation/animated-signal.js +19 -0
- package/dist/animation/animated-signal.js.map +1 -0
- package/dist/animation/create-spring.cjs +80 -0
- package/dist/animation/create-spring.cjs.map +1 -0
- package/dist/animation/create-spring.d.ts +56 -0
- package/dist/animation/create-spring.d.ts.map +1 -0
- package/dist/animation/create-spring.js +80 -0
- package/dist/animation/create-spring.js.map +1 -0
- package/dist/animation/easing.cjs +76 -0
- package/dist/animation/easing.cjs.map +1 -0
- package/dist/animation/easing.d.ts +45 -0
- package/dist/animation/easing.d.ts.map +1 -0
- package/dist/animation/easing.js +76 -0
- package/dist/animation/easing.js.map +1 -0
- package/dist/animation/effect-definitions.cjs +441 -0
- package/dist/animation/effect-definitions.cjs.map +1 -0
- package/dist/animation/effect-definitions.d.ts +60 -0
- package/dist/animation/effect-definitions.d.ts.map +1 -0
- package/dist/animation/effect-definitions.js +441 -0
- package/dist/animation/effect-definitions.js.map +1 -0
- package/dist/animation/effect-engine.cjs +189 -0
- package/dist/animation/effect-engine.cjs.map +1 -0
- package/dist/animation/effect-engine.d.ts +70 -0
- package/dist/animation/effect-engine.d.ts.map +1 -0
- package/dist/animation/effect-engine.js +189 -0
- package/dist/animation/effect-engine.js.map +1 -0
- package/dist/animation/index.d.ts +24 -0
- package/dist/animation/index.d.ts.map +1 -0
- package/dist/animation/spring-physics.cjs +94 -0
- package/dist/animation/spring-physics.cjs.map +1 -0
- package/dist/animation/spring-physics.d.ts +145 -0
- package/dist/animation/spring-physics.d.ts.map +1 -0
- package/dist/animation/spring-physics.js +94 -0
- package/dist/animation/spring-physics.js.map +1 -0
- package/dist/animation/tween.cjs +67 -0
- package/dist/animation/tween.cjs.map +1 -0
- package/dist/animation/tween.d.ts +60 -0
- package/dist/animation/tween.d.ts.map +1 -0
- package/dist/animation/tween.js +67 -0
- package/dist/animation/tween.js.map +1 -0
- package/dist/animation/types.d.ts +31 -0
- package/dist/animation/types.d.ts.map +1 -0
- package/dist/animation/useSpring.cjs +152 -0
- package/dist/animation/useSpring.cjs.map +1 -0
- package/dist/animation/useSpring.d.ts +55 -0
- package/dist/animation/useSpring.d.ts.map +1 -0
- package/dist/animation/useSpring.js +149 -0
- package/dist/animation/useSpring.js.map +1 -0
- package/dist/animation/useTween.cjs +208 -0
- package/dist/animation/useTween.cjs.map +1 -0
- package/dist/animation/useTween.d.ts +116 -0
- package/dist/animation/useTween.d.ts.map +1 -0
- package/dist/animation/useTween.js +208 -0
- package/dist/animation/useTween.js.map +1 -0
- package/dist/border-geometry.cjs +447 -0
- package/dist/border-geometry.cjs.map +1 -0
- package/dist/border-geometry.d.ts +114 -0
- package/dist/border-geometry.d.ts.map +1 -0
- package/dist/border-geometry.js +447 -0
- package/dist/border-geometry.js.map +1 -0
- package/dist/colors/color-presets.cjs +236 -0
- package/dist/colors/color-presets.cjs.map +1 -0
- package/dist/colors/color-presets.d.ts +89 -0
- package/dist/colors/color-presets.d.ts.map +1 -0
- package/dist/colors/color-presets.js +236 -0
- package/dist/colors/color-presets.js.map +1 -0
- package/dist/colors/color-theme-helpers.cjs +32 -0
- package/dist/colors/color-theme-helpers.cjs.map +1 -0
- package/dist/colors/color-theme-helpers.d.ts +65 -0
- package/dist/colors/color-theme-helpers.d.ts.map +1 -0
- package/dist/colors/color-theme-helpers.js +32 -0
- package/dist/colors/color-theme-helpers.js.map +1 -0
- package/dist/colors/color-types.cjs +38 -0
- package/dist/colors/color-types.cjs.map +1 -0
- package/dist/colors/color-types.d.ts +112 -0
- package/dist/colors/color-types.d.ts.map +1 -0
- package/dist/colors/color-types.js +38 -0
- package/dist/colors/color-types.js.map +1 -0
- package/dist/colors/color-utils.cjs +197 -0
- package/dist/colors/color-utils.cjs.map +1 -0
- package/dist/colors/color-utils.d.ts +216 -0
- package/dist/colors/color-utils.d.ts.map +1 -0
- package/dist/colors/color-utils.js +197 -0
- package/dist/colors/color-utils.js.map +1 -0
- package/dist/colors/contrast-contracts.cjs +265 -0
- package/dist/colors/contrast-contracts.cjs.map +1 -0
- package/dist/colors/contrast-contracts.d.ts +289 -0
- package/dist/colors/contrast-contracts.d.ts.map +1 -0
- package/dist/colors/contrast-contracts.js +265 -0
- package/dist/colors/contrast-contracts.js.map +1 -0
- package/dist/colors/index.cjs +55 -0
- package/dist/colors/index.cjs.map +1 -0
- package/dist/colors/index.d.ts +16 -0
- package/dist/colors/index.d.ts.map +1 -0
- package/dist/colors/index.js +55 -0
- package/dist/colors/index.js.map +1 -0
- package/dist/core-props.cjs +66 -0
- package/dist/core-props.cjs.map +1 -0
- package/dist/core-props.d.ts +395 -0
- package/dist/core-props.d.ts.map +1 -0
- package/dist/core-props.js +66 -0
- package/dist/core-props.js.map +1 -0
- package/dist/design-tokens/design-token-presets.cjs +91 -0
- package/dist/design-tokens/design-token-presets.cjs.map +1 -0
- package/dist/design-tokens/design-token-presets.d.ts +34 -0
- package/dist/design-tokens/design-token-presets.d.ts.map +1 -0
- package/dist/design-tokens/design-token-presets.js +91 -0
- package/dist/design-tokens/design-token-presets.js.map +1 -0
- package/dist/design-tokens/design-token-types.d.ts +97 -0
- package/dist/design-tokens/design-token-types.d.ts.map +1 -0
- package/dist/design-tokens/index.cjs +10 -0
- package/dist/design-tokens/index.cjs.map +1 -0
- package/dist/design-tokens/index.d.ts +9 -0
- package/dist/design-tokens/index.d.ts.map +1 -0
- package/dist/design-tokens/index.js +10 -0
- package/dist/design-tokens/index.js.map +1 -0
- package/dist/dev-config.cjs +296 -0
- package/dist/dev-config.cjs.map +1 -0
- package/dist/dev-config.d.ts +238 -0
- package/dist/dev-config.d.ts.map +1 -0
- package/dist/dev-config.js +296 -0
- package/dist/dev-config.js.map +1 -0
- package/dist/effects.cjs +69 -0
- package/dist/effects.cjs.map +1 -0
- package/dist/effects.d.ts +152 -0
- package/dist/effects.d.ts.map +1 -0
- package/dist/effects.js +69 -0
- package/dist/effects.js.map +1 -0
- package/dist/global-registry.cjs +25 -0
- package/dist/global-registry.cjs.map +1 -0
- package/dist/global-registry.d.ts +19 -0
- package/dist/global-registry.d.ts.map +1 -0
- package/dist/global-registry.js +25 -0
- package/dist/global-registry.js.map +1 -0
- package/dist/hooks.cjs +378 -0
- package/dist/hooks.cjs.map +1 -0
- package/dist/hooks.d.ts +322 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +378 -0
- package/dist/hooks.js.map +1 -0
- package/dist/host-adapter.d.ts +414 -0
- package/dist/host-adapter.d.ts.map +1 -0
- package/dist/index.cjs +229 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +226 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.cjs +10 -0
- package/dist/jsx-dev-runtime.cjs.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +5 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +11 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.cjs +44 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.d.ts +24 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +44 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/jsx-types.d.ts +25 -0
- package/dist/jsx-types.d.ts.map +1 -0
- package/dist/layout/appliers/container-applier.cjs +20 -0
- package/dist/layout/appliers/container-applier.cjs.map +1 -0
- package/dist/layout/appliers/container-applier.d.ts +9 -0
- package/dist/layout/appliers/container-applier.d.ts.map +1 -0
- package/dist/layout/appliers/container-applier.js +20 -0
- package/dist/layout/appliers/container-applier.js.map +1 -0
- package/dist/layout/appliers/position-applier.cjs +31 -0
- package/dist/layout/appliers/position-applier.cjs.map +1 -0
- package/dist/layout/appliers/position-applier.d.ts +8 -0
- package/dist/layout/appliers/position-applier.d.ts.map +1 -0
- package/dist/layout/appliers/position-applier.js +31 -0
- package/dist/layout/appliers/position-applier.js.map +1 -0
- package/dist/layout/layout-engine-test-utils.d.ts +26 -0
- package/dist/layout/layout-engine-test-utils.d.ts.map +1 -0
- package/dist/layout/layout-engine.cjs +628 -0
- package/dist/layout/layout-engine.cjs.map +1 -0
- package/dist/layout/layout-engine.d.ts +140 -0
- package/dist/layout/layout-engine.d.ts.map +1 -0
- package/dist/layout/layout-engine.js +628 -0
- package/dist/layout/layout-engine.js.map +1 -0
- package/dist/layout/strategies/base-strategy.cjs +31 -0
- package/dist/layout/strategies/base-strategy.cjs.map +1 -0
- package/dist/layout/strategies/base-strategy.d.ts +59 -0
- package/dist/layout/strategies/base-strategy.d.ts.map +1 -0
- package/dist/layout/strategies/base-strategy.js +31 -0
- package/dist/layout/strategies/base-strategy.js.map +1 -0
- package/dist/layout/strategies/column-layout.cjs +145 -0
- package/dist/layout/strategies/column-layout.cjs.map +1 -0
- package/dist/layout/strategies/column-layout.d.ts +38 -0
- package/dist/layout/strategies/column-layout.d.ts.map +1 -0
- package/dist/layout/strategies/column-layout.js +145 -0
- package/dist/layout/strategies/column-layout.js.map +1 -0
- package/dist/layout/strategies/row-layout.cjs +145 -0
- package/dist/layout/strategies/row-layout.cjs.map +1 -0
- package/dist/layout/strategies/row-layout.d.ts +38 -0
- package/dist/layout/strategies/row-layout.d.ts.map +1 -0
- package/dist/layout/strategies/row-layout.js +145 -0
- package/dist/layout/strategies/row-layout.js.map +1 -0
- package/dist/layout/strategies/stack-layout.cjs +94 -0
- package/dist/layout/strategies/stack-layout.cjs.map +1 -0
- package/dist/layout/strategies/stack-layout.d.ts +30 -0
- package/dist/layout/strategies/stack-layout.d.ts.map +1 -0
- package/dist/layout/strategies/stack-layout.js +94 -0
- package/dist/layout/strategies/stack-layout.js.map +1 -0
- package/dist/layout/types.d.ts +134 -0
- package/dist/layout/types.d.ts.map +1 -0
- package/dist/layout/utils/child-utils.cjs +129 -0
- package/dist/layout/utils/child-utils.cjs.map +1 -0
- package/dist/layout/utils/child-utils.d.ts +54 -0
- package/dist/layout/utils/child-utils.d.ts.map +1 -0
- package/dist/layout/utils/child-utils.js +129 -0
- package/dist/layout/utils/child-utils.js.map +1 -0
- package/dist/layout/utils/dimension-calculator.cjs +109 -0
- package/dist/layout/utils/dimension-calculator.cjs.map +1 -0
- package/dist/layout/utils/dimension-calculator.d.ts +59 -0
- package/dist/layout/utils/dimension-calculator.d.ts.map +1 -0
- package/dist/layout/utils/dimension-calculator.js +109 -0
- package/dist/layout/utils/dimension-calculator.js.map +1 -0
- package/dist/layout/utils/flex-distributor.cjs +173 -0
- package/dist/layout/utils/flex-distributor.cjs.map +1 -0
- package/dist/layout/utils/flex-distributor.d.ts +18 -0
- package/dist/layout/utils/flex-distributor.d.ts.map +1 -0
- package/dist/layout/utils/flex-distributor.js +173 -0
- package/dist/layout/utils/flex-distributor.js.map +1 -0
- package/dist/layout/utils/size-resolver.cjs +280 -0
- package/dist/layout/utils/size-resolver.cjs.map +1 -0
- package/dist/layout/utils/size-resolver.d.ts +84 -0
- package/dist/layout/utils/size-resolver.d.ts.map +1 -0
- package/dist/layout/utils/size-resolver.js +280 -0
- package/dist/layout/utils/size-resolver.js.map +1 -0
- package/dist/layout/utils/spacing-calculator.cjs +50 -0
- package/dist/layout/utils/spacing-calculator.cjs.map +1 -0
- package/dist/layout/utils/spacing-calculator.d.ts +27 -0
- package/dist/layout/utils/spacing-calculator.d.ts.map +1 -0
- package/dist/layout/utils/spacing-calculator.js +50 -0
- package/dist/layout/utils/spacing-calculator.js.map +1 -0
- package/dist/memo.cjs +18 -0
- package/dist/memo.cjs.map +1 -0
- package/dist/memo.d.ts +29 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +18 -0
- package/dist/memo.js.map +1 -0
- package/dist/nineslice-contract.cjs +60 -0
- package/dist/nineslice-contract.cjs.map +1 -0
- package/dist/nineslice-contract.d.ts +107 -0
- package/dist/nineslice-contract.d.ts.map +1 -0
- package/dist/nineslice-contract.js +60 -0
- package/dist/nineslice-contract.js.map +1 -0
- package/dist/placeholder.cjs +12 -0
- package/dist/placeholder.cjs.map +1 -0
- package/dist/placeholder.d.ts +44 -0
- package/dist/placeholder.d.ts.map +1 -0
- package/dist/placeholder.js +12 -0
- package/dist/placeholder.js.map +1 -0
- package/dist/portal.cjs +89 -0
- package/dist/portal.cjs.map +1 -0
- package/dist/portal.d.ts +62 -0
- package/dist/portal.d.ts.map +1 -0
- package/dist/portal.js +89 -0
- package/dist/portal.js.map +1 -0
- package/dist/primitive-contracts.cjs +12 -0
- package/dist/primitive-contracts.cjs.map +1 -0
- package/dist/primitive-contracts.d.ts +186 -0
- package/dist/primitive-contracts.d.ts.map +1 -0
- package/dist/primitive-contracts.js +12 -0
- package/dist/primitive-contracts.js.map +1 -0
- package/dist/theme.cjs +332 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.ts +204 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +332 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +86 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vdom/create-runtime.cjs +79 -0
- package/dist/vdom/create-runtime.cjs.map +1 -0
- package/dist/vdom/create-runtime.d.ts +7 -0
- package/dist/vdom/create-runtime.d.ts.map +1 -0
- package/dist/vdom/create-runtime.js +79 -0
- package/dist/vdom/create-runtime.js.map +1 -0
- package/dist/vdom/index.cjs +8 -0
- package/dist/vdom/index.cjs.map +1 -0
- package/dist/vdom/index.d.ts +4 -0
- package/dist/vdom/index.d.ts.map +1 -0
- package/dist/vdom/index.js +8 -0
- package/dist/vdom/index.js.map +1 -0
- package/dist/vdom/mount.cjs +161 -0
- package/dist/vdom/mount.cjs.map +1 -0
- package/dist/vdom/mount.d.ts +6 -0
- package/dist/vdom/mount.d.ts.map +1 -0
- package/dist/vdom/mount.js +161 -0
- package/dist/vdom/mount.js.map +1 -0
- package/dist/vdom/patch.cjs +163 -0
- package/dist/vdom/patch.cjs.map +1 -0
- package/dist/vdom/patch.d.ts +3 -0
- package/dist/vdom/patch.d.ts.map +1 -0
- package/dist/vdom/patch.js +163 -0
- package/dist/vdom/patch.js.map +1 -0
- package/dist/vdom/registry.cjs +85 -0
- package/dist/vdom/registry.cjs.map +1 -0
- package/dist/vdom/registry.d.ts +28 -0
- package/dist/vdom/registry.d.ts.map +1 -0
- package/dist/vdom/registry.js +85 -0
- package/dist/vdom/registry.js.map +1 -0
- package/dist/vdom/runtime-helpers.cjs +23 -0
- package/dist/vdom/runtime-helpers.cjs.map +1 -0
- package/dist/vdom/runtime-helpers.d.ts +8 -0
- package/dist/vdom/runtime-helpers.d.ts.map +1 -0
- package/dist/vdom/runtime-helpers.js +23 -0
- package/dist/vdom/runtime-helpers.js.map +1 -0
- package/dist/vdom/surface.cjs +107 -0
- package/dist/vdom/surface.cjs.map +1 -0
- package/dist/vdom/surface.d.ts +9 -0
- package/dist/vdom/surface.d.ts.map +1 -0
- package/dist/vdom/surface.js +107 -0
- package/dist/vdom/surface.js.map +1 -0
- package/dist/vdom/types.d.ts +104 -0
- package/dist/vdom/types.d.ts.map +1 -0
- package/dist/vdom/utils.cjs +146 -0
- package/dist/vdom/utils.cjs.map +1 -0
- package/dist/vdom/utils.d.ts +24 -0
- package/dist/vdom/utils.d.ts.map +1 -0
- package/dist/vdom/utils.js +146 -0
- package/dist/vdom/utils.js.map +1 -0
- package/dist/vdom.d.ts +4 -0
- package/dist/vdom.d.ts.map +1 -0
- package/dist/vector-draw-context.d.ts +63 -0
- package/dist/vector-draw-context.d.ts.map +1 -0
- package/package.json +161 -0
- package/vdom/index.cjs +1 -0
- package/vdom/index.d.ts +1 -0
- package/vdom/index.js +1 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { numberToHex, getContrastRatio, ensureContrast } from "./color-utils.js";
|
|
2
|
+
const contrastBackgroundRoles = {
|
|
3
|
+
"background/default": {
|
|
4
|
+
description: "Main application background.",
|
|
5
|
+
color: { group: "background", shade: "DEFAULT" }
|
|
6
|
+
},
|
|
7
|
+
"surface/default": {
|
|
8
|
+
description: "Default surface for panels, cards, and controls.",
|
|
9
|
+
color: { group: "surface", shade: "DEFAULT" }
|
|
10
|
+
},
|
|
11
|
+
"surface/elevated": {
|
|
12
|
+
description: "Elevated surface used for stronger separation.",
|
|
13
|
+
color: { group: "surface", shade: "light" }
|
|
14
|
+
},
|
|
15
|
+
"brand/primary": {
|
|
16
|
+
description: "Primary brand background.",
|
|
17
|
+
color: { group: "primary", shade: "dark" }
|
|
18
|
+
},
|
|
19
|
+
"feedback/success": {
|
|
20
|
+
description: "Success-state background.",
|
|
21
|
+
color: { group: "success", shade: "dark" }
|
|
22
|
+
},
|
|
23
|
+
"feedback/warning": {
|
|
24
|
+
description: "Warning-state background.",
|
|
25
|
+
color: { group: "warning", shade: "dark" }
|
|
26
|
+
},
|
|
27
|
+
"feedback/error": {
|
|
28
|
+
description: "Error-state background.",
|
|
29
|
+
color: { group: "error", shade: "dark" }
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const contrastForegroundRoles = {
|
|
33
|
+
"text/default": {
|
|
34
|
+
description: "Default body text.",
|
|
35
|
+
kind: "text",
|
|
36
|
+
candidates: [
|
|
37
|
+
{ group: "text", shade: "DEFAULT" },
|
|
38
|
+
{ group: "text", shade: "dark" },
|
|
39
|
+
{ group: "text", shade: "darkest" },
|
|
40
|
+
{ group: "text", shade: "light" }
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"text/muted": {
|
|
44
|
+
description: "Secondary or supporting text.",
|
|
45
|
+
kind: "text",
|
|
46
|
+
candidates: [
|
|
47
|
+
{ group: "text", shade: "light" },
|
|
48
|
+
{ group: "text", shade: "medium" },
|
|
49
|
+
{ group: "text", shade: "DEFAULT" }
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"text/strong": {
|
|
53
|
+
description: "Emphasized text on neutral surfaces.",
|
|
54
|
+
kind: "text",
|
|
55
|
+
candidates: [
|
|
56
|
+
{ group: "text", shade: "darkest" },
|
|
57
|
+
{ group: "text", shade: "dark" },
|
|
58
|
+
{ group: "text", shade: "DEFAULT" }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
"text/on-brand": {
|
|
62
|
+
description: "Text intended for strong brand or colored backgrounds.",
|
|
63
|
+
kind: "text",
|
|
64
|
+
candidates: [
|
|
65
|
+
{ group: "text", shade: "lightest" },
|
|
66
|
+
{ group: "text", shade: "light" },
|
|
67
|
+
{ group: "text", shade: "DEFAULT" }
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
"text/on-danger": {
|
|
71
|
+
description: "Text intended for danger/error backgrounds.",
|
|
72
|
+
kind: "text",
|
|
73
|
+
candidates: [
|
|
74
|
+
{ group: "text", shade: "lightest" },
|
|
75
|
+
{ group: "text", shade: "light" },
|
|
76
|
+
{ group: "text", shade: "DEFAULT" }
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"icon/on-brand": {
|
|
80
|
+
description: "Icon tint intended for strong brand or colored backgrounds.",
|
|
81
|
+
kind: "icon",
|
|
82
|
+
candidates: [
|
|
83
|
+
{ group: "text", shade: "lightest" },
|
|
84
|
+
{ group: "text", shade: "light" },
|
|
85
|
+
{ group: "text", shade: "DEFAULT" }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"icon/on-danger": {
|
|
89
|
+
description: "Icon tint intended for danger/error backgrounds.",
|
|
90
|
+
kind: "icon",
|
|
91
|
+
candidates: [
|
|
92
|
+
{ group: "text", shade: "lightest" },
|
|
93
|
+
{ group: "text", shade: "light" },
|
|
94
|
+
{ group: "text", shade: "DEFAULT" }
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
const defaultContrastContracts = [
|
|
99
|
+
{
|
|
100
|
+
id: "body-on-background",
|
|
101
|
+
description: "Default body text on the main application background.",
|
|
102
|
+
foregroundRole: "text/default",
|
|
103
|
+
backgroundRole: "background/default",
|
|
104
|
+
minRatio: 4.5
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "body-on-surface",
|
|
108
|
+
description: "Default body text on standard surfaces and cards.",
|
|
109
|
+
foregroundRole: "text/default",
|
|
110
|
+
backgroundRole: "surface/default",
|
|
111
|
+
minRatio: 4.5
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "muted-on-surface",
|
|
115
|
+
description: "Muted supporting text on standard surfaces.",
|
|
116
|
+
foregroundRole: "text/muted",
|
|
117
|
+
backgroundRole: "surface/default",
|
|
118
|
+
minRatio: 4.5
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: "strong-on-surface",
|
|
122
|
+
description: "Strong emphasized text on elevated surfaces.",
|
|
123
|
+
foregroundRole: "text/strong",
|
|
124
|
+
backgroundRole: "surface/elevated",
|
|
125
|
+
minRatio: 4.5
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: "text-on-primary",
|
|
129
|
+
description: "Readable text on the primary brand background.",
|
|
130
|
+
foregroundRole: "text/on-brand",
|
|
131
|
+
backgroundRole: "brand/primary",
|
|
132
|
+
minRatio: 4.5
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: "text-on-error",
|
|
136
|
+
description: "Readable text on the error background.",
|
|
137
|
+
foregroundRole: "text/on-danger",
|
|
138
|
+
backgroundRole: "feedback/error",
|
|
139
|
+
minRatio: 4.5
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: "icon-on-primary",
|
|
143
|
+
description: "Readable icon tint on the primary brand background.",
|
|
144
|
+
foregroundRole: "icon/on-brand",
|
|
145
|
+
backgroundRole: "brand/primary",
|
|
146
|
+
minRatio: 3
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: "icon-on-error",
|
|
150
|
+
description: "Readable icon tint on the error background.",
|
|
151
|
+
foregroundRole: "icon/on-danger",
|
|
152
|
+
backgroundRole: "feedback/error",
|
|
153
|
+
minRatio: 3
|
|
154
|
+
}
|
|
155
|
+
];
|
|
156
|
+
function resolveContrastColorRef(colors, ref) {
|
|
157
|
+
return colors[ref.group][ref.shade].toNumber();
|
|
158
|
+
}
|
|
159
|
+
function resolveContrastBackgroundRole(colors, role) {
|
|
160
|
+
const definition = contrastBackgroundRoles[role];
|
|
161
|
+
const value = resolveContrastColorRef(colors, definition.color);
|
|
162
|
+
return {
|
|
163
|
+
role,
|
|
164
|
+
value,
|
|
165
|
+
hex: numberToHex(value)
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function resolveContrastForegroundRole(colors, role, background, minRatio) {
|
|
169
|
+
const definition = contrastForegroundRoles[role];
|
|
170
|
+
const resolvedCandidates = definition.candidates.map((candidate) => ({
|
|
171
|
+
candidate,
|
|
172
|
+
value: resolveContrastColorRef(colors, candidate)
|
|
173
|
+
}));
|
|
174
|
+
const exactMatch = resolvedCandidates.find(
|
|
175
|
+
({ value }) => getContrastRatio(value, background) >= minRatio
|
|
176
|
+
);
|
|
177
|
+
if (exactMatch) {
|
|
178
|
+
return {
|
|
179
|
+
role,
|
|
180
|
+
kind: definition.kind,
|
|
181
|
+
source: "token",
|
|
182
|
+
candidate: exactMatch.candidate,
|
|
183
|
+
value: exactMatch.value,
|
|
184
|
+
hex: numberToHex(exactMatch.value)
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const preferred = resolvedCandidates[0];
|
|
188
|
+
if (!preferred) {
|
|
189
|
+
throw new Error(`Contrast foreground role "${role}" has no candidate colors.`);
|
|
190
|
+
}
|
|
191
|
+
const adjustedValue = ensureContrast(preferred.value, background, minRatio);
|
|
192
|
+
return {
|
|
193
|
+
role,
|
|
194
|
+
kind: definition.kind,
|
|
195
|
+
source: "adjusted",
|
|
196
|
+
candidate: preferred.candidate,
|
|
197
|
+
value: adjustedValue,
|
|
198
|
+
hex: numberToHex(adjustedValue)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function resolveContrastContract(colors, contract) {
|
|
202
|
+
const background = resolveContrastBackgroundRole(colors, contract.backgroundRole);
|
|
203
|
+
const foreground = resolveContrastForegroundRole(
|
|
204
|
+
colors,
|
|
205
|
+
contract.foregroundRole,
|
|
206
|
+
background.value,
|
|
207
|
+
contract.minRatio
|
|
208
|
+
);
|
|
209
|
+
const ratio = getContrastRatio(foreground.value, background.value);
|
|
210
|
+
return {
|
|
211
|
+
contract,
|
|
212
|
+
foreground,
|
|
213
|
+
background,
|
|
214
|
+
ratio,
|
|
215
|
+
passes: ratio >= contract.minRatio
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function validateContrastContracts(colors, contracts = defaultContrastContracts) {
|
|
219
|
+
return contracts.map((contract) => resolveContrastContract(colors, contract));
|
|
220
|
+
}
|
|
221
|
+
function getFailingContrastContracts(colors, contracts = defaultContrastContracts) {
|
|
222
|
+
return validateContrastContracts(colors, contracts).filter((result) => !result.passes);
|
|
223
|
+
}
|
|
224
|
+
function getContrastContract(contractId) {
|
|
225
|
+
return defaultContrastContracts.find((contract) => contract.id === contractId);
|
|
226
|
+
}
|
|
227
|
+
function resolveContrastContractById(colors, contractId) {
|
|
228
|
+
const contract = getContrastContract(contractId);
|
|
229
|
+
if (!contract) throw new Error(`Contrast contract not found: ${contractId}`);
|
|
230
|
+
return resolveContrastContract(colors, contract);
|
|
231
|
+
}
|
|
232
|
+
function resolveContrastTextColor(colors, foregroundRole, background, minRatio = 4.5) {
|
|
233
|
+
return resolveContrastForegroundRole(colors, foregroundRole, background, minRatio).hex;
|
|
234
|
+
}
|
|
235
|
+
function resolveContrastTintColor(colors, foregroundRole, background, minRatio = 3) {
|
|
236
|
+
return resolveContrastForegroundRole(colors, foregroundRole, background, minRatio).value;
|
|
237
|
+
}
|
|
238
|
+
function formatResolvedContrastContract(resolved) {
|
|
239
|
+
const { contract, foreground, background, ratio } = resolved;
|
|
240
|
+
const status = resolved.passes ? "✓" : "✗";
|
|
241
|
+
return [
|
|
242
|
+
`${status} ${contract.id}`,
|
|
243
|
+
` ${contract.description}`,
|
|
244
|
+
` fg: ${foreground.hex} role=${foreground.role} kind=${foreground.kind} src=${foreground.source}`,
|
|
245
|
+
` bg: ${background.hex} role=${background.role}`,
|
|
246
|
+
` ratio: ${ratio.toFixed(2)}:1 (need ≥ ${contract.minRatio}:1)`
|
|
247
|
+
].join("\n");
|
|
248
|
+
}
|
|
249
|
+
export {
|
|
250
|
+
contrastBackgroundRoles,
|
|
251
|
+
contrastForegroundRoles,
|
|
252
|
+
defaultContrastContracts,
|
|
253
|
+
formatResolvedContrastContract,
|
|
254
|
+
getContrastContract,
|
|
255
|
+
getFailingContrastContracts,
|
|
256
|
+
resolveContrastBackgroundRole,
|
|
257
|
+
resolveContrastColorRef,
|
|
258
|
+
resolveContrastContract,
|
|
259
|
+
resolveContrastContractById,
|
|
260
|
+
resolveContrastForegroundRole,
|
|
261
|
+
resolveContrastTextColor,
|
|
262
|
+
resolveContrastTintColor,
|
|
263
|
+
validateContrastContracts
|
|
264
|
+
};
|
|
265
|
+
//# sourceMappingURL=contrast-contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrast-contracts.js","sources":["../../src/colors/contrast-contracts.ts"],"sourcesContent":["/**\n * Semantic contrast contracts for theme and preset authors.\n *\n * This file is intentionally a small first step:\n * - define a shared language for meaningful foreground/background pairings\n * - expose helpers that can resolve and validate those pairings\n * - keep room for a second step where component defaults and tests adopt them\n *\n * TODO(step-2): let theme-default builders consume these contracts directly.\n * TODO(step-2): move component-level contrast test heuristics onto this model.\n * TODO(step-3): add context-aware contracts for alpha/translucent surfaces.\n */\n\nimport type { ColorTokens, ShadeLevel } from './color-types'\nimport { ensureContrast, getContrastRatio, numberToHex } from './color-utils'\n\ntype TokenColorGroup =\n | 'background'\n | 'surface'\n | 'text'\n | 'border'\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'success'\n | 'warning'\n | 'error'\n | 'info'\n\nexport interface ContrastColorRef {\n group: TokenColorGroup\n shade: ShadeLevel | 'DEFAULT'\n}\n\nexport interface ContrastBackgroundRoleDefinition {\n description: string\n color: ContrastColorRef\n}\n\nexport interface ContrastForegroundRoleDefinition {\n description: string\n kind: 'text' | 'icon'\n candidates: readonly ContrastColorRef[]\n}\n\nexport const contrastBackgroundRoles = {\n 'background/default': {\n description: 'Main application background.',\n color: { group: 'background', shade: 'DEFAULT' },\n },\n 'surface/default': {\n description: 'Default surface for panels, cards, and controls.',\n color: { group: 'surface', shade: 'DEFAULT' },\n },\n 'surface/elevated': {\n description: 'Elevated surface used for stronger separation.',\n color: { group: 'surface', shade: 'light' },\n },\n 'brand/primary': {\n description: 'Primary brand background.',\n color: { group: 'primary', shade: 'dark' },\n },\n 'feedback/success': {\n description: 'Success-state background.',\n color: { group: 'success', shade: 'dark' },\n },\n 'feedback/warning': {\n description: 'Warning-state background.',\n color: { group: 'warning', shade: 'dark' },\n },\n 'feedback/error': {\n description: 'Error-state background.',\n color: { group: 'error', shade: 'dark' },\n },\n} as const satisfies Record<string, ContrastBackgroundRoleDefinition>\n\nexport type ContrastBackgroundRole = keyof typeof contrastBackgroundRoles\n\nexport const contrastForegroundRoles = {\n 'text/default': {\n description: 'Default body text.',\n kind: 'text',\n candidates: [\n { group: 'text', shade: 'DEFAULT' },\n { group: 'text', shade: 'dark' },\n { group: 'text', shade: 'darkest' },\n { group: 'text', shade: 'light' },\n ],\n },\n 'text/muted': {\n description: 'Secondary or supporting text.',\n kind: 'text',\n candidates: [\n { group: 'text', shade: 'light' },\n { group: 'text', shade: 'medium' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n 'text/strong': {\n description: 'Emphasized text on neutral surfaces.',\n kind: 'text',\n candidates: [\n { group: 'text', shade: 'darkest' },\n { group: 'text', shade: 'dark' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n 'text/on-brand': {\n description: 'Text intended for strong brand or colored backgrounds.',\n kind: 'text',\n candidates: [\n { group: 'text', shade: 'lightest' },\n { group: 'text', shade: 'light' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n 'text/on-danger': {\n description: 'Text intended for danger/error backgrounds.',\n kind: 'text',\n candidates: [\n { group: 'text', shade: 'lightest' },\n { group: 'text', shade: 'light' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n 'icon/on-brand': {\n description: 'Icon tint intended for strong brand or colored backgrounds.',\n kind: 'icon',\n candidates: [\n { group: 'text', shade: 'lightest' },\n { group: 'text', shade: 'light' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n 'icon/on-danger': {\n description: 'Icon tint intended for danger/error backgrounds.',\n kind: 'icon',\n candidates: [\n { group: 'text', shade: 'lightest' },\n { group: 'text', shade: 'light' },\n { group: 'text', shade: 'DEFAULT' },\n ],\n },\n} as const satisfies Record<string, ContrastForegroundRoleDefinition>\n\nexport type ContrastForegroundRole = keyof typeof contrastForegroundRoles\n\nexport interface ContrastContract {\n id: string\n description: string\n foregroundRole: ContrastForegroundRole\n backgroundRole: ContrastBackgroundRole\n minRatio: number\n}\n\nexport const defaultContrastContracts = [\n {\n id: 'body-on-background',\n description: 'Default body text on the main application background.',\n foregroundRole: 'text/default',\n backgroundRole: 'background/default',\n minRatio: 4.5,\n },\n {\n id: 'body-on-surface',\n description: 'Default body text on standard surfaces and cards.',\n foregroundRole: 'text/default',\n backgroundRole: 'surface/default',\n minRatio: 4.5,\n },\n {\n id: 'muted-on-surface',\n description: 'Muted supporting text on standard surfaces.',\n foregroundRole: 'text/muted',\n backgroundRole: 'surface/default',\n minRatio: 4.5,\n },\n {\n id: 'strong-on-surface',\n description: 'Strong emphasized text on elevated surfaces.',\n foregroundRole: 'text/strong',\n backgroundRole: 'surface/elevated',\n minRatio: 4.5,\n },\n {\n id: 'text-on-primary',\n description: 'Readable text on the primary brand background.',\n foregroundRole: 'text/on-brand',\n backgroundRole: 'brand/primary',\n minRatio: 4.5,\n },\n {\n id: 'text-on-error',\n description: 'Readable text on the error background.',\n foregroundRole: 'text/on-danger',\n backgroundRole: 'feedback/error',\n minRatio: 4.5,\n },\n {\n id: 'icon-on-primary',\n description: 'Readable icon tint on the primary brand background.',\n foregroundRole: 'icon/on-brand',\n backgroundRole: 'brand/primary',\n minRatio: 3,\n },\n {\n id: 'icon-on-error',\n description: 'Readable icon tint on the error background.',\n foregroundRole: 'icon/on-danger',\n backgroundRole: 'feedback/error',\n minRatio: 3,\n },\n] as const satisfies readonly ContrastContract[]\n\nexport interface ResolvedContrastColor {\n role: ContrastForegroundRole | ContrastBackgroundRole\n value: number\n hex: string\n}\n\nexport interface ResolvedContrastForeground extends ResolvedContrastColor {\n kind: 'text' | 'icon'\n source: 'token' | 'adjusted'\n candidate: ContrastColorRef\n}\n\nexport interface ResolvedContrastContract {\n contract: ContrastContract\n foreground: ResolvedContrastForeground\n background: ResolvedContrastColor\n ratio: number\n passes: boolean\n}\n\nexport function resolveContrastColorRef(colors: ColorTokens, ref: ContrastColorRef): number {\n return colors[ref.group][ref.shade].toNumber()\n}\n\nexport function resolveContrastBackgroundRole(\n colors: ColorTokens,\n role: ContrastBackgroundRole\n): ResolvedContrastColor {\n const definition = contrastBackgroundRoles[role]\n const value = resolveContrastColorRef(colors, definition.color)\n\n return {\n role,\n value,\n hex: numberToHex(value),\n }\n}\n\nexport function resolveContrastForegroundRole(\n colors: ColorTokens,\n role: ContrastForegroundRole,\n background: number,\n minRatio: number\n): ResolvedContrastForeground {\n const definition = contrastForegroundRoles[role]\n const resolvedCandidates = definition.candidates.map((candidate) => ({\n candidate,\n value: resolveContrastColorRef(colors, candidate),\n }))\n\n const exactMatch = resolvedCandidates.find(\n ({ value }) => getContrastRatio(value, background) >= minRatio\n )\n\n if (exactMatch) {\n return {\n role,\n kind: definition.kind,\n source: 'token',\n candidate: exactMatch.candidate,\n value: exactMatch.value,\n hex: numberToHex(exactMatch.value),\n }\n }\n\n const preferred = resolvedCandidates[0]\n if (!preferred) {\n throw new Error(`Contrast foreground role \"${role}\" has no candidate colors.`)\n }\n\n const adjustedValue = ensureContrast(preferred.value, background, minRatio)\n\n return {\n role,\n kind: definition.kind,\n source: 'adjusted',\n candidate: preferred.candidate,\n value: adjustedValue,\n hex: numberToHex(adjustedValue),\n }\n}\n\nexport function resolveContrastContract(\n colors: ColorTokens,\n contract: ContrastContract\n): ResolvedContrastContract {\n const background = resolveContrastBackgroundRole(colors, contract.backgroundRole)\n const foreground = resolveContrastForegroundRole(\n colors,\n contract.foregroundRole,\n background.value,\n contract.minRatio\n )\n const ratio = getContrastRatio(foreground.value, background.value)\n\n return {\n contract,\n foreground,\n background,\n ratio,\n passes: ratio >= contract.minRatio,\n }\n}\n\nexport function validateContrastContracts(\n colors: ColorTokens,\n contracts: readonly ContrastContract[] = defaultContrastContracts\n): ResolvedContrastContract[] {\n return contracts.map((contract) => resolveContrastContract(colors, contract))\n}\n\nexport function getFailingContrastContracts(\n colors: ColorTokens,\n contracts: readonly ContrastContract[] = defaultContrastContracts\n): ResolvedContrastContract[] {\n return validateContrastContracts(colors, contracts).filter((result) => !result.passes)\n}\n\nexport function getContrastContract(contractId: string): ContrastContract | undefined {\n return defaultContrastContracts.find((contract) => contract.id === contractId)\n}\n\n/**\n * Resolve a contract by id, throwing if the contract is not found.\n * Convenience wrapper around getContrastContract + resolveContrastContract.\n * @param colors - The color token set\n * @param contractId - The contract identifier (e.g. 'text-on-primary')\n * @returns Resolved contract with foreground, background, ratio, and pass/fail\n * @throws If no contract with the given id exists\n */\nexport function resolveContrastContractById(\n colors: ColorTokens,\n contractId: string\n): ResolvedContrastContract {\n const contract = getContrastContract(contractId)\n if (!contract) throw new Error(`Contrast contract not found: ${contractId}`)\n return resolveContrastContract(colors, contract)\n}\n\n/**\n * Convenience: resolve a foreground role against a numeric background and\n * return the resulting hex color string (for Text style `.color`).\n * @param colors - The color token set\n * @param foregroundRole - Semantic foreground role (e.g. 'text/on-brand')\n * @param background - Numeric background color to check contrast against\n * @param minRatio - Minimum contrast ratio (defaults to WCAG AA 4.5:1)\n * @returns Hex color string suitable for Text style `.color`\n */\nexport function resolveContrastTextColor(\n colors: ColorTokens,\n foregroundRole: ContrastForegroundRole,\n background: number,\n minRatio = 4.5\n): string {\n return resolveContrastForegroundRole(colors, foregroundRole, background, minRatio).hex\n}\n\n/**\n * Convenience: resolve a foreground role against a numeric background and\n * return the resulting numeric color (for Icon `.tint` or similar).\n * @param colors - The color token set\n * @param foregroundRole - Semantic foreground role (e.g. 'icon/on-brand')\n * @param background - Numeric background color to check contrast against\n * @param minRatio - Minimum contrast ratio (defaults to 3:1 for icons/UI graphics)\n * @returns Numeric color value\n */\nexport function resolveContrastTintColor(\n colors: ColorTokens,\n foregroundRole: ContrastForegroundRole,\n background: number,\n minRatio = 3\n): number {\n return resolveContrastForegroundRole(colors, foregroundRole, background, minRatio).value\n}\n\n/**\n * Format a resolved contract as a human-readable multi-line string.\n * Useful for debugging, CLI output, and authoring tools.\n * @param resolved - A resolved contrast contract\n * @returns Formatted description string\n */\nexport function formatResolvedContrastContract(resolved: ResolvedContrastContract): string {\n const { contract, foreground, background, ratio } = resolved\n const status = resolved.passes ? '✓' : '✗'\n return [\n `${status} ${contract.id}`,\n ` ${contract.description}`,\n ` fg: ${foreground.hex} role=${foreground.role} kind=${foreground.kind} src=${foreground.source}`,\n ` bg: ${background.hex} role=${background.role}`,\n ` ratio: ${ratio.toFixed(2)}:1 (need ≥ ${contract.minRatio}:1)`,\n ].join('\\n')\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const colorTypes = require("./color-types.cjs");
|
|
4
|
+
const colorUtils = require("./color-utils.cjs");
|
|
5
|
+
const contrastContracts = require("./contrast-contracts.cjs");
|
|
6
|
+
const colorPresets = require("./color-presets.cjs");
|
|
7
|
+
const colorThemeHelpers = require("./color-theme-helpers.cjs");
|
|
8
|
+
exports.HexColor = colorTypes.HexColor;
|
|
9
|
+
exports.alpha = colorUtils.alpha;
|
|
10
|
+
exports.createTextStyle = colorUtils.createTextStyle;
|
|
11
|
+
exports.darken = colorUtils.darken;
|
|
12
|
+
exports.darkenHex = colorUtils.darkenHex;
|
|
13
|
+
exports.ensureContrast = colorUtils.ensureContrast;
|
|
14
|
+
exports.getContrastRatio = colorUtils.getContrastRatio;
|
|
15
|
+
exports.hexToNumber = colorUtils.hexToNumber;
|
|
16
|
+
exports.hslToNumber = colorUtils.hslToNumber;
|
|
17
|
+
exports.hslToRgb = colorUtils.hslToRgb;
|
|
18
|
+
exports.lighten = colorUtils.lighten;
|
|
19
|
+
exports.lightenHex = colorUtils.lightenHex;
|
|
20
|
+
exports.normalizeColorNumber = colorUtils.normalizeColorNumber;
|
|
21
|
+
exports.normalizeTextColor = colorUtils.normalizeTextColor;
|
|
22
|
+
exports.numberToHex = colorUtils.numberToHex;
|
|
23
|
+
exports.numberToHsl = colorUtils.numberToHsl;
|
|
24
|
+
exports.numberToRgb = colorUtils.numberToRgb;
|
|
25
|
+
exports.rgbToHsl = colorUtils.rgbToHsl;
|
|
26
|
+
exports.rgbToNumber = colorUtils.rgbToNumber;
|
|
27
|
+
exports.contrastBackgroundRoles = contrastContracts.contrastBackgroundRoles;
|
|
28
|
+
exports.contrastForegroundRoles = contrastContracts.contrastForegroundRoles;
|
|
29
|
+
exports.defaultContrastContracts = contrastContracts.defaultContrastContracts;
|
|
30
|
+
exports.formatResolvedContrastContract = contrastContracts.formatResolvedContrastContract;
|
|
31
|
+
exports.getContrastContract = contrastContracts.getContrastContract;
|
|
32
|
+
exports.getFailingContrastContracts = contrastContracts.getFailingContrastContracts;
|
|
33
|
+
exports.resolveContrastBackgroundRole = contrastContracts.resolveContrastBackgroundRole;
|
|
34
|
+
exports.resolveContrastColorRef = contrastContracts.resolveContrastColorRef;
|
|
35
|
+
exports.resolveContrastContract = contrastContracts.resolveContrastContract;
|
|
36
|
+
exports.resolveContrastContractById = contrastContracts.resolveContrastContractById;
|
|
37
|
+
exports.resolveContrastForegroundRole = contrastContracts.resolveContrastForegroundRole;
|
|
38
|
+
exports.resolveContrastTextColor = contrastContracts.resolveContrastTextColor;
|
|
39
|
+
exports.resolveContrastTintColor = contrastContracts.resolveContrastTintColor;
|
|
40
|
+
exports.validateContrastContracts = contrastContracts.validateContrastContracts;
|
|
41
|
+
exports.applyDarkMode = colorPresets.applyDarkMode;
|
|
42
|
+
exports.applyLightMode = colorPresets.applyLightMode;
|
|
43
|
+
exports.forestGreenPreset = colorPresets.forestGreenPreset;
|
|
44
|
+
exports.generateColorScale = colorPresets.generateColorScale;
|
|
45
|
+
exports.getPreset = colorPresets.getPreset;
|
|
46
|
+
exports.getPresetWithMode = colorPresets.getPresetWithMode;
|
|
47
|
+
exports.midnightPreset = colorPresets.midnightPreset;
|
|
48
|
+
exports.oceanBluePreset = colorPresets.oceanBluePreset;
|
|
49
|
+
exports.presets = colorPresets.presets;
|
|
50
|
+
exports.colorsToTheme = colorThemeHelpers.colorsToTheme;
|
|
51
|
+
exports.getBackgroundColor = colorThemeHelpers.getBackgroundColor;
|
|
52
|
+
exports.getBorderColor = colorThemeHelpers.getBorderColor;
|
|
53
|
+
exports.getSurfaceColor = colorThemeHelpers.getSurfaceColor;
|
|
54
|
+
exports.getTextColor = colorThemeHelpers.getTextColor;
|
|
55
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color system — renderer-neutral color math and presets.
|
|
3
|
+
*
|
|
4
|
+
* @migration(audit:scene-portal-mount) Phase 3C — extracted from packages/ui/src/colors.
|
|
5
|
+
* Pure color types, utilities, and presets. Theme-dependent hooks stay in Phaser package.
|
|
6
|
+
*/
|
|
7
|
+
export { HexColor } from './color-types';
|
|
8
|
+
export type { ColorMode, ColorShade, ColorTokens, RGBColor, ShadeLevel } from './color-types';
|
|
9
|
+
export { hexToNumber, hslToNumber, hslToRgb, normalizeColorNumber, normalizeTextColor, numberToHex, numberToHsl, numberToRgb, rgbToHsl, rgbToNumber, } from './color-utils';
|
|
10
|
+
export { alpha, darken, darkenHex, lighten, lightenHex } from './color-utils';
|
|
11
|
+
export type { HSLColor } from './color-utils';
|
|
12
|
+
export { createTextStyle, ensureContrast, getContrastRatio } from './color-utils';
|
|
13
|
+
export { contrastBackgroundRoles, contrastForegroundRoles, defaultContrastContracts, formatResolvedContrastContract, getContrastContract, getFailingContrastContracts, resolveContrastBackgroundRole, resolveContrastColorRef, resolveContrastContract, resolveContrastContractById, resolveContrastForegroundRole, resolveContrastTextColor, resolveContrastTintColor, validateContrastContracts, type ContrastBackgroundRole, type ContrastBackgroundRoleDefinition, type ContrastColorRef, type ContrastContract, type ContrastForegroundRole, type ContrastForegroundRoleDefinition, type ResolvedContrastColor, type ResolvedContrastContract, type ResolvedContrastForeground, } from './contrast-contracts';
|
|
14
|
+
export { applyDarkMode, applyLightMode, forestGreenPreset, generateColorScale, getPreset, getPresetWithMode, midnightPreset, oceanBluePreset, presets, type ColorPreset, type PresetName, } from './color-presets';
|
|
15
|
+
export { colorsToTheme, getBackgroundColor, getBorderColor, getSurfaceColor, getTextColor, } from './color-theme-helpers';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/colors/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAG7F,OAAO,EACL,WAAW,EACX,WAAW,EACX,QAAQ,EACR,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,WAAW,EACX,WAAW,EACX,QAAQ,EACR,WAAW,GACZ,MAAM,eAAe,CAAA;AAGtB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC7E,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAG7C,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAGjF,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,2BAA2B,EAC3B,6BAA6B,EAC7B,uBAAuB,EACvB,uBAAuB,EACvB,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,gCAAgC,EACrC,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,gCAAgC,EACrC,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,GAChC,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,OAAO,EACP,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAA;AAGxB,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,YAAY,GACb,MAAM,uBAAuB,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HexColor } from "./color-types.js";
|
|
2
|
+
import { alpha, createTextStyle, darken, darkenHex, ensureContrast, getContrastRatio, hexToNumber, hslToNumber, hslToRgb, lighten, lightenHex, normalizeColorNumber, normalizeTextColor, numberToHex, numberToHsl, numberToRgb, rgbToHsl, rgbToNumber } from "./color-utils.js";
|
|
3
|
+
import { contrastBackgroundRoles, contrastForegroundRoles, defaultContrastContracts, formatResolvedContrastContract, getContrastContract, getFailingContrastContracts, resolveContrastBackgroundRole, resolveContrastColorRef, resolveContrastContract, resolveContrastContractById, resolveContrastForegroundRole, resolveContrastTextColor, resolveContrastTintColor, validateContrastContracts } from "./contrast-contracts.js";
|
|
4
|
+
import { applyDarkMode, applyLightMode, forestGreenPreset, generateColorScale, getPreset, getPresetWithMode, midnightPreset, oceanBluePreset, presets } from "./color-presets.js";
|
|
5
|
+
import { colorsToTheme, getBackgroundColor, getBorderColor, getSurfaceColor, getTextColor } from "./color-theme-helpers.js";
|
|
6
|
+
export {
|
|
7
|
+
HexColor,
|
|
8
|
+
alpha,
|
|
9
|
+
applyDarkMode,
|
|
10
|
+
applyLightMode,
|
|
11
|
+
colorsToTheme,
|
|
12
|
+
contrastBackgroundRoles,
|
|
13
|
+
contrastForegroundRoles,
|
|
14
|
+
createTextStyle,
|
|
15
|
+
darken,
|
|
16
|
+
darkenHex,
|
|
17
|
+
defaultContrastContracts,
|
|
18
|
+
ensureContrast,
|
|
19
|
+
forestGreenPreset,
|
|
20
|
+
formatResolvedContrastContract,
|
|
21
|
+
generateColorScale,
|
|
22
|
+
getBackgroundColor,
|
|
23
|
+
getBorderColor,
|
|
24
|
+
getContrastContract,
|
|
25
|
+
getContrastRatio,
|
|
26
|
+
getFailingContrastContracts,
|
|
27
|
+
getPreset,
|
|
28
|
+
getPresetWithMode,
|
|
29
|
+
getSurfaceColor,
|
|
30
|
+
getTextColor,
|
|
31
|
+
hexToNumber,
|
|
32
|
+
hslToNumber,
|
|
33
|
+
hslToRgb,
|
|
34
|
+
lighten,
|
|
35
|
+
lightenHex,
|
|
36
|
+
midnightPreset,
|
|
37
|
+
normalizeColorNumber,
|
|
38
|
+
normalizeTextColor,
|
|
39
|
+
numberToHex,
|
|
40
|
+
numberToHsl,
|
|
41
|
+
numberToRgb,
|
|
42
|
+
oceanBluePreset,
|
|
43
|
+
presets,
|
|
44
|
+
resolveContrastBackgroundRole,
|
|
45
|
+
resolveContrastColorRef,
|
|
46
|
+
resolveContrastContract,
|
|
47
|
+
resolveContrastContractById,
|
|
48
|
+
resolveContrastForegroundRole,
|
|
49
|
+
resolveContrastTextColor,
|
|
50
|
+
resolveContrastTintColor,
|
|
51
|
+
rgbToHsl,
|
|
52
|
+
rgbToNumber,
|
|
53
|
+
validateContrastContracts
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
function clampToViewport(x, y, boxWidth, boxHeight, viewport, padding = 8) {
|
|
4
|
+
return {
|
|
5
|
+
x: Math.min(Math.max(padding, x), Math.max(padding, viewport.width - boxWidth - padding)),
|
|
6
|
+
y: Math.min(Math.max(padding, y), Math.max(padding, viewport.height - boxHeight - padding))
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function getOverlayPosition(placement, anchor, contentWidth, contentHeight, offset = 4) {
|
|
10
|
+
const cx = anchor.x + anchor.width / 2;
|
|
11
|
+
const cy = anchor.y + anchor.height / 2;
|
|
12
|
+
switch (placement) {
|
|
13
|
+
case "top":
|
|
14
|
+
return { x: cx - contentWidth / 2, y: anchor.y - contentHeight - offset };
|
|
15
|
+
case "bottom":
|
|
16
|
+
return { x: cx - contentWidth / 2, y: anchor.y + anchor.height + offset };
|
|
17
|
+
case "left":
|
|
18
|
+
return { x: anchor.x - contentWidth - offset, y: cy - contentHeight / 2 };
|
|
19
|
+
case "right":
|
|
20
|
+
return { x: anchor.x + anchor.width + offset, y: cy - contentHeight / 2 };
|
|
21
|
+
case "top-start":
|
|
22
|
+
return { x: anchor.x, y: anchor.y - contentHeight - offset };
|
|
23
|
+
case "top-end":
|
|
24
|
+
return { x: anchor.x + anchor.width - contentWidth, y: anchor.y - contentHeight - offset };
|
|
25
|
+
case "bottom-start":
|
|
26
|
+
return { x: anchor.x, y: anchor.y + anchor.height + offset };
|
|
27
|
+
case "bottom-end":
|
|
28
|
+
return { x: anchor.x + anchor.width - contentWidth, y: anchor.y + anchor.height + offset };
|
|
29
|
+
case "left-start":
|
|
30
|
+
return { x: anchor.x - contentWidth - offset, y: anchor.y };
|
|
31
|
+
case "left-end":
|
|
32
|
+
return { x: anchor.x - contentWidth - offset, y: anchor.y + anchor.height - contentHeight };
|
|
33
|
+
case "right-start":
|
|
34
|
+
return { x: anchor.x + anchor.width + offset, y: anchor.y };
|
|
35
|
+
case "right-end":
|
|
36
|
+
return { x: anchor.x + anchor.width + offset, y: anchor.y + anchor.height - contentHeight };
|
|
37
|
+
default:
|
|
38
|
+
return { x: cx - contentWidth / 2, y: anchor.y + anchor.height + offset };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function normalizeEdgeInsets(value) {
|
|
42
|
+
if (value === void 0) return {};
|
|
43
|
+
if (typeof value === "number") {
|
|
44
|
+
return { top: value, right: value, bottom: value, left: value };
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function normalizeCornerRadius(value) {
|
|
49
|
+
if (value === void 0) return 0;
|
|
50
|
+
if (typeof value === "number") return value;
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function normalizeGap(value) {
|
|
54
|
+
if (value === void 0) return { horizontal: 0, vertical: 0 };
|
|
55
|
+
if (typeof value === "number") return { horizontal: value, vertical: value };
|
|
56
|
+
return {
|
|
57
|
+
horizontal: value.horizontal ?? 0,
|
|
58
|
+
vertical: value.vertical ?? 0
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
exports.clampToViewport = clampToViewport;
|
|
62
|
+
exports.getOverlayPosition = getOverlayPosition;
|
|
63
|
+
exports.normalizeCornerRadius = normalizeCornerRadius;
|
|
64
|
+
exports.normalizeEdgeInsets = normalizeEdgeInsets;
|
|
65
|
+
exports.normalizeGap = normalizeGap;
|
|
66
|
+
//# sourceMappingURL=core-props.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-props.cjs","sources":["../src/core-props.ts"],"sourcesContent":["/**\n * Core prop type definitions — renderer-neutral component properties.\n * These prop groups can be composed to build component-specific props.\n *\n * @migration(audit:scene-portal-mount) Phase 3A — split from packages/ui/src/core-props.ts.\n * Portable types live here in @number10/jsx-core. Phaser-specific props\n * (PhaserProps, TextSpecificProps, GestureProps) remain in the Phaser package.\n */\n\nimport type { AnimatedSignal } from './animation/animated-signal'\n\n// ---------------------------------------------------------------------------\n// Animatable value helper\n// ---------------------------------------------------------------------------\n\n/**\n * Utility type that allows a value to be either a direct value or an\n * {@link AnimatedSignal}. Enables direct binding of `useSpring` / `useTween`\n * signals to JSX props without needing `useForceRedraw` + `.value`.\n *\n * @example\n * ```tsx\n * const [x, setX] = useSpring(0)\n * <View x={x} /> // ✅ x is Animatable<number> → accepts AnimatedSignal\n * ```\n */\nexport type Animatable<T> = T | AnimatedSignal\n\n// ---------------------------------------------------------------------------\n// Size value types\n// ---------------------------------------------------------------------------\n\n/**\n * Valid CSS-like size values with type safety\n * - Fixed pixels: number or \"20px\"\n * - Percentage: \"50%\", \"100%\"\n * - Viewport units: \"100vw\", \"50vh\"\n * - Keywords: \"auto\", \"fill\"\n * - Calc expressions: \"calc(100% - 20px)\"\n */\nexport type SizeValue =\n | number\n | 'auto'\n | 'fill'\n | `${number}%`\n | `${number}px`\n | `${number}vw`\n | `${number}vh`\n | `calc(${string})`\n\n/**\n * Flex basis size values (subset of SizeValue, no \"fill\" keyword)\n */\nexport type FlexBasisValue =\n | number\n | 'auto'\n | `${number}%`\n | `${number}px`\n | `${number}vw`\n | `${number}vh`\n | `calc(${string})`\n\n/**\n * Display mode for visibility control\n * - 'visible': Rendered and takes up layout space (default)\n * - 'invisible': Not rendered but takes up layout space\n * - 'none': Not rendered and does not take up layout space\n */\nexport type Display = 'visible' | 'invisible' | 'none'\n\n// ---------------------------------------------------------------------------\n// Viewport helpers (portable, for overlay positioning)\n// ---------------------------------------------------------------------------\n\n/**\n * Viewport dimensions used for overlay clamping and positioning.\n */\nexport interface ViewportSize {\n width: number\n height: number\n}\n\n/**\n * Clamp a position so that a box of the given size stays within the viewport.\n * @param x - Desired x position (left edge of the box)\n * @param y - Desired y position (top edge of the box)\n * @param boxWidth - Width of the box to clamp\n * @param boxHeight - Height of the box to clamp\n * @param viewport - Viewport dimensions\n * @param padding - Minimum padding from viewport edges (default 8)\n * @returns Clamped { x, y } position\n */\nexport function clampToViewport(\n x: number,\n y: number,\n boxWidth: number,\n boxHeight: number,\n viewport: ViewportSize,\n padding = 8\n): { x: number; y: number } {\n return {\n x: Math.min(Math.max(padding, x), Math.max(padding, viewport.width - boxWidth - padding)),\n y: Math.min(Math.max(padding, y), Math.max(padding, viewport.height - boxHeight - padding)),\n }\n}\n\n/**\n * Calculate the preferred placement for an overlay relative to an anchor rect.\n * Returns the anchor-relative position before viewport clamping.\n * @param placement - Preferred placement direction\n * @param anchor - Anchor rect in viewport coordinates\n * @param contentWidth - Width of the overlay content\n * @param contentHeight - Height of the overlay content\n * @param offset - Gap between anchor and overlay (default 4)\n * @returns Position relative to the anchor\n */\nexport function getOverlayPosition(\n placement:\n | 'top'\n | 'bottom'\n | 'left'\n | 'right'\n | 'top-start'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-end'\n | 'left-start'\n | 'left-end'\n | 'right-start'\n | 'right-end',\n anchor: { x: number; y: number; width: number; height: number },\n contentWidth: number,\n contentHeight: number,\n offset = 4\n): { x: number; y: number } {\n const cx = anchor.x + anchor.width / 2\n const cy = anchor.y + anchor.height / 2\n\n switch (placement) {\n case 'top':\n return { x: cx - contentWidth / 2, y: anchor.y - contentHeight - offset }\n case 'bottom':\n return { x: cx - contentWidth / 2, y: anchor.y + anchor.height + offset }\n case 'left':\n return { x: anchor.x - contentWidth - offset, y: cy - contentHeight / 2 }\n case 'right':\n return { x: anchor.x + anchor.width + offset, y: cy - contentHeight / 2 }\n case 'top-start':\n return { x: anchor.x, y: anchor.y - contentHeight - offset }\n case 'top-end':\n return { x: anchor.x + anchor.width - contentWidth, y: anchor.y - contentHeight - offset }\n case 'bottom-start':\n return { x: anchor.x, y: anchor.y + anchor.height + offset }\n case 'bottom-end':\n return { x: anchor.x + anchor.width - contentWidth, y: anchor.y + anchor.height + offset }\n case 'left-start':\n return { x: anchor.x - contentWidth - offset, y: anchor.y }\n case 'left-end':\n return { x: anchor.x - contentWidth - offset, y: anchor.y + anchor.height - contentHeight }\n case 'right-start':\n return { x: anchor.x + anchor.width + offset, y: anchor.y }\n case 'right-end':\n return { x: anchor.x + anchor.width + offset, y: anchor.y + anchor.height - contentHeight }\n default:\n return { x: cx - contentWidth / 2, y: anchor.y + anchor.height + offset }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Geometric properties\n// ---------------------------------------------------------------------------\n\n/**\n * Transform properties — geometric transformations (position, rotation, scale)\n * and visual opacity.\n */\nexport interface TransformProps {\n x?: Animatable<number>\n y?: Animatable<number>\n rotation?: Animatable<number>\n scale?: Animatable<number>\n scaleX?: Animatable<number>\n scaleY?: Animatable<number>\n /** Alpha transparency (0 = fully transparent, 1 = fully opaque) */\n alpha?: Animatable<number>\n /**\n * Z-order / render depth. Higher values render on top.\n * Supported by both Phaser (native depth property) and Pixi (child index).\n */\n depth?: number\n}\n\n// ---------------------------------------------------------------------------\n// Spacing types\n// ---------------------------------------------------------------------------\n\n/** Edge insets for margins and padding */\nexport interface EdgeInsets {\n top?: number\n right?: number\n bottom?: number\n left?: number\n}\n\n/** Gap insets for horizontal and vertical gaps */\nexport interface GapInsets {\n horizontal?: number\n vertical?: number\n}\n\n/** Corner radius specification */\nexport interface CornerRadiusInsets {\n tl?: number\n tr?: number\n bl?: number\n br?: number\n}\n\n// ---------------------------------------------------------------------------\n// Normalization helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize edge insets — converts number to all-sides object\n */\nexport function normalizeEdgeInsets(value: number | EdgeInsets | undefined): EdgeInsets {\n if (value === undefined) return {}\n if (typeof value === 'number') {\n return { top: value, right: value, bottom: value, left: value }\n }\n return value\n}\n\n/**\n * Normalize corner radius — converts number to all-corners object\n */\nexport function normalizeCornerRadius(\n value: number | CornerRadiusInsets | undefined\n): number | CornerRadiusInsets {\n if (value === undefined) return 0\n if (typeof value === 'number') return value\n return value\n}\n\n/**\n * Normalize gap values — converts number to GapInsets object\n */\nexport function normalizeGap(value: number | GapInsets | undefined): {\n horizontal: number\n vertical: number\n} {\n if (value === undefined) return { horizontal: 0, vertical: 0 }\n if (typeof value === 'number') return { horizontal: value, vertical: value }\n return {\n horizontal: value.horizontal ?? 0,\n vertical: value.vertical ?? 0,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Layout properties\n// ---------------------------------------------------------------------------\n\n/**\n * Layout properties — sizing, spacing, and layout participation.\n * Renderer-neutral. Every renderer maps these to its native layout system.\n */\nexport interface LayoutProps {\n /** Visibility and layout participation */\n visible?: boolean | Display\n\n /** If true, object is rendered but excluded from layout calculations */\n headless?: boolean\n\n /** Width: number (px), \"50%\", \"100vw\", \"auto\", \"fill\", \"calc(...)\" */\n width?: SizeValue | undefined\n\n /** Height: number (px), \"50%\", \"100vh\", \"auto\", \"fill\", \"calc(...)\" */\n height?: SizeValue | undefined\n\n /** Minimum width constraint */\n minWidth?: SizeValue | undefined\n\n /** Minimum height constraint */\n minHeight?: SizeValue | undefined\n\n /** Maximum width constraint */\n maxWidth?: SizeValue | undefined\n\n /** Maximum height constraint */\n maxHeight?: SizeValue | undefined\n\n /** Margin outside the container */\n margin?: number | EdgeInsets | undefined\n\n /** Padding inside the container */\n padding?: number | EdgeInsets | undefined\n\n /** Layout direction: 'column' (default), 'row', 'stack' */\n direction?: 'row' | 'column' | 'stack'\n\n /** Gap between children */\n gap?: number | GapInsets | undefined\n\n /** Main axis alignment */\n justifyContent?: 'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'space-evenly'\n\n /** Cross axis alignment */\n alignItems?: 'start' | 'center' | 'end' | 'stretch'\n\n /** Flex grow factor */\n flex?: number\n\n /** Flex shrink factor */\n flexShrink?: number\n\n /** Flex basis — initial size before flex distribution */\n flexBasis?: FlexBasisValue | undefined\n\n /** Overflow handling: 'visible' (default) or 'hidden' (clipped) */\n overflow?: 'visible' | 'hidden'\n\n /** Wrapping behavior for flex layouts */\n flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse'\n\n /** Alignment of wrapped lines */\n alignContent?: 'start' | 'center' | 'end' | 'space-between' | 'space-around' | 'stretch'\n}\n\n// ---------------------------------------------------------------------------\n// Advanced border types (BorderPropsV2)\n// ---------------------------------------------------------------------------\n\n/**\n * Border line style for advanced border rendering.\n * - `'solid'`: Continuous line (default)\n * - `'dashed'`: Segmented line\n * - `'dotted'`: Rounded dotted line\n */\nexport type BorderLineStyle = 'solid' | 'dashed' | 'dotted'\n\n/**\n * Per-side inset values for border widths.\n * Each side can have a different thickness.\n */\nexport type BorderSideInsets<T> = {\n top?: T\n right?: T\n bottom?: T\n left?: T\n}\n\n/**\n * Advanced border configuration — extended border styling beyond\n * the legacy `borderWidth`/`borderColor`/`borderAlpha` props.\n *\n * When set on `BackgroundProps.border`, this object takes precedence\n * over the legacy border props.\n */\nexport interface BorderPropsV2 {\n /** Border color (number, e.g. 0xff0000 for red) */\n color?: number\n /**\n * Border opacity.\n * Accepts either a plain value or an {@link AnimatedSignal}.\n */\n alpha?: Animatable<number>\n /**\n * Border width in pixels.\n * - `number`: uniform width on all sides (supports `cornerRadius`)\n * - `BorderSideInsets<number>`: per-side widths (supports `cornerRadius`)\n */\n width?: number | BorderSideInsets<number>\n /** Line style: `'solid'` (default), `'dashed'`, or `'dotted'` */\n style?: BorderLineStyle\n /**\n * Stroke pattern configuration.\n *\n * For `style: 'dashed'`, values are interpreted as alternating dash/gap\n * lengths, e.g. `[5, 3]`.\n *\n * For `style: 'dotted'`, `dash[0]` is the gap and `dash[1]` optionally\n * overrides the dot diameter.\n */\n dash?: number[]\n /** Offset where the dash pattern starts */\n dashOffset?: number\n /** Line cap style: `'butt'`, `'round'`, `'square'`. */\n cap?: 'butt' | 'round' | 'square'\n /** Line join style: `'miter'`, `'round'`, `'bevel'`. */\n join?: 'miter' | 'round' | 'bevel'\n /**\n * Border alignment relative to the edge: `'center'`, `'inside'`, `'outside'`.\n * - `center`: centered on the edge\n * - `inside`: fully inside the box\n * - `outside`: fully outside the box\n */\n align?: 'center' | 'inside' | 'outside'\n}\n\n// ---------------------------------------------------------------------------\n// Background properties\n// ---------------------------------------------------------------------------\n\n/**\n * Background styling properties — renderer-neutral.\n * Each renderer maps colors and corner radii to its native drawing API.\n */\nexport interface BackgroundProps {\n backgroundColor?: number | undefined\n /**\n * Background fill opacity.\n * Accepts either a plain value or an {@link AnimatedSignal}.\n */\n backgroundAlpha?: Animatable<number> | undefined\n cornerRadius?: number | CornerRadiusInsets | undefined\n borderWidth?: number | undefined\n borderColor?: number | undefined\n /**\n * Border stroke opacity.\n * Accepts either a plain value or an {@link AnimatedSignal}.\n */\n borderAlpha?: Animatable<number> | undefined\n /**\n * Advanced border configuration (BorderPropsV2).\n * When set, takes precedence over legacy `borderWidth`/`borderColor`/`borderAlpha`.\n */\n border?: BorderPropsV2 | undefined\n}\n\n// ---------------------------------------------------------------------------\n// Gesture properties — renderer-neutral touch / mouse / pointer contracts\n// ---------------------------------------------------------------------------\n\n/**\n * Touch move gesture state.\n */\nexport type TouchMoveState = 'start' | 'move' | 'end'\n\n/**\n * Data passed to gesture event handlers.\n * Renderer-agnostic — the pointer field is opaque.\n * Each renderer fills it with its own pointer type.\n */\nexport interface GestureEventData<TPointer = unknown> {\n /** Renderer-specific pointer object */\n pointer: TPointer\n /** Local X coordinate relative to container origin (0,0) */\n localX: number\n /** Local Y coordinate relative to container origin (0,0) */\n localY: number\n /** Delta X since last move event (only for onTouchMove) */\n dx?: number\n /** Delta Y since last move event (only for onTouchMove) */\n dy?: number\n /** Width of the container's hit area */\n width: number\n /** Height of the container's hit area */\n height: number\n /** Whether pointer is currently inside the container hit area */\n isInside?: boolean\n /** Current state of touch move gesture (only for onTouchMove) */\n state?: TouchMoveState\n\n /** Stop event propagation to parent containers (DOM-style bubbling) */\n stopPropagation(): void\n\n /** Check if propagation has been stopped */\n isPropagationStopped(): boolean\n}\n\n/**\n * Data passed to wheel event handlers.\n * Renderer-agnostic — pointer/originalEvent are opaque.\n */\nexport interface WheelEventData<TPointer = unknown, TOriginalEvent = unknown> {\n /** Renderer-specific pointer object, if available */\n pointer: TPointer\n /** Local X coordinate relative to container origin (0,0) */\n localX: number\n /** Local Y coordinate relative to container origin (0,0) */\n localY: number\n /** Wheel scroll delta X (horizontal scrolling) */\n deltaX: number\n /** Wheel scroll delta Y (vertical scrolling) */\n deltaY: number\n /** Wheel scroll delta Z */\n deltaZ: number\n /** Delta mode: 0 = pixels, 1 = lines, 2 = pages */\n deltaMode: number\n /** Width of the container's hit area */\n width: number\n /** Height of the container's hit area */\n height: number\n /** Original platform wheel event */\n originalEvent: TOriginalEvent\n\n /** Stop event propagation to parent containers (DOM-style bubbling) */\n stopPropagation(): void\n\n /** Check if propagation has been stopped */\n isPropagationStopped(): boolean\n\n /** Prevent default browser behavior */\n preventDefault(): void\n}\n\n/**\n * Tooltip position relative to the target element.\n */\nexport type TooltipPosition = 'top' | 'bottom' | 'left' | 'right'\n\n/**\n * Renderer-neutral tooltip animation configuration.\n * Renderers may ignore fields they cannot represent.\n */\nexport interface TooltipAnimation {\n fadeIn?: number\n fadeOut?: number\n move?: { dx?: number; dy?: number }\n pulse?: boolean\n pulseScale?: [number, number]\n}\n\n/**\n * Tooltip configuration returned by `onTooltip`.\n * Text-only on purpose so each renderer can draw it natively.\n */\nexport interface TooltipConfig {\n content: string\n position?: TooltipPosition\n showDelay?: number\n hideDelay?: number\n offset?: number\n disabled?: boolean\n autoDismiss?: number\n animation?: TooltipAnimation\n}\n\n/**\n * Tooltip callback function.\n * Return `null` / `undefined` to disable the tooltip for the current hover.\n */\nexport type TooltipCallback = () => TooltipConfig | string | null | undefined\n\n/**\n * High-level gesture interaction props.\n * Renderer-neutral — each renderer provides its own GestureManager.\n */\nexport interface GestureProps<TPointer = unknown> {\n /** Enable gesture system for this container */\n enableGestures?: boolean\n\n /** Called on pointer down + up on the same target (click/tap) */\n onTouch?: (data: GestureEventData<TPointer>) => void\n\n /** Called when pointer up occurs outside the container */\n onTouchOutside?: (data: GestureEventData<TPointer>) => void\n\n /** Called during pointer movement */\n onTouchMove?: (data: GestureEventData<TPointer>) => void\n\n /** Called when double tap/click is detected */\n onDoubleTap?: (data: GestureEventData<TPointer>) => void\n\n /** Called when pointer is held down for configured duration */\n onLongPress?: (data: GestureEventData<TPointer>) => void\n\n /** Called when mouse wheel / trackpad scroll occurs over the container */\n onWheel?: (data: WheelEventData<TPointer>) => void\n\n /**\n * Tooltip configuration callback (desktop / pointer hover only).\n * The API is portable, the renderer decides how to draw it.\n */\n onTooltip?: TooltipCallback\n\n /** Duration in ms to trigger long press (default: 500ms) */\n longPressDuration?: number\n\n /** Max time in ms between taps for double tap (default: 300ms) */\n doubleTapDelay?: number\n\n /** Max time in ms for a valid touch/click (default: 500ms) */\n maxTouchDuration?: number\n}\n"],"names":[],"mappings":";;AA4FO,SAAS,gBACd,GACA,GACA,UACA,WACA,UACA,UAAU,GACgB;AAC1B,SAAO;AAAA,IACL,GAAG,KAAK,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,KAAK,IAAI,SAAS,SAAS,QAAQ,WAAW,OAAO,CAAC;AAAA,IACxF,GAAG,KAAK,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,KAAK,IAAI,SAAS,SAAS,SAAS,YAAY,OAAO,CAAC;AAAA,EAAA;AAE9F;AAYO,SAAS,mBACd,WAaA,QACA,cACA,eACA,SAAS,GACiB;AAC1B,QAAM,KAAK,OAAO,IAAI,OAAO,QAAQ;AACrC,QAAM,KAAK,OAAO,IAAI,OAAO,SAAS;AAEtC,UAAQ,WAAA;AAAA,IACN,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,eAAe,GAAG,GAAG,OAAO,IAAI,gBAAgB,OAAA;AAAA,IACnE,KAAK;AACH,aAAO,EAAE,GAAG,KAAK,eAAe,GAAG,GAAG,OAAO,IAAI,OAAO,SAAS,OAAA;AAAA,IACnE,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,eAAe,QAAQ,GAAG,KAAK,gBAAgB,EAAA;AAAA,IACxE,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,QAAQ,GAAG,KAAK,gBAAgB,EAAA;AAAA,IACxE,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,IAAI,gBAAgB,OAAA;AAAA,IACtD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,cAAc,GAAG,OAAO,IAAI,gBAAgB,OAAA;AAAA,IACpF,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,SAAS,OAAA;AAAA,IACtD,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,cAAc,GAAG,OAAO,IAAI,OAAO,SAAS,OAAA;AAAA,IACpF,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,eAAe,QAAQ,GAAG,OAAO,EAAA;AAAA,IAC1D,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,eAAe,QAAQ,GAAG,OAAO,IAAI,OAAO,SAAS,cAAA;AAAA,IAC9E,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,QAAQ,GAAG,OAAO,EAAA;AAAA,IAC1D,KAAK;AACH,aAAO,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,QAAQ,GAAG,OAAO,IAAI,OAAO,SAAS,cAAA;AAAA,IAC9E;AACE,aAAO,EAAE,GAAG,KAAK,eAAe,GAAG,GAAG,OAAO,IAAI,OAAO,SAAS,OAAA;AAAA,EAAO;AAE9E;AA2DO,SAAS,oBAAoB,OAAoD;AACtF,MAAI,UAAU,OAAW,QAAO,CAAA;AAChC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,KAAK,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,MAAA;AAAA,EAC1D;AACA,SAAO;AACT;AAKO,SAAS,sBACd,OAC6B;AAC7B,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO;AACT;AAKO,SAAS,aAAa,OAG3B;AACA,MAAI,UAAU,OAAW,QAAO,EAAE,YAAY,GAAG,UAAU,EAAA;AAC3D,MAAI,OAAO,UAAU,SAAU,QAAO,EAAE,YAAY,OAAO,UAAU,MAAA;AACrE,SAAO;AAAA,IACL,YAAY,MAAM,cAAc;AAAA,IAChC,UAAU,MAAM,YAAY;AAAA,EAAA;AAEhC;;;;;;"}
|