@hanzogui/web 7.3.2 → 8.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/.turbo/turbo-build.log +2 -0
- package/dist/cjs/_withStableStyle.cjs +2 -2
- package/dist/cjs/_withStableStyle.native.js +2 -2
- package/dist/cjs/_withStableStyle.native.js.map +1 -1
- package/dist/cjs/config.cjs +18 -10
- package/dist/cjs/config.native.js +19 -10
- package/dist/cjs/config.native.js.map +1 -1
- package/dist/cjs/constants/constants.cjs +1 -1
- package/dist/cjs/constants/constants.native.js +1 -1
- package/dist/cjs/constants/constants.native.js.map +1 -1
- package/dist/cjs/createComponent.cjs +68 -28
- package/dist/cjs/createComponent.native.js +75 -30
- package/dist/cjs/createComponent.native.js.map +1 -1
- package/dist/cjs/createGui.cjs +1 -1
- package/dist/cjs/createGui.native.js +1 -1
- package/dist/cjs/createGui.native.js.map +1 -1
- package/dist/cjs/eventHandling.cjs +2 -2
- package/dist/cjs/eventHandling.native.js +73 -54
- package/dist/cjs/eventHandling.native.js.map +1 -1
- package/dist/cjs/helpers/createDesignSystem.cjs +2 -2
- package/dist/cjs/helpers/defaultAnimationDriver.cjs +1 -1
- package/dist/cjs/helpers/defaultAnimationDriver.native.js +1 -1
- package/dist/cjs/helpers/expandStyle.cjs +46 -5
- package/dist/cjs/helpers/expandStyle.native.js +36 -30
- package/dist/cjs/helpers/expandStyle.native.js.map +1 -1
- package/dist/cjs/helpers/getGroupPropParts.cjs +1 -1
- package/dist/cjs/helpers/getGroupPropParts.native.js +1 -1
- package/dist/cjs/helpers/getSplitStyles.cjs +76 -31
- package/dist/cjs/helpers/getSplitStyles.native.js +140 -85
- package/dist/cjs/helpers/getSplitStyles.native.js.map +1 -1
- package/dist/cjs/helpers/getTokenForKey.cjs +5 -5
- package/dist/cjs/helpers/getTokenForKey.native.js +5 -5
- package/dist/cjs/helpers/getTokenForKey.native.js.map +1 -1
- package/dist/cjs/helpers/getVariantExtras.cjs +7 -3
- package/dist/cjs/helpers/getVariantExtras.native.js +7 -3
- package/dist/cjs/helpers/getVariantExtras.native.js.map +1 -1
- package/dist/cjs/helpers/insertStyleRule.cjs +4 -4
- package/dist/cjs/helpers/insertStyleRule.native.js +3 -3
- package/dist/cjs/helpers/insertStyleRule.native.js.map +1 -1
- package/dist/cjs/helpers/mainThreadPressEvents.native.js +32 -4
- package/dist/cjs/helpers/mainThreadPressEvents.native.js.map +1 -1
- package/dist/cjs/helpers/normalizeStyle.cjs +22 -1
- package/dist/cjs/helpers/normalizeStyle.native.js +41 -1
- package/dist/cjs/helpers/normalizeStyle.native.js.map +1 -1
- package/dist/cjs/helpers/platformResolveValue.cjs +1 -1
- package/dist/cjs/helpers/platformResolveValue.native.js +1 -1
- package/dist/cjs/helpers/platformResolveValue.native.js.map +1 -1
- package/dist/cjs/helpers/pointerEvents.native.js +26 -20
- package/dist/cjs/helpers/pointerEvents.native.js.map +1 -1
- package/dist/cjs/helpers/propMapper.cjs +31 -7
- package/dist/cjs/helpers/propMapper.native.js +70 -20
- package/dist/cjs/helpers/propMapper.native.js.map +1 -1
- package/dist/cjs/helpers/resolveSafeArea.native.js +1 -1
- package/dist/cjs/helpers/resolveSafeArea.native.js.map +1 -1
- package/dist/cjs/helpers/styleOriginalValues.cjs +28 -0
- package/dist/cjs/helpers/styleOriginalValues.native.js +31 -0
- package/dist/cjs/helpers/styleOriginalValues.native.js.map +1 -0
- package/dist/cjs/helpers/styleProvenance.cjs +43 -0
- package/dist/cjs/helpers/styleProvenance.native.js +46 -0
- package/dist/cjs/helpers/styleProvenance.native.js.map +1 -0
- package/dist/cjs/helpers/wrapStyleTags.cjs +35 -11
- package/dist/cjs/helpers/wrapStyleTags.native.js.map +1 -1
- package/dist/cjs/hooks/getThemeProxied.cjs +1 -1
- package/dist/cjs/hooks/getThemeProxied.native.js +4 -4
- package/dist/cjs/hooks/getThemeProxied.native.js.map +1 -1
- package/dist/cjs/hooks/useComponentState.cjs +29 -3
- package/dist/cjs/hooks/useComponentState.native.js +30 -4
- package/dist/cjs/hooks/useComponentState.native.js.map +1 -1
- package/dist/cjs/hooks/useMedia.cjs +107 -42
- package/dist/cjs/hooks/useMedia.native.js +149 -60
- package/dist/cjs/hooks/useMedia.native.js.map +1 -1
- package/dist/cjs/hooks/useTheme.cjs +18 -5
- package/dist/cjs/hooks/useTheme.native.js +19 -5
- package/dist/cjs/hooks/useTheme.native.js.map +1 -1
- package/dist/cjs/hooks/useThemeState.cjs +143 -72
- package/dist/cjs/hooks/useThemeState.native.js +155 -74
- package/dist/cjs/hooks/useThemeState.native.js.map +1 -1
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/index.native.js +3 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/opacityModifier.test-d.cjs +36 -0
- package/dist/cjs/opacityModifier.test-d.native.js +39 -0
- package/dist/cjs/opacityModifier.test-d.native.js.map +1 -0
- package/dist/cjs/styledNonStyleProps.test-d.cjs +63 -0
- package/dist/cjs/styledNonStyleProps.test-d.native.js +66 -0
- package/dist/cjs/styledNonStyleProps.test-d.native.js.map +1 -0
- package/dist/cjs/views/GuiProvider.cjs +2 -2
- package/dist/cjs/views/Text.cjs +1 -0
- package/dist/cjs/views/Text.native.js +1 -0
- package/dist/cjs/views/Text.native.js.map +1 -1
- package/dist/cjs/views/Theme.cjs +1 -1
- package/dist/cjs/views/Theme.native.js +1 -1
- package/dist/cjs/views/Theme.native.js.map +1 -1
- package/dist/esm/_withStableStyle.mjs +2 -2
- package/dist/esm/_withStableStyle.mjs.map +1 -1
- package/dist/esm/_withStableStyle.native.js +2 -2
- package/dist/esm/_withStableStyle.native.js.map +1 -1
- package/dist/esm/config.mjs +18 -11
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/config.native.js +19 -11
- package/dist/esm/config.native.js.map +1 -1
- package/dist/esm/constants/constants.mjs +1 -1
- package/dist/esm/constants/constants.native.js +1 -1
- package/dist/esm/constants/constants.native.js.map +1 -1
- package/dist/esm/createComponent.mjs +74 -35
- package/dist/esm/createComponent.mjs.map +1 -1
- package/dist/esm/createComponent.native.js +90 -42
- package/dist/esm/createComponent.native.js.map +1 -1
- package/dist/esm/createGui.mjs +6 -6
- package/dist/esm/createGui.mjs.map +1 -1
- package/dist/esm/createGui.native.js +6 -6
- package/dist/esm/createGui.native.js.map +1 -1
- package/dist/esm/eventHandling.mjs +2 -2
- package/dist/esm/eventHandling.mjs.map +1 -1
- package/dist/esm/eventHandling.native.js +74 -55
- package/dist/esm/eventHandling.native.js.map +1 -1
- package/dist/esm/helpers/createDesignSystem.mjs +2 -2
- package/dist/esm/helpers/createDesignSystem.mjs.map +1 -1
- package/dist/esm/helpers/createDesignSystem.native.js +1 -2
- package/dist/esm/helpers/createDesignSystem.native.js.map +1 -1
- package/dist/esm/helpers/defaultAnimationDriver.mjs +1 -1
- package/dist/esm/helpers/defaultAnimationDriver.mjs.map +1 -1
- package/dist/esm/helpers/defaultAnimationDriver.native.js +1 -1
- package/dist/esm/helpers/expandStyle.mjs +47 -8
- package/dist/esm/helpers/expandStyle.mjs.map +1 -1
- package/dist/esm/helpers/expandStyle.native.js +36 -30
- package/dist/esm/helpers/expandStyle.native.js.map +1 -1
- package/dist/esm/helpers/expandStyles.mjs.map +1 -1
- package/dist/esm/helpers/expandStyles.native.js.map +1 -1
- package/dist/esm/helpers/getGroupPropParts.mjs +1 -1
- package/dist/esm/helpers/getGroupPropParts.mjs.map +1 -1
- package/dist/esm/helpers/getGroupPropParts.native.js +1 -1
- package/dist/esm/helpers/getSplitStyles.mjs +86 -45
- package/dist/esm/helpers/getSplitStyles.mjs.map +1 -1
- package/dist/esm/helpers/getSplitStyles.native.js +146 -98
- package/dist/esm/helpers/getSplitStyles.native.js.map +1 -1
- package/dist/esm/helpers/getThemeCSSRules.mjs +1 -1
- package/dist/esm/helpers/getThemeCSSRules.mjs.map +1 -1
- package/dist/esm/helpers/getTokenForKey.mjs +5 -5
- package/dist/esm/helpers/getTokenForKey.mjs.map +1 -1
- package/dist/esm/helpers/getTokenForKey.native.js +5 -5
- package/dist/esm/helpers/getTokenForKey.native.js.map +1 -1
- package/dist/esm/helpers/getVariantExtras.mjs +7 -3
- package/dist/esm/helpers/getVariantExtras.mjs.map +1 -1
- package/dist/esm/helpers/getVariantExtras.native.js +7 -3
- package/dist/esm/helpers/getVariantExtras.native.js.map +1 -1
- package/dist/esm/helpers/insertStyleRule.mjs +4 -6
- package/dist/esm/helpers/insertStyleRule.mjs.map +1 -1
- package/dist/esm/helpers/insertStyleRule.native.js +0 -26
- package/dist/esm/helpers/insertStyleRule.native.js.map +1 -1
- package/dist/esm/helpers/isActivePlatform.mjs.map +1 -1
- package/dist/esm/helpers/isActivePlatform.native.js.map +1 -1
- package/dist/esm/helpers/log.mjs.map +1 -1
- package/dist/esm/helpers/log.native.js.map +1 -1
- package/dist/esm/helpers/mainThreadPressEvents.native.js +32 -4
- package/dist/esm/helpers/mainThreadPressEvents.native.js.map +1 -1
- package/dist/esm/helpers/normalizeStyle.mjs +22 -1
- package/dist/esm/helpers/normalizeStyle.mjs.map +1 -1
- package/dist/esm/helpers/normalizeStyle.native.js +41 -1
- package/dist/esm/helpers/normalizeStyle.native.js.map +1 -1
- package/dist/esm/helpers/platformResolveValue.mjs +1 -1
- package/dist/esm/helpers/platformResolveValue.mjs.map +1 -1
- package/dist/esm/helpers/platformResolveValue.native.js +1 -1
- package/dist/esm/helpers/platformResolveValue.native.js.map +1 -1
- package/dist/esm/helpers/pointerEvents.native.js +26 -20
- package/dist/esm/helpers/pointerEvents.native.js.map +1 -1
- package/dist/esm/helpers/propMapper.mjs +32 -11
- package/dist/esm/helpers/propMapper.mjs.map +1 -1
- package/dist/esm/helpers/propMapper.native.js +71 -22
- package/dist/esm/helpers/propMapper.native.js.map +1 -1
- package/dist/esm/helpers/resolveSafeArea.native.js +1 -1
- package/dist/esm/helpers/resolveSafeArea.native.js.map +1 -1
- package/dist/esm/helpers/skipProps.mjs +0 -1
- package/dist/esm/helpers/skipProps.mjs.map +1 -1
- package/dist/esm/helpers/skipProps.native.js +0 -1
- package/dist/esm/helpers/skipProps.native.js.map +1 -1
- package/dist/esm/helpers/styleOriginalValues.mjs +3 -0
- package/dist/esm/helpers/styleOriginalValues.mjs.map +1 -0
- package/dist/esm/helpers/styleOriginalValues.native.js +3 -0
- package/dist/esm/helpers/styleOriginalValues.native.js.map +1 -0
- package/dist/esm/helpers/styleProvenance.mjs +16 -0
- package/dist/esm/helpers/styleProvenance.mjs.map +1 -0
- package/dist/esm/helpers/styleProvenance.native.js +16 -0
- package/dist/esm/helpers/styleProvenance.native.js.map +1 -0
- package/dist/esm/helpers/useRenderElement.mjs.map +1 -1
- package/dist/esm/helpers/useRenderElement.native.js.map +1 -1
- package/dist/esm/helpers/wrapStyleTags.mjs +35 -11
- package/dist/esm/helpers/wrapStyleTags.mjs.map +1 -1
- package/dist/esm/helpers/wrapStyleTags.native.js +0 -2
- package/dist/esm/helpers/wrapStyleTags.native.js.map +1 -1
- package/dist/esm/hooks/getThemeProxied.mjs +2 -5
- package/dist/esm/hooks/getThemeProxied.mjs.map +1 -1
- package/dist/esm/hooks/getThemeProxied.native.js +5 -5
- package/dist/esm/hooks/getThemeProxied.native.js.map +1 -1
- package/dist/esm/hooks/useComponentState.mjs +31 -5
- package/dist/esm/hooks/useComponentState.mjs.map +1 -1
- package/dist/esm/hooks/useComponentState.native.js +32 -6
- package/dist/esm/hooks/useComponentState.native.js.map +1 -1
- package/dist/esm/hooks/useMedia.mjs +108 -43
- package/dist/esm/hooks/useMedia.mjs.map +1 -1
- package/dist/esm/hooks/useMedia.native.js +150 -61
- package/dist/esm/hooks/useMedia.native.js.map +1 -1
- package/dist/esm/hooks/useTheme.mjs +18 -5
- package/dist/esm/hooks/useTheme.mjs.map +1 -1
- package/dist/esm/hooks/useTheme.native.js +19 -5
- package/dist/esm/hooks/useTheme.native.js.map +1 -1
- package/dist/esm/hooks/useThemeState.mjs +141 -70
- package/dist/esm/hooks/useThemeState.mjs.map +1 -1
- package/dist/esm/hooks/useThemeState.native.js +154 -73
- package/dist/esm/hooks/useThemeState.native.js.map +1 -1
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +4 -4
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +4 -4
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/insertFont.mjs.map +1 -1
- package/dist/esm/insertFont.native.js +0 -1
- package/dist/esm/insertFont.native.js.map +1 -1
- package/dist/esm/opacityModifier.test-d.mjs +37 -0
- package/dist/esm/opacityModifier.test-d.mjs.map +1 -0
- package/dist/esm/opacityModifier.test-d.native.js +37 -0
- package/dist/esm/opacityModifier.test-d.native.js.map +1 -0
- package/dist/esm/styledNonStyleProps.test-d.mjs +64 -0
- package/dist/esm/styledNonStyleProps.test-d.mjs.map +1 -0
- package/dist/esm/styledNonStyleProps.test-d.native.js +64 -0
- package/dist/esm/styledNonStyleProps.test-d.native.js.map +1 -0
- package/dist/esm/views/GuiProvider.mjs +2 -2
- package/dist/esm/views/GuiProvider.mjs.map +1 -1
- package/dist/esm/views/GuiProvider.native.js +6 -6
- package/dist/esm/views/GuiProvider.native.js.map +1 -1
- package/dist/esm/views/Text.mjs +1 -0
- package/dist/esm/views/Text.mjs.map +1 -1
- package/dist/esm/views/Text.native.js +1 -0
- package/dist/esm/views/Text.native.js.map +1 -1
- package/dist/esm/views/Theme.mjs +1 -1
- package/dist/esm/views/Theme.mjs.map +1 -1
- package/dist/esm/views/Theme.native.js +1 -1
- package/dist/esm/views/Theme.native.js.map +1 -1
- package/dist/esm/views/ThemeProvider.mjs.map +1 -1
- package/dist/esm/views/ThemeProvider.native.js +2 -4
- package/dist/esm/views/ThemeProvider.native.js.map +1 -1
- package/inject-styles/index.cjs +2 -0
- package/inject-styles/index.js +2 -0
- package/package.json +27 -40
- package/src/_withStableStyle.tsx +9 -3
- package/src/config.ts +24 -14
- package/src/constants/accessibilityDirectMap.tsx +1 -1
- package/src/constants/constants.ts +1 -1
- package/src/createComponent.tsx +161 -26
- package/src/createGui.ts +2 -2
- package/src/eventHandling.native.ts +143 -52
- package/src/eventHandling.ts +4 -2
- package/src/helpers/createDesignSystem.ts +2 -2
- package/src/helpers/createMediaStyle.ts +1 -1
- package/src/helpers/defaultAnimationDriver.tsx +1 -1
- package/src/helpers/expandStyle.ts +108 -40
- package/src/helpers/getGroupPropParts.ts +1 -1
- package/src/helpers/getSplitStyles.tsx +178 -72
- package/src/helpers/getTokenForKey.ts +5 -5
- package/src/helpers/getVariantExtras.tsx +5 -4
- package/src/helpers/insertStyleRule.tsx +7 -7
- package/src/helpers/mainThreadPressEvents.native.ts +42 -2
- package/src/helpers/mergeProps.ts +1 -1
- package/src/helpers/normalizeStyle.ts +23 -1
- package/src/helpers/platformResolveValue.native.ts +4 -1
- package/src/helpers/platformResolveValue.ts +5 -1
- package/src/helpers/pointerEvents.native.ts +26 -19
- package/src/helpers/propMapper.ts +61 -6
- package/src/helpers/resolveSafeArea.native.ts +1 -1
- package/src/helpers/styleOriginalValues.ts +2 -0
- package/src/helpers/styleProvenance.ts +49 -0
- package/src/helpers/wrapStyleTags.tsx +63 -20
- package/src/hooks/getThemeProxied.ts +14 -8
- package/src/hooks/useComponentState.ts +56 -4
- package/src/hooks/useMedia.tsx +156 -43
- package/src/hooks/useTheme.tsx +28 -6
- package/src/hooks/useThemeState.ts +284 -142
- package/src/index.ts +9 -1
- package/src/interfaces/GuiComponentPropsBaseBase.tsx +2 -2
- package/src/opacityModifier.test-d.ts +65 -0
- package/src/styled.tsx +1 -1
- package/src/styledNonStyleProps.test-d.ts +106 -0
- package/src/types.tsx +120 -22
- package/src/views/GuiProvider.tsx +2 -2
- package/src/views/Text.tsx +1 -0
- package/src/views/Theme.tsx +4 -1
- package/tsconfig.json +44 -0
- package/tsconfig.test.json +9 -0
- package/types/_withStableStyle.d.ts.map +1 -1
- package/types/config.d.ts +3 -1
- package/types/config.d.ts.map +1 -1
- package/types/constants/constants.d.ts +1 -1
- package/types/constants/constants.d.ts.map +1 -1
- package/types/createComponent.d.ts.map +1 -1
- package/types/eventHandling.d.ts +2 -2
- package/types/eventHandling.d.ts.map +1 -1
- package/types/eventHandling.native.d.ts +3 -3
- package/types/eventHandling.native.d.ts.map +1 -1
- package/types/helpers/expandStyle.d.ts +2 -1
- package/types/helpers/expandStyle.d.ts.map +1 -1
- package/types/helpers/getSplitStyles.d.ts +4 -2
- package/types/helpers/getSplitStyles.d.ts.map +1 -1
- package/types/helpers/getVariantExtras.d.ts.map +1 -1
- package/types/helpers/mainThreadPressEvents.native.d.ts.map +1 -1
- package/types/helpers/normalizeStyle.d.ts.map +1 -1
- package/types/helpers/platformResolveValue.d.ts.map +1 -1
- package/types/helpers/platformResolveValue.native.d.ts.map +1 -1
- package/types/helpers/pointerEvents.native.d.ts.map +1 -1
- package/types/helpers/propMapper.d.ts.map +1 -1
- package/types/helpers/styleOriginalValues.d.ts +2 -0
- package/types/helpers/styleOriginalValues.d.ts.map +1 -0
- package/types/helpers/styleProvenance.d.ts +11 -0
- package/types/helpers/styleProvenance.d.ts.map +1 -0
- package/types/helpers/wrapStyleTags.d.ts +1 -1
- package/types/helpers/wrapStyleTags.d.ts.map +1 -1
- package/types/hooks/getThemeProxied.d.ts.map +1 -1
- package/types/hooks/useComponentState.d.ts +2 -1
- package/types/hooks/useComponentState.d.ts.map +1 -1
- package/types/hooks/useMedia.d.ts.map +1 -1
- package/types/hooks/useTheme.d.ts +1 -1
- package/types/hooks/useTheme.d.ts.map +1 -1
- package/types/hooks/useThemeState.d.ts +1 -1
- package/types/hooks/useThemeState.d.ts.map +1 -1
- package/types/index.d.ts +3 -3
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/GuiComponentPropsBaseBase.d.ts +2 -2
- package/types/types.d.ts +33 -16
- package/types/types.d.ts.map +1 -1
- package/types/views/Configuration.d.ts +1 -1
- package/types/views/Configuration.d.ts.map +1 -1
- package/types/views/FontLanguage.d.ts +1 -1
- package/types/views/FontLanguage.native.d.ts +1 -2
- package/types/views/FontLanguage.native.d.ts.map +1 -1
- package/types/views/GuiProvider.d.ts +1 -2
- package/types/views/GuiProvider.d.ts.map +1 -1
- package/types/views/GuiRoot.d.ts +1 -1
- package/types/views/GuiRoot.d.ts.map +1 -1
- package/types/views/Slot.d.ts +1 -1
- package/types/views/Text.d.ts.map +1 -1
- package/types/views/Theme.d.ts.map +1 -1
- package/types/views/ThemeProvider.d.ts +1 -1
- package/types/views/ThemeProvider.d.ts.map +1 -1
- package/vitest.config.d.ts +3 -0
- package/vitest.config.d.ts.map +1 -0
- package/vitest.config.ts +14 -0
- package/LICENSE +0 -42
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useIsomorphicLayoutEffect } from '@hanzogui/constants'
|
|
1
|
+
import { supportsDynamicColorIOS, useIsomorphicLayoutEffect } from '@hanzogui/constants'
|
|
3
2
|
import {
|
|
4
3
|
createContext,
|
|
5
|
-
useCallback,
|
|
6
4
|
useContext,
|
|
5
|
+
useEffect,
|
|
7
6
|
useId,
|
|
8
|
-
|
|
7
|
+
useReducer,
|
|
8
|
+
useRef,
|
|
9
9
|
type MutableRefObject,
|
|
10
10
|
} from 'react'
|
|
11
11
|
import { getConfig, getSetting } from '../config'
|
|
@@ -55,11 +55,22 @@ export const getRootThemeState = () => rootThemeState
|
|
|
55
55
|
// extracts base name without scheme: "light_red_surface1" -> "red_surface1"
|
|
56
56
|
const getThemeBaseName = (name: string) => name.replace(/^(light|dark)_/, '')
|
|
57
57
|
|
|
58
|
+
// useReducer-based force-update; cheaper than useSyncExternalStore's internal
|
|
59
|
+
// useState+useLayoutEffect+useEffect+useDebugValue chain on Hermes.
|
|
60
|
+
const incReducer = (c: number): number => c + 1
|
|
61
|
+
|
|
58
62
|
export const useThemeState = (
|
|
59
63
|
props: UseThemeWithStateProps,
|
|
60
64
|
isRoot = false,
|
|
61
65
|
keys: MutableRefObject<Set<string> | null>,
|
|
62
|
-
schemeKeys?: MutableRefObject<Set<string> | null
|
|
66
|
+
schemeKeys?: MutableRefObject<Set<string> | null>,
|
|
67
|
+
// when true, install the propsKey-watching useIsomorphicLayoutEffect that
|
|
68
|
+
// schedules descendant updates via listenersByParent[id]. Only <Theme>
|
|
69
|
+
// providers actually push their themeState.id into ThemeStateContext, so
|
|
70
|
+
// only they can have descendants subscribed under their id. Leaf styled
|
|
71
|
+
// components pass false (the default) and save one hook slot per mount.
|
|
72
|
+
// Stable per call-site (rule of hooks satisfied).
|
|
73
|
+
cascadeOnChange = false
|
|
63
74
|
): ThemeState => {
|
|
64
75
|
'use no memo'
|
|
65
76
|
|
|
@@ -87,148 +98,271 @@ Looked for theme${props.name ? ` "${props.name}"` : ''}${props.componentName ? `
|
|
|
87
98
|
)
|
|
88
99
|
}
|
|
89
100
|
|
|
101
|
+
// useId keeps theme-provider ids tied to the React tree. A process-wide
|
|
102
|
+
// counter can let children observe a provider context id whose matching
|
|
103
|
+
// states Map entry was never populated in multi-root/native surfaces.
|
|
90
104
|
const id = useId()
|
|
91
|
-
const subscribe = useCallback(
|
|
92
|
-
(cb: Function) => {
|
|
93
|
-
listenersByParent[parentId] = listenersByParent[parentId] || new Set()
|
|
94
|
-
listenersByParent[parentId].add(id)
|
|
95
|
-
allListeners.set(id, () => {
|
|
96
|
-
PendingUpdate.set(id, shouldForce ? 'force' : true)
|
|
97
|
-
cb()
|
|
98
|
-
})
|
|
99
|
-
return () => {
|
|
100
|
-
allListeners.delete(id)
|
|
101
|
-
listenersByParent[parentId].delete(id)
|
|
102
|
-
localStates.delete(id)
|
|
103
|
-
states.delete(id)
|
|
104
|
-
PendingUpdate.delete(id)
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
[id, parentId]
|
|
108
|
-
)
|
|
109
|
-
|
|
110
105
|
const propsKey = getPropsKey(props)
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
parentState &&
|
|
120
|
-
(local as any)._parentName === parentState.name &&
|
|
121
|
-
(local as any)._propsKey === propsKey
|
|
122
|
-
) {
|
|
123
|
-
return local
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// check if this is a scheme-only change (light↔dark) where DynamicColorIOS handles it
|
|
128
|
-
const isSchemeOnlyChange =
|
|
129
|
-
process.env.GUI_TARGET === 'native' &&
|
|
130
|
-
isIos &&
|
|
131
|
-
getSetting('fastSchemeChange') &&
|
|
132
|
-
local &&
|
|
133
|
-
parentState &&
|
|
134
|
-
local.scheme !== parentState.scheme &&
|
|
135
|
-
getThemeBaseName(local.name) === getThemeBaseName(parentState.name)
|
|
136
|
-
|
|
137
|
-
// all tracked keys are scheme-optimized = can skip re-render for scheme changes
|
|
138
|
-
const keysSize = keys?.current?.size ?? 0
|
|
139
|
-
const schemeKeysSize = schemeKeys?.current?.size ?? 0
|
|
140
|
-
const allKeysSchemeOptimized = schemeKeysSize === keysSize && keysSize > 0
|
|
141
|
-
|
|
142
|
-
const canSkipForSchemeChange = isSchemeOnlyChange && allKeysSchemeOptimized
|
|
143
|
-
|
|
144
|
-
const needsUpdate = props.passThrough
|
|
145
|
-
? false
|
|
146
|
-
: isRoot || props.name === 'light' || props.name === 'dark' || props.name === null
|
|
147
|
-
? true
|
|
148
|
-
: !HasRenderedOnce.get(keys)
|
|
149
|
-
? true
|
|
150
|
-
: canSkipForSchemeChange
|
|
151
|
-
? false // skip re-render for scheme-only changes with DynamicColorIOS
|
|
152
|
-
: keys?.current?.size
|
|
153
|
-
? true
|
|
154
|
-
: props.needsUpdate?.()
|
|
155
|
-
|
|
156
|
-
const [rerender, next] = getNextState(
|
|
157
|
-
local,
|
|
107
|
+
// stable ref-bag for render inputs and the optional subscription cleanup.
|
|
108
|
+
// lastSnap caches the last getSnapshot result for the subscription bailout.
|
|
109
|
+
const ref = useRef<ThemeStateRef>(null as any)
|
|
110
|
+
if (!ref.current) {
|
|
111
|
+
ref.current = {
|
|
112
|
+
id,
|
|
113
|
+
parentId,
|
|
158
114
|
props,
|
|
159
115
|
propsKey,
|
|
160
116
|
isRoot,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
117
|
+
keys,
|
|
118
|
+
schemeKeys,
|
|
119
|
+
renderVersion: 0,
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
// refresh latest values for the stable closures to read
|
|
123
|
+
ref.current.props = props
|
|
124
|
+
ref.current.propsKey = propsKey
|
|
125
|
+
ref.current.isRoot = isRoot
|
|
126
|
+
ref.current.keys = keys
|
|
127
|
+
ref.current.schemeKeys = schemeKeys
|
|
128
|
+
ref.current.parentId = parentId
|
|
129
|
+
}
|
|
130
|
+
ref.current.renderVersion++
|
|
131
|
+
|
|
132
|
+
if (process.env.NODE_ENV === 'development' && globalThis.time)
|
|
133
|
+
globalThis.time`theme-prep-uses`
|
|
166
134
|
|
|
167
|
-
|
|
135
|
+
// manual subscription replaces useSyncExternalStore: same granular bailout
|
|
136
|
+
// (getSnapshot returning the same ref → React doesn't re-render), fewer
|
|
137
|
+
// React-internal hook slots on Hermes. We don't need tearing prevention
|
|
138
|
+
// here: theme/media updates are event-driven, not transition-driven, and
|
|
139
|
+
// useReducer in normal mode already gives same-tick batching.
|
|
140
|
+
const [, forceUpdate] = useReducer(incReducer, 0)
|
|
141
|
+
const state = getSnapshotImpl(ref.current)
|
|
142
|
+
ref.current.lastSnap = state
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
const r = ref.current
|
|
146
|
+
const renderVersion = r.renderVersion
|
|
147
|
+
|
|
148
|
+
// strict-mode dev double-invokes effects: cleanup runs between the two
|
|
149
|
+
// invocations with no render in between, so the "unchanged renderVersion
|
|
150
|
+
// means unmount" check below false-positives and deletes this component's
|
|
151
|
+
// registered theme state mid-lifecycle. the registry is only re-populated
|
|
152
|
+
// on this component's next render, so until then children resolve a
|
|
153
|
+
// missing parent and fall back to the root theme state (isNew: true) —
|
|
154
|
+
// which flips getThemedChildren to wrap and re-parents/remounts their
|
|
155
|
+
// hosts, losing focus (keyboard dismiss on first Input tap). per react's
|
|
156
|
+
// strict-mode contract, setup restores whatever cleanup tore down.
|
|
157
|
+
if (r.lastSnap && !states.has(r.id)) {
|
|
158
|
+
states.set(r.id, r.lastSnap)
|
|
159
|
+
localStates.set(r.id, r.lastSnap)
|
|
160
|
+
}
|
|
168
161
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
// we always return the localState object in each component
|
|
172
|
-
// the global state (states) should always be up to date with the latest
|
|
173
|
-
if (!local || rerender) {
|
|
174
|
-
local = { ...next }
|
|
175
|
-
localStates.set(id, local)
|
|
162
|
+
if (r.unsubscribe && r.subscribedParentId !== r.parentId) {
|
|
163
|
+
cleanupThemeSubscription(r)
|
|
176
164
|
}
|
|
177
165
|
|
|
178
|
-
if (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
166
|
+
if (shouldSubscribeToTheme(r, cascadeOnChange)) {
|
|
167
|
+
if (!r.unsubscribe) {
|
|
168
|
+
const pid = r.parentId
|
|
169
|
+
const sid = r.id
|
|
170
|
+
const cb = () => {
|
|
171
|
+
const next = getSnapshotImpl(r)
|
|
172
|
+
if (next !== r.lastSnap) {
|
|
173
|
+
r.lastSnap = next
|
|
174
|
+
forceUpdate()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
listenersByParent[pid] = listenersByParent[pid] || new Set()
|
|
179
|
+
listenersByParent[pid].add(sid)
|
|
180
|
+
allListeners.set(sid, () => {
|
|
181
|
+
PendingUpdate.set(sid, shouldForce ? 'force' : true)
|
|
182
|
+
cb()
|
|
183
|
+
})
|
|
184
|
+
r.subscribedParentId = pid
|
|
185
|
+
r.unsubscribe = () => {
|
|
186
|
+
allListeners.delete(sid)
|
|
187
|
+
listenersByParent[pid]?.delete(sid)
|
|
188
|
+
localStates.delete(sid)
|
|
189
|
+
states.delete(sid)
|
|
190
|
+
PendingUpdate.delete(sid)
|
|
191
|
+
r.unsubscribe = undefined
|
|
192
|
+
r.subscribedParentId = undefined
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} else if (r.unsubscribe) {
|
|
196
|
+
cleanupThemeSubscription(r)
|
|
193
197
|
}
|
|
194
198
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
199
|
+
return () => {
|
|
200
|
+
// react runs passive cleanup before the next effect as well as on unmount.
|
|
201
|
+
// a newer render bumps renderVersion before that cleanup, so equality here
|
|
202
|
+
// means this is the final unmount cleanup.
|
|
203
|
+
if (r.renderVersion === renderVersion) {
|
|
204
|
+
cleanupThemeState(r)
|
|
205
|
+
}
|
|
198
206
|
}
|
|
199
|
-
|
|
200
|
-
;(local as any)._propsKey = propsKey
|
|
201
|
-
states.set(id, next)
|
|
207
|
+
})
|
|
202
208
|
|
|
203
|
-
|
|
209
|
+
if (cascadeOnChange) {
|
|
210
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
211
|
+
useIsomorphicLayoutEffect(() => {
|
|
212
|
+
if (!HasRenderedOnce.get(keys)) {
|
|
213
|
+
HasRenderedOnce.set(keys, true)
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
if (!propsKey) {
|
|
217
|
+
if (HadTheme.get(keys)) {
|
|
218
|
+
// we're removing the last theme, make sure to notify
|
|
219
|
+
scheduleUpdate(id)
|
|
220
|
+
}
|
|
221
|
+
HadTheme.set(keys, false)
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') {
|
|
225
|
+
console.warn(` · useTheme(${id}) scheduleUpdate`, propsKey, states.get(id)?.name)
|
|
226
|
+
}
|
|
227
|
+
scheduleUpdate(id)
|
|
228
|
+
HadTheme.set(keys, true)
|
|
229
|
+
}, [keys, propsKey])
|
|
204
230
|
}
|
|
205
231
|
|
|
206
|
-
|
|
207
|
-
|
|
232
|
+
return state
|
|
233
|
+
}
|
|
208
234
|
|
|
209
|
-
|
|
235
|
+
type SnapshotRef = {
|
|
236
|
+
id: string
|
|
237
|
+
parentId: string
|
|
238
|
+
props: UseThemeWithStateProps
|
|
239
|
+
propsKey: string
|
|
240
|
+
isRoot: boolean
|
|
241
|
+
keys: MutableRefObject<Set<string> | null>
|
|
242
|
+
schemeKeys?: MutableRefObject<Set<string> | null>
|
|
243
|
+
}
|
|
210
244
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
245
|
+
type ThemeStateRef = SnapshotRef & {
|
|
246
|
+
renderVersion: number
|
|
247
|
+
unsubscribe?: () => void
|
|
248
|
+
subscribedParentId?: string
|
|
249
|
+
lastSnap?: ThemeState
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const shouldSubscribeToTheme = (r: ThemeStateRef, cascadeOnChange: boolean): boolean =>
|
|
253
|
+
r.isRoot ||
|
|
254
|
+
cascadeOnChange ||
|
|
255
|
+
hasThemeUpdatingProps(r.props) ||
|
|
256
|
+
!!r.keys.current?.size ||
|
|
257
|
+
!!r.props.needsUpdate?.()
|
|
258
|
+
|
|
259
|
+
function cleanupThemeSubscription(r: ThemeStateRef) {
|
|
260
|
+
r.unsubscribe?.()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function cleanupThemeState(r: ThemeStateRef) {
|
|
264
|
+
if (r.unsubscribe) {
|
|
265
|
+
cleanupThemeSubscription(r)
|
|
266
|
+
} else {
|
|
267
|
+
localStates.delete(r.id)
|
|
268
|
+
states.delete(r.id)
|
|
269
|
+
PendingUpdate.delete(r.id)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const getSnapshotImpl = (r: SnapshotRef): ThemeState => {
|
|
274
|
+
const { id, parentId, props, propsKey, isRoot, keys, schemeKeys } = r
|
|
275
|
+
let local = localStates.get(id)
|
|
276
|
+
const parentState = states.get(parentId)
|
|
277
|
+
|
|
278
|
+
// fast path: nothing changed since last snapshot
|
|
279
|
+
if (local && !PendingUpdate.has(id)) {
|
|
280
|
+
if (
|
|
281
|
+
parentState &&
|
|
282
|
+
(local as any)._parentName === parentState.name &&
|
|
283
|
+
(local as any)._propsKey === propsKey
|
|
284
|
+
) {
|
|
285
|
+
return local
|
|
226
286
|
}
|
|
227
|
-
|
|
228
|
-
HadTheme.set(keys, true)
|
|
229
|
-
}, [keys, propsKey])
|
|
287
|
+
}
|
|
230
288
|
|
|
231
|
-
|
|
289
|
+
// check if this is a scheme-only change (light↔dark) where DynamicColorIOS handles it
|
|
290
|
+
const isSchemeOnlyChange =
|
|
291
|
+
process.env.GUI_TARGET === 'native' &&
|
|
292
|
+
supportsDynamicColorIOS &&
|
|
293
|
+
getSetting('fastSchemeChange') &&
|
|
294
|
+
local &&
|
|
295
|
+
parentState &&
|
|
296
|
+
local.scheme !== parentState.scheme &&
|
|
297
|
+
getThemeBaseName(local.name) === getThemeBaseName(parentState.name)
|
|
298
|
+
|
|
299
|
+
// all tracked keys are scheme-optimized = can skip re-render for scheme changes
|
|
300
|
+
const keysSize = keys?.current?.size ?? 0
|
|
301
|
+
const schemeKeysSize = schemeKeys?.current?.size ?? 0
|
|
302
|
+
const allKeysSchemeOptimized = schemeKeysSize === keysSize && keysSize > 0
|
|
303
|
+
|
|
304
|
+
const canSkipForSchemeChange = isSchemeOnlyChange && allKeysSchemeOptimized
|
|
305
|
+
|
|
306
|
+
const needsUpdate = props.passThrough
|
|
307
|
+
? false
|
|
308
|
+
: isRoot || props.name === 'light' || props.name === 'dark' || props.name === null
|
|
309
|
+
? true
|
|
310
|
+
: !HasRenderedOnce.get(keys)
|
|
311
|
+
? true
|
|
312
|
+
: canSkipForSchemeChange
|
|
313
|
+
? false // skip re-render for scheme-only changes with DynamicColorIOS
|
|
314
|
+
: keys?.current?.size
|
|
315
|
+
? true
|
|
316
|
+
: props.needsUpdate?.()
|
|
317
|
+
|
|
318
|
+
const [rerender, next] = getNextState(
|
|
319
|
+
local,
|
|
320
|
+
props,
|
|
321
|
+
propsKey,
|
|
322
|
+
isRoot,
|
|
323
|
+
id,
|
|
324
|
+
parentId,
|
|
325
|
+
needsUpdate,
|
|
326
|
+
PendingUpdate.get(id)
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
PendingUpdate.delete(id)
|
|
330
|
+
|
|
331
|
+
// we always create a new localState for every component
|
|
332
|
+
// that way we can use it to de-opt and avoid renders granularly
|
|
333
|
+
// we always return the localState object in each component
|
|
334
|
+
// the global state (states) should always be up to date with the latest
|
|
335
|
+
if (!local || rerender) {
|
|
336
|
+
local = { ...next }
|
|
337
|
+
localStates.set(id, local)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (process.env.NODE_ENV === 'development' && props.debug === 'verbose') {
|
|
341
|
+
console.groupCollapsed(` ${id} getSnapshot ${rerender}`, local.name, '>', next.name)
|
|
342
|
+
console.info({
|
|
343
|
+
props,
|
|
344
|
+
propsKey,
|
|
345
|
+
isRoot,
|
|
346
|
+
parentId,
|
|
347
|
+
local,
|
|
348
|
+
next,
|
|
349
|
+
needsUpdate,
|
|
350
|
+
isSchemeOnlyChange,
|
|
351
|
+
allKeysSchemeOptimized,
|
|
352
|
+
canSkipForSchemeChange,
|
|
353
|
+
})
|
|
354
|
+
console.groupEnd()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (next !== local) {
|
|
358
|
+
Object.assign(local, next)
|
|
359
|
+
local.id = id
|
|
360
|
+
}
|
|
361
|
+
;(local as any)._parentName = parentState?.name
|
|
362
|
+
;(local as any)._propsKey = propsKey
|
|
363
|
+
states.set(id, next)
|
|
364
|
+
|
|
365
|
+
return local
|
|
232
366
|
}
|
|
233
367
|
|
|
234
368
|
const getNextState = (
|
|
@@ -285,20 +419,25 @@ const getNextState = (
|
|
|
285
419
|
}
|
|
286
420
|
|
|
287
421
|
if (!name) {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
422
|
+
// parentState can be transiently missing when a consumer renders in a
|
|
423
|
+
// separate sync flush (a portal/Toast viewport, or a native multi-root
|
|
424
|
+
// surface) before its provider has populated the module-level `states` map.
|
|
425
|
+
// that's recoverable — the next render resolves it — so fall back to the
|
|
426
|
+
// root theme (or a light stub) instead of throwing. the "no parent context"
|
|
427
|
+
// throw above still catches a genuinely missing provider. going back to
|
|
428
|
+
// useSyncExternalStore would avoid the race but force every themed node out
|
|
429
|
+
// of concurrent rendering, so we keep the manual store and tolerate the
|
|
430
|
+
// ordering here.
|
|
431
|
+
const next = lastState ??
|
|
432
|
+
parentState ??
|
|
433
|
+
rootThemeState ?? {
|
|
434
|
+
id,
|
|
435
|
+
name: 'light',
|
|
436
|
+
theme: getConfig().themes.light,
|
|
437
|
+
}
|
|
299
438
|
|
|
300
439
|
if (shouldRerender) {
|
|
301
|
-
const updated = { ...(parentState || lastState)! }
|
|
440
|
+
const updated = { ...(parentState || lastState || next)! }
|
|
302
441
|
return [true, updated]
|
|
303
442
|
}
|
|
304
443
|
|
|
@@ -306,9 +445,12 @@ Looked for theme${props.name ? ` "${props.name}"` : ''}${props.componentName ? `
|
|
|
306
445
|
}
|
|
307
446
|
|
|
308
447
|
const scheme = getScheme(name)
|
|
309
|
-
|
|
448
|
+
const parentInverses = parentState?.inverses ?? 0
|
|
310
449
|
const isInverse = parentState && scheme !== parentState.scheme
|
|
311
|
-
//
|
|
450
|
+
// cumulative from the root: once any level flips scheme, every descendant is
|
|
451
|
+
// considered inverted vs the OS, even sub-themes that match their immediate
|
|
452
|
+
// parent (dark_blue under dark). gates the DynamicColorIOS optimization below.
|
|
453
|
+
const inverses = parentInverses + (isInverse ? 1 : 0)
|
|
312
454
|
|
|
313
455
|
const nextState = {
|
|
314
456
|
id,
|
|
@@ -317,7 +459,7 @@ Looked for theme${props.name ? ` "${props.name}"` : ''}${props.componentName ? `
|
|
|
317
459
|
scheme,
|
|
318
460
|
parentId,
|
|
319
461
|
parentName: parentState?.name,
|
|
320
|
-
|
|
462
|
+
inverses,
|
|
321
463
|
isInverse,
|
|
322
464
|
isNew: true,
|
|
323
465
|
} satisfies ThemeState
|
package/src/index.ts
CHANGED
|
@@ -56,6 +56,7 @@ export * from './interfaces/GetRef'
|
|
|
56
56
|
export {
|
|
57
57
|
getConfig,
|
|
58
58
|
getSetting,
|
|
59
|
+
getStyleCompat,
|
|
59
60
|
getThemes,
|
|
60
61
|
getToken,
|
|
61
62
|
getTokens,
|
|
@@ -64,6 +65,7 @@ export {
|
|
|
64
65
|
setConfig,
|
|
65
66
|
setupDev,
|
|
66
67
|
updateConfig,
|
|
68
|
+
type StyleCompat,
|
|
67
69
|
} from './config'
|
|
68
70
|
|
|
69
71
|
export { setNonce } from './helpers/insertStyleRule'
|
|
@@ -75,10 +77,16 @@ export {
|
|
|
75
77
|
_disableMediaTouch,
|
|
76
78
|
configureMedia,
|
|
77
79
|
mediaKeyMatch,
|
|
80
|
+
updateMediaListeners,
|
|
78
81
|
useMedia,
|
|
79
82
|
} from './hooks/useMedia'
|
|
80
83
|
export { mediaObjectToString } from './helpers/mediaObjectToString'
|
|
81
|
-
export {
|
|
84
|
+
export {
|
|
85
|
+
getMedia,
|
|
86
|
+
mediaQueryConfig,
|
|
87
|
+
mediaState,
|
|
88
|
+
setMediaState,
|
|
89
|
+
} from './helpers/mediaState'
|
|
82
90
|
export * from './hooks/useProps'
|
|
83
91
|
export * from './hooks/useTheme'
|
|
84
92
|
export * from './hooks/useThemeName'
|
|
@@ -68,13 +68,13 @@ export type GuiComponentPropsBaseBase = {
|
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* Marks this component as a group for use in styling children based on parents named group
|
|
71
|
-
* See: https://
|
|
71
|
+
* See: https://hanzogui.dev/docs/intro/props
|
|
72
72
|
*/
|
|
73
73
|
group?: GroupNames | boolean
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Works only alongside group, when children of the group are using container based sizing on native you can hide them until parent is measured.
|
|
77
|
-
* See: https://
|
|
77
|
+
* See: https://hanzogui.dev/docs/intro/props
|
|
78
78
|
*/
|
|
79
79
|
untilMeasured?: 'hide' | 'show'
|
|
80
80
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* type tests for the opacity modifier syntax (e.g., $color/50)
|
|
3
|
+
*
|
|
4
|
+
* the runtime already supports this syntax in getTokenForKey, but the types
|
|
5
|
+
* were not accepting it. these tests verify that color tokens with opacity
|
|
6
|
+
* modifiers are now type-safe.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { expectTypeOf, describe, test } from 'vitest'
|
|
10
|
+
import type { ColorTokens, FontColorTokens, GetThemeValueForKey } from './types'
|
|
11
|
+
|
|
12
|
+
type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
|
13
|
+
type ColorTokenKey = `color${Digit}${Digit}${Digit}`
|
|
14
|
+
|
|
15
|
+
describe('opacity modifier types', () => {
|
|
16
|
+
test('ColorTokens accepts opacity modifier syntax', () => {
|
|
17
|
+
// should accept token with opacity modifier
|
|
18
|
+
const colorWithOpacity: ColorTokens = '$color/50'
|
|
19
|
+
const colorWithFullOpacity: ColorTokens = '$color/100'
|
|
20
|
+
const colorWithLowOpacity: ColorTokens = '$color/10'
|
|
21
|
+
|
|
22
|
+
// should still accept regular tokens
|
|
23
|
+
const regularToken: ColorTokens = '$color'
|
|
24
|
+
const colorName: ColorTokens = 'red'
|
|
25
|
+
|
|
26
|
+
expectTypeOf(colorWithOpacity).toMatchTypeOf<ColorTokens>()
|
|
27
|
+
expectTypeOf(colorWithFullOpacity).toMatchTypeOf<ColorTokens>()
|
|
28
|
+
expectTypeOf(colorWithLowOpacity).toMatchTypeOf<ColorTokens>()
|
|
29
|
+
expectTypeOf(regularToken).toMatchTypeOf<ColorTokens>()
|
|
30
|
+
expectTypeOf(colorName).toMatchTypeOf<ColorTokens>()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test('FontColorTokens accepts opacity modifier syntax', () => {
|
|
34
|
+
const fontColorNumber: FontColorTokens = 42
|
|
35
|
+
const fontColorWithOpacity: FontColorTokens = '$bodyColor/50'
|
|
36
|
+
|
|
37
|
+
expectTypeOf(fontColorNumber).toMatchTypeOf<FontColorTokens>()
|
|
38
|
+
expectTypeOf(fontColorWithOpacity).toMatchTypeOf<FontColorTokens>()
|
|
39
|
+
expectTypeOf<number>().toMatchTypeOf<FontColorTokens>()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
test('opacity modifier requires token prefix', () => {
|
|
43
|
+
const validOpacity: ColorTokens = '$color/75'
|
|
44
|
+
expectTypeOf(validOpacity).toMatchTypeOf<ColorTokens>()
|
|
45
|
+
|
|
46
|
+
// @ts-expect-error opacity modifiers only apply to token-like values.
|
|
47
|
+
const cssColorWithOpacity: ColorTokens = 'red/75'
|
|
48
|
+
expectTypeOf(cssColorWithOpacity).toMatchTypeOf<ColorTokens>()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('color props accept opacity without expanding large token unions', () => {
|
|
52
|
+
type LargeColorTokens = `$${ColorTokenKey}` | ColorTokens
|
|
53
|
+
|
|
54
|
+
const colorToken: LargeColorTokens = '$color123'
|
|
55
|
+
const colorTokenWithOpacity: LargeColorTokens = '$color123/50'
|
|
56
|
+
const propColorTokenWithOpacity: GetThemeValueForKey<'backgroundColor'> =
|
|
57
|
+
'$color123/50'
|
|
58
|
+
|
|
59
|
+
expectTypeOf(colorToken).toMatchTypeOf<LargeColorTokens>()
|
|
60
|
+
expectTypeOf(colorTokenWithOpacity).toMatchTypeOf<LargeColorTokens>()
|
|
61
|
+
expectTypeOf(propColorTokenWithOpacity).toMatchTypeOf<
|
|
62
|
+
GetThemeValueForKey<'backgroundColor'>
|
|
63
|
+
>()
|
|
64
|
+
})
|
|
65
|
+
})
|