mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(monorepo): migrate prototype code to organized package structure
Migrate all prototype code from vjs10-prototype repository into the monorepo structure following established dependency hierarchy and package organization patterns. Core packages migrated: - @vjs-10/media-store: Complete media store with nanostores integration - @vjs-10/playback-engine: HLS.js playback engine implementation - @vjs-10/media: Core media state owner and interfaces HTML packages migrated: - @vjs-10/html-icons: Web component icons with proper base classes - @vjs-10/html-media-elements: Context provider integration - @vjs-10/html: Main HTML UI components, skins, and utilities React packages migrated: - @vjs-10/react-icons: React icon components - @vjs-10/react-media-elements: Video component with state integration - @vjs-10/react-media-store: MediaProvider and React hooks - @vjs-10/react: Main React UI components and skins Changes made: - Updated all imports to use monorepo package names (@vjs-10/*) - Distributed dependencies to specific packages that use them - Preserved all prototype functionality and component structure - Created proper index files for all packages - Fixed workspace protocol usage for npm compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
fc5a0e46fd
commit
4b472ec49c
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
import {
|
||||
useRef,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useDebugValue,
|
||||
useSyncExternalStore,
|
||||
} from 'react';
|
||||
|
||||
// NOTE: This is a port of https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreWithSelector.js
|
||||
// and React's internal/shared version of `Object.is` with refactors for TypeScript and bundling. Doing this to avoid adding an additional dependency
|
||||
// beyond core React when using the `MediaStore` React hooks and related (CJP)
|
||||
|
||||
/**
|
||||
* inlined Object.is polyfill to avoid requiring consumers ship their own
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
|
||||
*/
|
||||
function isPolyfill(x: any, y: any) {
|
||||
return (
|
||||
(x === y && (x !== 0 || 1 / x === 1 / y)) || (x !== x && y !== y) // eslint-disable-line no-self-compare
|
||||
);
|
||||
}
|
||||
|
||||
type SnapshotRef<Selection> =
|
||||
| {
|
||||
hasValue: true;
|
||||
value: Selection;
|
||||
}
|
||||
| {
|
||||
hasValue: false;
|
||||
value: null;
|
||||
}
|
||||
| null;
|
||||
|
||||
const is: (x: any, y: any) => boolean =
|
||||
typeof Object.is === 'function' ? Object.is : isPolyfill;
|
||||
|
||||
// Same as useSyncExternalStore, but supports selector and isEqual arguments.
|
||||
export function useSyncExternalStoreWithSelector<Snapshot, Selection>(
|
||||
subscribe: (onStoreChange: () => void) => () => void,
|
||||
getSnapshot: () => Snapshot,
|
||||
getServerSnapshot: undefined | null | (() => Snapshot),
|
||||
selector: (snapshot: Snapshot) => Selection,
|
||||
isEqual?: (a: Selection, b: Selection) => boolean
|
||||
) {
|
||||
// Use this to track the rendered snapshot.
|
||||
const instRef = useRef<SnapshotRef<Selection>>(null);
|
||||
let inst: SnapshotRef<Selection>;
|
||||
if (instRef.current === null) {
|
||||
inst = {
|
||||
hasValue: false,
|
||||
value: null,
|
||||
};
|
||||
instRef.current = inst as SnapshotRef<Selection>;
|
||||
} else {
|
||||
inst = instRef.current;
|
||||
}
|
||||
|
||||
const [getSelection, getServerSelection] = useMemo(() => {
|
||||
// Track the memoized state using closure variables that are local to this
|
||||
// memoized instance of a getSnapshot function. Intentionally not using a
|
||||
// useRef hook, because that state would be shared across all concurrent
|
||||
// copies of the hook/component.
|
||||
let hasMemo = false;
|
||||
let memoizedSnapshot;
|
||||
let memoizedSelection: Selection;
|
||||
const memoizedSelector = (nextSnapshot: Snapshot) => {
|
||||
if (!hasMemo) {
|
||||
// The first time the hook is called, there is no memoized result.
|
||||
hasMemo = true;
|
||||
memoizedSnapshot = nextSnapshot;
|
||||
const nextSelection = selector(nextSnapshot);
|
||||
if (isEqual !== undefined) {
|
||||
// Even if the selector has changed, the currently rendered selection
|
||||
// may be equal to the new selection. We should attempt to reuse the
|
||||
// current value if possible, to preserve downstream memoizations.
|
||||
if (inst.hasValue) {
|
||||
const currentSelection = inst.value;
|
||||
if (isEqual(currentSelection, nextSelection)) {
|
||||
memoizedSelection = currentSelection;
|
||||
return currentSelection;
|
||||
}
|
||||
}
|
||||
}
|
||||
memoizedSelection = nextSelection;
|
||||
return nextSelection;
|
||||
}
|
||||
|
||||
// We may be able to reuse the previous invocation's result.
|
||||
const prevSnapshot: Snapshot = memoizedSnapshot;
|
||||
const prevSelection: Selection = memoizedSelection;
|
||||
|
||||
if (is(prevSnapshot, nextSnapshot)) {
|
||||
// The snapshot is the same as last time. Reuse the previous selection.
|
||||
return prevSelection;
|
||||
}
|
||||
|
||||
// The snapshot has changed, so we need to compute a new selection.
|
||||
const nextSelection = selector(nextSnapshot);
|
||||
|
||||
// If a custom isEqual function is provided, use that to check if the data
|
||||
// has changed. If it hasn't, return the previous selection. That signals
|
||||
// to React that the selections are conceptually equal, and we can bail
|
||||
// out of rendering.
|
||||
if (isEqual !== undefined && isEqual(prevSelection, nextSelection)) {
|
||||
return prevSelection;
|
||||
}
|
||||
|
||||
memoizedSnapshot = nextSnapshot;
|
||||
memoizedSelection = nextSelection;
|
||||
return nextSelection;
|
||||
};
|
||||
// Assigning this to a constant so that Flow knows it can't change.
|
||||
const maybeGetServerSnapshot =
|
||||
getServerSnapshot === undefined ? null : getServerSnapshot;
|
||||
const getSnapshotWithSelector = () => memoizedSelector(getSnapshot());
|
||||
const getServerSnapshotWithSelector =
|
||||
maybeGetServerSnapshot === null
|
||||
? undefined
|
||||
: () => memoizedSelector(maybeGetServerSnapshot());
|
||||
return [getSnapshotWithSelector, getServerSnapshotWithSelector];
|
||||
}, [getSnapshot, getServerSnapshot, selector, isEqual]);
|
||||
|
||||
const value = useSyncExternalStore(
|
||||
subscribe,
|
||||
getSelection,
|
||||
getServerSelection
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
inst.hasValue = true;
|
||||
inst.value = value;
|
||||
}, [value]);
|
||||
|
||||
useDebugValue(value);
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user