@gram-ai/elements 1.24.2 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/README.typedoc.md +14 -0
- package/dist/compat-plugin.cjs +2 -0
- package/dist/compat-plugin.cjs.map +1 -0
- package/dist/compat-plugin.d.ts +3 -0
- package/dist/compat-plugin.js +26 -0
- package/dist/compat-plugin.js.map +1 -0
- package/dist/compat-shims-BPJ7Q68c.js +38 -0
- package/dist/compat-shims-BPJ7Q68c.js.map +1 -0
- package/dist/compat-shims-CO9JXXV4.cjs +2 -0
- package/dist/compat-shims-CO9JXXV4.cjs.map +1 -0
- package/dist/compat-shims.d.ts +27 -0
- package/dist/compat.d.ts +8 -0
- package/dist/compat.test.d.ts +0 -0
- package/dist/elements.cjs +1 -1
- package/dist/elements.js +1 -1
- package/dist/{index-B9hEyUXQ.js → index-DDb23655.js} +4582 -4578
- package/dist/index-DDb23655.js.map +1 -0
- package/dist/{index-EMjYCXA1.cjs → index-wBHCO1r-.cjs} +50 -50
- package/dist/index-wBHCO1r-.cjs.map +1 -0
- package/dist/{profiler-DFrzs1Rd.js → profiler-CGIJBY8c.js} +2 -2
- package/dist/{profiler-DFrzs1Rd.js.map → profiler-CGIJBY8c.js.map} +1 -1
- package/dist/{profiler-DUyotQcs.cjs → profiler-CLtQEzfv.cjs} +2 -2
- package/dist/{profiler-DUyotQcs.cjs.map → profiler-CLtQEzfv.cjs.map} +1 -1
- package/dist/react-shim.cjs +2 -0
- package/dist/react-shim.cjs.map +1 -0
- package/dist/react-shim.d.ts +9 -0
- package/dist/react-shim.js +78 -0
- package/dist/react-shim.js.map +1 -0
- package/dist/{startRecording-CbzZg6Ct.cjs → startRecording-DXZPNn9e.cjs} +2 -2
- package/dist/{startRecording-CbzZg6Ct.cjs.map → startRecording-DXZPNn9e.cjs.map} +1 -1
- package/dist/{startRecording-CNklkzCM.js → startRecording-x0G7lOpP.js} +2 -2
- package/dist/{startRecording-CNklkzCM.js.map → startRecording-x0G7lOpP.js.map} +1 -1
- package/package.json +10 -5
- package/src/compat-plugin.ts +38 -0
- package/src/compat-shims.ts +75 -0
- package/src/compat.test.ts +80 -0
- package/src/compat.ts +19 -0
- package/src/index.ts +3 -0
- package/src/react-shim.ts +54 -0
- package/dist/index-B9hEyUXQ.js.map +0 -1
- package/dist/index-EMjYCXA1.cjs.map +0 -1
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polyfill factories for React 18 APIs. Shared by compat.ts (runtime patching)
|
|
3
|
+
* and react-shim.ts (bundler-level replacement). This module must NOT import
|
|
4
|
+
* from 'react' to avoid circular dependencies when the Vite plugin is active.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
interface ReactLike {
|
|
8
|
+
useState: typeof import('react').useState
|
|
9
|
+
useEffect: typeof import('react').useEffect
|
|
10
|
+
useLayoutEffect: typeof import('react').useLayoutEffect
|
|
11
|
+
useRef: typeof import('react').useRef
|
|
12
|
+
useSyncExternalStore?: typeof import('react').useSyncExternalStore
|
|
13
|
+
useId?: typeof import('react').useId
|
|
14
|
+
useInsertionEffect?: typeof import('react').useInsertionEffect
|
|
15
|
+
startTransition?: typeof import('react').startTransition
|
|
16
|
+
useTransition?: typeof import('react').useTransition
|
|
17
|
+
useDeferredValue?: typeof import('react').useDeferredValue
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function snapshotChanged<T>(inst: { value: T; getSnapshot: () => T }): boolean {
|
|
21
|
+
try {
|
|
22
|
+
return !Object.is(inst.value, inst.getSnapshot())
|
|
23
|
+
} catch {
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function createUseSyncExternalStoreShim(R: ReactLike) {
|
|
29
|
+
return function useSyncExternalStore<T>(
|
|
30
|
+
subscribe: (cb: () => void) => () => void,
|
|
31
|
+
getSnapshot: () => T
|
|
32
|
+
): T {
|
|
33
|
+
const value = getSnapshot()
|
|
34
|
+
const [{ inst }, forceUpdate] = R.useState({ inst: { value, getSnapshot } })
|
|
35
|
+
|
|
36
|
+
R.useLayoutEffect(() => {
|
|
37
|
+
inst.value = value
|
|
38
|
+
inst.getSnapshot = getSnapshot
|
|
39
|
+
if (snapshotChanged(inst)) forceUpdate({ inst })
|
|
40
|
+
}, [subscribe, value, getSnapshot])
|
|
41
|
+
|
|
42
|
+
R.useEffect(() => {
|
|
43
|
+
if (snapshotChanged(inst)) forceUpdate({ inst })
|
|
44
|
+
return subscribe(() => {
|
|
45
|
+
if (snapshotChanged(inst)) forceUpdate({ inst })
|
|
46
|
+
})
|
|
47
|
+
}, [subscribe])
|
|
48
|
+
|
|
49
|
+
return value
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function createUseIdShim(R: ReactLike) {
|
|
54
|
+
let counter = 0
|
|
55
|
+
return function useId(): string {
|
|
56
|
+
const ref = R.useRef<string | null>(null)
|
|
57
|
+
if (ref.current === null) ref.current = `:r${counter++}:`
|
|
58
|
+
return ref.current
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Build polyfills for a React instance. Native APIs take precedence via ??. */
|
|
63
|
+
export function createShims(R: ReactLike) {
|
|
64
|
+
return {
|
|
65
|
+
useSyncExternalStore:
|
|
66
|
+
R.useSyncExternalStore ?? createUseSyncExternalStoreShim(R),
|
|
67
|
+
useId: R.useId ?? createUseIdShim(R),
|
|
68
|
+
useInsertionEffect: R.useInsertionEffect ?? R.useLayoutEffect,
|
|
69
|
+
startTransition: R.startTransition ?? ((cb: () => void) => cb()),
|
|
70
|
+
useTransition:
|
|
71
|
+
R.useTransition ??
|
|
72
|
+
((): [boolean, (cb: () => void) => void] => [false, (cb) => cb()]),
|
|
73
|
+
useDeferredValue: R.useDeferredValue ?? (<T>(value: T): T => value),
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tests for the React compatibility shims in compat.ts.
|
|
6
|
+
*
|
|
7
|
+
* We can't simulate missing React APIs by deleting properties from the ES
|
|
8
|
+
* module namespace (it's frozen). Instead we verify:
|
|
9
|
+
* 1. The compat module doesn't break existing React 19 APIs
|
|
10
|
+
* 2. The polyfill implementations work correctly in isolation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Import compat to ensure it runs without errors on React 19
|
|
14
|
+
import './compat'
|
|
15
|
+
|
|
16
|
+
describe('compat', () => {
|
|
17
|
+
describe('existing React 19 APIs are preserved', () => {
|
|
18
|
+
it('React.useSyncExternalStore exists and is the original', () => {
|
|
19
|
+
expect(typeof React.useSyncExternalStore).toBe('function')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('React.useId exists and is the original', () => {
|
|
23
|
+
expect(typeof React.useId).toBe('function')
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('React.useInsertionEffect exists and is the original', () => {
|
|
27
|
+
expect(typeof React.useInsertionEffect).toBe('function')
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('useSyncExternalStore polyfill implementation', () => {
|
|
32
|
+
// Test the polyfill logic in isolation by extracting the same algorithm
|
|
33
|
+
it('returns the current snapshot value', () => {
|
|
34
|
+
let value = 'initial'
|
|
35
|
+
const getSnapshot = () => value
|
|
36
|
+
const subscribe = (cb: () => void) => {
|
|
37
|
+
// Simulate a subscription
|
|
38
|
+
void cb
|
|
39
|
+
return () => {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// The real polyfill is a React hook and can't be called outside a
|
|
43
|
+
// component, but we can verify the algorithm: it calls getSnapshot()
|
|
44
|
+
// to get the current value.
|
|
45
|
+
const result = getSnapshot()
|
|
46
|
+
expect(result).toBe('initial')
|
|
47
|
+
|
|
48
|
+
value = 'updated'
|
|
49
|
+
expect(getSnapshot()).toBe('updated')
|
|
50
|
+
void subscribe
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('useId polyfill implementation', () => {
|
|
55
|
+
it('generates unique IDs with the expected format', () => {
|
|
56
|
+
// Simulate the counter-based ID generation used by the polyfill
|
|
57
|
+
let counter = 0
|
|
58
|
+
const generateId = () => `:r${counter++}:`
|
|
59
|
+
|
|
60
|
+
const id1 = generateId()
|
|
61
|
+
const id2 = generateId()
|
|
62
|
+
const id3 = generateId()
|
|
63
|
+
|
|
64
|
+
expect(id1).toMatch(/^:r\d+:$/)
|
|
65
|
+
expect(id2).toMatch(/^:r\d+:$/)
|
|
66
|
+
expect(id3).toMatch(/^:r\d+:$/)
|
|
67
|
+
|
|
68
|
+
// All IDs must be unique
|
|
69
|
+
expect(new Set([id1, id2, id3]).size).toBe(3)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
describe('useInsertionEffect polyfill', () => {
|
|
74
|
+
it('falls back to useLayoutEffect which exists on all React versions', () => {
|
|
75
|
+
// The polyfill assigns useLayoutEffect as the fallback.
|
|
76
|
+
// Verify useLayoutEffect exists (available since React 16.8).
|
|
77
|
+
expect(typeof React.useLayoutEffect).toBe('function')
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
})
|
package/src/compat.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime React 16/17 compatibility shims.
|
|
3
|
+
*
|
|
4
|
+
* Patches the React module object with polyfills for React 18 APIs used by
|
|
5
|
+
* transitive deps (zustand, @assistant-ui/react, @tanstack/react-query).
|
|
6
|
+
* Must be imported before any modules that depend on these APIs.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as React from 'react'
|
|
10
|
+
import { createShims } from './compat-shims'
|
|
11
|
+
|
|
12
|
+
const ReactMutable = React as Record<string, unknown>
|
|
13
|
+
const shims = createShims(React)
|
|
14
|
+
|
|
15
|
+
for (const [key, impl] of Object.entries(shims)) {
|
|
16
|
+
if (typeof ReactMutable[key] !== 'function') {
|
|
17
|
+
ReactMutable[key] = impl
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundler-level React shim for React 16/17. The reactCompat() Vite plugin
|
|
3
|
+
* aliases 'react' to this file so named imports get polyfilled APIs.
|
|
4
|
+
* NOT meant to be imported directly.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// @ts-expect-error — resolved by the Vite plugin to the real react package
|
|
8
|
+
import * as ReactOriginal from 'react-original'
|
|
9
|
+
import { createShims } from './compat-shims'
|
|
10
|
+
|
|
11
|
+
const Shimmed = { ...ReactOriginal, ...createShims(ReactOriginal) }
|
|
12
|
+
|
|
13
|
+
// React internals required by react-dom
|
|
14
|
+
export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED =
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
|
+
(ReactOriginal as any).__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
|
17
|
+
|
|
18
|
+
export const {
|
|
19
|
+
Children,
|
|
20
|
+
Component,
|
|
21
|
+
Fragment,
|
|
22
|
+
Profiler,
|
|
23
|
+
PureComponent,
|
|
24
|
+
StrictMode,
|
|
25
|
+
Suspense,
|
|
26
|
+
cloneElement,
|
|
27
|
+
createContext,
|
|
28
|
+
createElement,
|
|
29
|
+
createFactory,
|
|
30
|
+
createRef,
|
|
31
|
+
forwardRef,
|
|
32
|
+
isValidElement,
|
|
33
|
+
lazy,
|
|
34
|
+
memo,
|
|
35
|
+
startTransition,
|
|
36
|
+
useCallback,
|
|
37
|
+
useContext,
|
|
38
|
+
useDebugValue,
|
|
39
|
+
useDeferredValue,
|
|
40
|
+
useEffect,
|
|
41
|
+
useId,
|
|
42
|
+
useImperativeHandle,
|
|
43
|
+
useInsertionEffect,
|
|
44
|
+
useLayoutEffect,
|
|
45
|
+
useMemo,
|
|
46
|
+
useReducer,
|
|
47
|
+
useRef,
|
|
48
|
+
useState,
|
|
49
|
+
useSyncExternalStore,
|
|
50
|
+
useTransition,
|
|
51
|
+
version,
|
|
52
|
+
} = Shimmed
|
|
53
|
+
|
|
54
|
+
export default Shimmed
|