1
- import type { App , ComputedRef , InjectionKey , Ref } from 'vue' ;
2
- import { provide , defineComponent , unref , computed , inject } from 'vue' ;
1
+ import type { ShallowRef , ExtractPropTypes , InjectionKey , Ref } from 'vue' ;
2
+ import { provide , defineComponent , unref , inject , watch , shallowRef } from 'vue' ;
3
3
import CacheEntity from './Cache' ;
4
4
import type { Linter } from './linters/interface' ;
5
5
import type { Transformer } from './transformers/interface' ;
6
- import { arrayType , objectType } from '../type' ;
7
- import PropTypes from '../vue-types' ;
6
+ import { arrayType , booleanType , objectType , someType , stringType , withInstall } from '../type' ;
8
7
import initDefaultProps from '../props-util/initDefaultProps' ;
9
8
export const ATTR_TOKEN = 'data-token-hash' ;
10
9
export const ATTR_MARK = 'data-css-hash' ;
@@ -73,61 +72,62 @@ export interface StyleContextProps {
73
72
linters ?: Linter [ ] ;
74
73
}
75
74
76
- const StyleContextKey : InjectionKey < ComputedRef < Partial < StyleContextProps > > > =
75
+ const StyleContextKey : InjectionKey < ShallowRef < Partial < StyleContextProps > > > =
77
76
Symbol ( 'StyleContextKey' ) ;
78
77
79
- export type StyleProviderProps = Partial < StyleContextProps > | Ref < Partial < StyleContextProps > > ;
78
+ export type UseStyleProviderProps = Partial < StyleContextProps > | Ref < Partial < StyleContextProps > > ;
80
79
const defaultStyleContext : StyleContextProps = {
81
80
cache : createCache ( ) ,
82
81
defaultCache : true ,
83
82
hashPriority : 'low' ,
84
83
} ;
85
84
export const useStyleInject = ( ) => {
86
- return inject (
87
- StyleContextKey ,
88
- computed ( ( ) => defaultStyleContext ) ,
89
- ) ;
85
+ return inject ( StyleContextKey , shallowRef ( { ...defaultStyleContext } ) ) ;
90
86
} ;
91
- export const useStyleProvider = ( props : StyleProviderProps ) => {
87
+ export const useStyleProvider = ( props : UseStyleProviderProps ) => {
92
88
const parentContext = useStyleInject ( ) ;
89
+ const context = shallowRef < Partial < StyleContextProps > > ( { ...defaultStyleContext } ) ;
90
+ watch (
91
+ [ props , parentContext ] ,
92
+ ( ) => {
93
+ const mergedContext : Partial < StyleContextProps > = {
94
+ ...parentContext . value ,
95
+ } ;
96
+ const propsValue = unref ( props ) ;
97
+ Object . keys ( propsValue ) . forEach ( key => {
98
+ const value = propsValue [ key ] ;
99
+ if ( propsValue [ key ] !== undefined ) {
100
+ mergedContext [ key ] = value ;
101
+ }
102
+ } ) ;
93
103
94
- const context = computed < Partial < StyleContextProps > > ( ( ) => {
95
- const mergedContext : Partial < StyleContextProps > = {
96
- ...parentContext . value ,
97
- } ;
98
- const propsValue = unref ( props ) ;
99
- Object . keys ( propsValue ) . forEach ( key => {
100
- const value = propsValue [ key ] ;
101
- if ( propsValue [ key ] !== undefined ) {
102
- mergedContext [ key ] = value ;
103
- }
104
- } ) ;
105
-
106
- const { cache } = propsValue ;
107
- mergedContext . cache = mergedContext . cache || createCache ( ) ;
108
- mergedContext . defaultCache = ! cache && parentContext . value . defaultCache ;
109
- return mergedContext ;
110
- } ) ;
104
+ const { cache } = propsValue ;
105
+ mergedContext . cache = mergedContext . cache || createCache ( ) ;
106
+ mergedContext . defaultCache = ! cache && parentContext . value . defaultCache ;
107
+ context . value = mergedContext ;
108
+ } ,
109
+ { immediate : true } ,
110
+ ) ;
111
111
provide ( StyleContextKey , context ) ;
112
112
return context ;
113
113
} ;
114
- const AStyleProviderProps = ( ) => ( {
115
- autoClear : PropTypes . bool ,
114
+ export const styleProviderProps = ( ) => ( {
115
+ autoClear : booleanType ( ) ,
116
116
/** @private Test only. Not work in production. */
117
- mock : PropTypes . oneOf ( [ 'server' , 'client' ] as const ) ,
117
+ mock : stringType < 'server' | 'client' > ( ) ,
118
118
/**
119
119
* Only set when you need ssr to extract style on you own.
120
120
* If not provided, it will auto create <style /> on the end of Provider in server side.
121
121
*/
122
122
cache : objectType < CacheEntity > ( ) ,
123
123
/** Tell children that this context is default generated context */
124
- defaultCache : PropTypes . bool ,
124
+ defaultCache : booleanType ( ) ,
125
125
/** Use `:where` selector to reduce hashId css selector priority */
126
- hashPriority : PropTypes . oneOf ( [ 'low' , 'high' ] as const ) ,
126
+ hashPriority : stringType < HashPriority > ( ) ,
127
127
/** Tell cssinjs where to inject style in */
128
- container : PropTypes . oneOfType ( [ objectType < Element > ( ) , objectType < ShadowRoot > ( ) ] ) ,
128
+ container : someType < Element | ShadowRoot > ( ) ,
129
129
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
130
- ssrInline : PropTypes . bool ,
130
+ ssrInline : booleanType ( ) ,
131
131
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
132
132
transformers : arrayType < Transformer [ ] > ( ) ,
133
133
/**
@@ -137,20 +137,21 @@ const AStyleProviderProps = () => ({
137
137
*/
138
138
linters : arrayType < Linter [ ] > ( ) ,
139
139
} ) ;
140
+ export type StyleProviderProps = Partial < ExtractPropTypes < ReturnType < typeof styleProviderProps > > > ;
141
+ export const StyleProvider = withInstall (
142
+ defineComponent ( {
143
+ name : 'AStyleProvider' ,
144
+ inheritAttrs : false ,
145
+ props : initDefaultProps ( styleProviderProps ( ) , defaultStyleContext ) ,
146
+ setup ( props , { slots } ) {
147
+ useStyleProvider ( props ) ;
148
+ return ( ) => slots . default ?.( ) ;
149
+ } ,
150
+ } ) ,
151
+ ) ;
140
152
141
- export const StyleProvider = defineComponent ( {
142
- name : 'AStyleProvider' ,
143
- props : initDefaultProps ( AStyleProviderProps ( ) , defaultStyleContext ) ,
144
- setup ( props , { slots } ) {
145
- useStyleProvider ( props ) ;
146
- return ( ) => slots . default ?.( ) ;
147
- } ,
148
- } ) ;
149
-
150
- StyleProvider . install = function ( app : App ) {
151
- app . component ( StyleProvider . name , StyleProvider ) ;
152
- } ;
153
153
export default {
154
154
useStyleInject,
155
155
useStyleProvider,
156
+ StyleProvider,
156
157
} ;
0 commit comments