36 lines
1.2 KiB
TypeScript
36 lines
1.2 KiB
TypeScript
|
|
import React, { createContext, useContext, useMemo } from 'react';
|
||
|
|
import type { Shade } from '@shade/sdk';
|
||
|
|
import type { FilesNamespace } from '../integration/files-namespace.js';
|
||
|
|
|
||
|
|
export interface ShadeFilesContextValue {
|
||
|
|
shade: Shade;
|
||
|
|
files: FilesNamespace;
|
||
|
|
}
|
||
|
|
|
||
|
|
const ShadeFilesContext = createContext<ShadeFilesContextValue | null>(null);
|
||
|
|
|
||
|
|
export interface ShadeFilesProviderProps {
|
||
|
|
/** Initialized `Shade` instance. `files` namespace is read off it lazily. */
|
||
|
|
shade: Shade;
|
||
|
|
children: React.ReactNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Provider for `@shade/files` React hooks. Distinct from
|
||
|
|
* `<ShadeRuntimeProvider>` in `@shade/widgets` so file-RPC consumers
|
||
|
|
* don't pull in the widget tree.
|
||
|
|
*/
|
||
|
|
export function ShadeFilesProvider({ shade, children }: ShadeFilesProviderProps): React.ReactElement {
|
||
|
|
const value = useMemo<ShadeFilesContextValue>(() => ({ shade, files: shade.files }), [shade]);
|
||
|
|
return React.createElement(ShadeFilesContext.Provider, { value }, children);
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Throws if no `<ShadeFilesProvider>` is mounted above. */
|
||
|
|
export function useShadeFilesContext(): ShadeFilesContextValue {
|
||
|
|
const ctx = useContext(ShadeFilesContext);
|
||
|
|
if (ctx === null) {
|
||
|
|
throw new Error('useShadeFilesContext: missing <ShadeFilesProvider>');
|
||
|
|
}
|
||
|
|
return ctx;
|
||
|
|
}
|