mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-12 19:57:37 +00:00
c8a54a988b
- Replace catch (error: any) with catch (error) + (error as Error).message cast in EditorLayout, NodeManager, HomeDashboard, AppStoreView - Define TemplateVolume interface in AppStoreView; replace volumes any[] with typed array - Define MetricPoint interface in HomeDashboard; replace metrics any[] with MetricPoint[] - Define TerminalContainer type in BashExecModal; replace as any DOM property casts - Define NodeTestInfo interface in NodeManager; replace info: any with typed shape - Fix DockerNetworkStats cast in EditorLayout container stats WebSocket handler - Remove unused catch variable (e) in api.ts and other components - Cast streamFilter onValueChange val to union type in GlobalObservabilityView - Add eslint-disable-next-line react-refresh/only-export-components to badge.tsx, button.tsx, AuthContext, NodeContext, use-data-state, use-is-in-view - Add eslint-disable-next-line react-hooks/set-state-in-effect in LogViewer - Add /* eslint-disable */ to animate-ui third-party primitive files
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
|
|
type DataStateValue = string | boolean | null;
|
|
|
|
function parseDatasetValue(value: string | null): DataStateValue {
|
|
if (value === null) return null;
|
|
if (value === '' || value === 'true') return true;
|
|
if (value === 'false') return false;
|
|
return value;
|
|
}
|
|
|
|
function useDataState<T extends HTMLElement = HTMLElement>(
|
|
key: string,
|
|
forwardedRef?: React.Ref<T | null>,
|
|
onChange?: (value: DataStateValue) => void,
|
|
): [DataStateValue, React.RefObject<T | null>] {
|
|
const localRef = React.useRef<T | null>(null);
|
|
React.useImperativeHandle(forwardedRef, () => localRef.current as T);
|
|
|
|
const getSnapshot = (): DataStateValue => {
|
|
const el = localRef.current;
|
|
return el ? parseDatasetValue(el.getAttribute(`data-${key}`)) : null;
|
|
};
|
|
|
|
const subscribe = (callback: () => void) => {
|
|
const el = localRef.current;
|
|
if (!el) return () => {};
|
|
const observer = new MutationObserver((records) => {
|
|
for (const record of records) {
|
|
if (record.attributeName === `data-${key}`) {
|
|
callback();
|
|
break;
|
|
}
|
|
}
|
|
});
|
|
observer.observe(el, {
|
|
attributes: true,
|
|
attributeFilter: [`data-${key}`],
|
|
});
|
|
return () => observer.disconnect();
|
|
};
|
|
|
|
const value = React.useSyncExternalStore(subscribe, getSnapshot);
|
|
|
|
React.useEffect(() => {
|
|
if (onChange) onChange(value);
|
|
}, [value, onChange]);
|
|
|
|
return [value, localRef];
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export { useDataState, type DataStateValue };
|