UNPKG

@dark-engine/core

Version:

The lightweight and powerful UI rendering engine without dependencies and written in TypeScript (Browser, Node.js, Android, iOS, Windows, Linux, macOS)

60 lines (59 loc) 1.96 kB
import { component } from '../component'; import { useLayoutEffect } from '../use-layout-effect'; import { __useCursor as useCursor } from '../internal'; import { EventEmitter } from '../emitter'; import { useUpdate } from '../use-update'; import { detectIsEqual } from '../utils'; import { useMemo } from '../use-memo'; function createContext(defaultValue, options) { const { displayName = 'Component' } = options || {}; const context = component( ({ value = defaultValue, slot }) => { const cursor = useCursor(); const { hook } = cursor; let providers = hook.getProviders(); if (!providers) { providers = new Map(); providers.set(context, { value, emitter: new EventEmitter() }); hook.setProviders(providers); } const provider = providers.get(context); useLayoutEffect(() => { provider.emitter.emit('publish', value); }, [value]); provider.value = value; return slot; }, { displayName: `Context(${displayName})` }, ); context.defaultValue = defaultValue; Object.freeze(context); return context; } function useContext(context) { const { defaultValue } = context; const cursor = useCursor(); const scope = useMemo(() => ({ value: null, provider: getProvider(context, cursor) }), []); const update = useUpdate(); const { provider } = scope; const value = provider ? provider.value : defaultValue; useLayoutEffect(() => { if (!provider) return; return provider.emitter.on('publish', value => { !detectIsEqual(scope.value, value) && update(); }); }, []); scope.value = value; return value; } function getProvider(context, fiber) { let $fiber = fiber; while ($fiber) { const providers = $fiber.hook?.getProviders(); if (providers?.has(context)) return providers.get(context); $fiber = $fiber.parent; } return null; } export { createContext, useContext }; //# sourceMappingURL=context.js.map