@aplus-frontend/antdv
Version:
Vue basic component library maintained based on ant-design-vue
147 lines • 5.25 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { provide, defineComponent, unref, inject, watch, shallowRef, getCurrentInstance } from 'vue';
import CacheEntity from './Cache';
import { arrayType, booleanType, objectType, someType, stringType, withInstall } from '../type';
export const ATTR_TOKEN = 'data-token-hash';
export const ATTR_MARK = 'data-css-hash';
export const ATTR_CACHE_PATH = 'data-cache-path';
// Mark css-in-js instance in style element
export const CSS_IN_JS_INSTANCE = '__cssinjs_instance__';
export function createCache() {
const cssinjsInstanceId = Math.random().toString(12).slice(2);
// Tricky SSR: Move all inline style to the head.
// PS: We do not recommend tricky mode.
if (typeof document !== 'undefined' && document.head && document.body) {
const styles = document.body.querySelectorAll(`style[${ATTR_MARK}]`) || [];
const {
firstChild
} = document.head;
Array.from(styles).forEach(style => {
style[CSS_IN_JS_INSTANCE] = style[CSS_IN_JS_INSTANCE] || cssinjsInstanceId;
// Not force move if no head
// Not force move if no head
if (style[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
document.head.insertBefore(style, firstChild);
}
});
// Deduplicate of moved styles
const styleHash = {};
Array.from(document.querySelectorAll(`style[${ATTR_MARK}]`)).forEach(style => {
var _a;
const hash = style.getAttribute(ATTR_MARK);
if (styleHash[hash]) {
if (style[CSS_IN_JS_INSTANCE] === cssinjsInstanceId) {
(_a = style.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(style);
}
} else {
styleHash[hash] = true;
}
});
}
return new CacheEntity(cssinjsInstanceId);
}
const StyleContextKey = Symbol('StyleContextKey');
// fix: https://github.com/vueComponent/ant-design-vue/issues/7023
const getCache = () => {
var _a, _b, _c;
const instance = getCurrentInstance();
let cache;
if (instance && instance.appContext) {
const globalCache = (_c = (_b = (_a = instance.appContext) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.globalProperties) === null || _c === void 0 ? void 0 : _c.__ANTDV_CSSINJS_CACHE__;
if (globalCache) {
cache = globalCache;
} else {
cache = createCache();
if (instance.appContext.config.globalProperties) {
instance.appContext.config.globalProperties.__ANTDV_CSSINJS_CACHE__ = cache;
}
}
} else {
cache = createCache();
}
return cache;
};
const defaultStyleContext = {
cache: createCache(),
defaultCache: true,
hashPriority: 'low'
};
// fix: https://github.com/vueComponent/ant-design-vue/issues/6912
export const useStyleInject = () => {
const cache = getCache();
return inject(StyleContextKey, shallowRef(_extends(_extends({}, defaultStyleContext), {
cache
})));
};
export const useStyleProvider = props => {
const parentContext = useStyleInject();
const context = shallowRef(_extends(_extends({}, defaultStyleContext), {
cache: createCache()
}));
watch([() => unref(props), parentContext], () => {
const mergedContext = _extends({}, parentContext.value);
const propsValue = unref(props);
Object.keys(propsValue).forEach(key => {
const value = propsValue[key];
if (propsValue[key] !== undefined) {
mergedContext[key] = value;
}
});
const {
cache
} = propsValue;
mergedContext.cache = mergedContext.cache || createCache();
mergedContext.defaultCache = !cache && parentContext.value.defaultCache;
context.value = mergedContext;
}, {
immediate: true
});
provide(StyleContextKey, context);
return context;
};
export const styleProviderProps = () => ({
autoClear: booleanType(),
/** @private Test only. Not work in production. */
mock: stringType(),
/**
* Only set when you need ssr to extract style on you own.
* If not provided, it will auto create <style /> on the end of Provider in server side.
*/
cache: objectType(),
/** Tell children that this context is default generated context */
defaultCache: booleanType(),
/** Use `:where` selector to reduce hashId css selector priority */
hashPriority: stringType(),
/** Tell cssinjs where to inject style in */
container: someType(),
/** Component wil render inline `<style />` for fallback in SSR. Not recommend. */
ssrInline: booleanType(),
/** Transform css before inject in document. Please note that `transformers` do not support dynamic update */
transformers: arrayType(),
/**
* Linters to lint css before inject in document.
* Styles will be linted after transforming.
* Please note that `linters` do not support dynamic update.
*/
linters: arrayType()
});
export const StyleProvider = withInstall(defineComponent({
name: 'AStyleProvider',
inheritAttrs: false,
props: styleProviderProps(),
setup(props, _ref) {
let {
slots
} = _ref;
useStyleProvider(props);
return () => {
var _a;
return (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots);
};
}
}));
export default {
useStyleInject,
useStyleProvider,
StyleProvider
};