what-react 0.11.7 → 0.12.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/dom.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // what-react/dom — react-dom compatible surface (src/dom.js).
2
2
  // Alias `react-dom` → `what-react/dom` to run React libraries that render.
3
3
 
4
- import type { ReactNode } from './index';
4
+ import type { ReactNode } from './index.js';
5
5
 
6
6
  export interface Root {
7
7
  render(children: ReactNode): void;
@@ -1,10 +1,10 @@
1
1
  // what-react/jsx-dev-runtime — development JSX runtime type definitions.
2
2
  // Mirrors jsx-runtime.d.ts; TS uses this under "jsx": "react-jsxdev".
3
3
 
4
- import type { ReactElement, Key } from './index';
4
+ import type { ReactElement, Key } from './index.js';
5
5
 
6
- export { Fragment } from './index';
7
- export { JSX } from './jsx-runtime';
6
+ export { Fragment } from './index.js';
7
+ export { JSX } from './jsx-runtime.js';
8
8
 
9
9
  export function jsx(type: any, props: any, key?: Key): ReactElement;
10
10
  export function jsxs(type: any, props: any, key?: Key): ReactElement;
package/jsx-runtime.d.ts CHANGED
@@ -8,12 +8,15 @@
8
8
  // Common attributes are typed for autocomplete; an index signature keeps
9
9
  // arbitrary/custom attributes and web-component tags valid.
10
10
 
11
- import type { ReactElement, ReactNode, Ref, Key } from './index';
11
+ import type { ReactElement, ReactNode, Ref, Key } from './index.js';
12
12
 
13
- export { Fragment } from './index';
13
+ export { Fragment } from './index.js';
14
14
 
15
15
  export function jsx(type: any, props: any, key?: Key): ReactElement;
16
16
  export function jsxs(type: any, props: any, key?: Key): ReactElement;
17
+ // The dev runtime ("jsx": "react-jsxdev") calls jsxDEV instead of jsx. Without a
18
+ // declaration, a TypeScript project on the dev transform fails to resolve it.
19
+ export function jsxDEV(type: any, props: any, key?: Key): ReactElement;
17
20
 
18
21
  type EventHandler<E extends Event = Event> = (
19
22
  event: E & { currentTarget: EventTarget & Element; target: Element },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-react",
3
- "version": "0.11.7",
3
+ "version": "0.12.0",
4
4
  "description": "React compatibility layer for What Framework — real React semantics (value hooks, re-renders, context) on a dedicated compat runtime",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -53,7 +53,7 @@
53
53
  "compatibility"
54
54
  ],
55
55
  "peerDependencies": {
56
- "what-core": "^0.11.7"
56
+ "what-core": "^0.12.0"
57
57
  },
58
58
  "author": "ZVN DEV (https://zvndev.com)",
59
59
  "license": "MIT",
package/src/index.js CHANGED
@@ -189,6 +189,30 @@ function flattenChildren(children, out) {
189
189
  return out;
190
190
  }
191
191
 
192
+ // ---- React element brands ----
193
+ // Ecosystem libraries do not duck-type elements, they check the brand:
194
+ // MUI, emotion, styled-components, recharts and react-select all compare
195
+ // `element.$$typeof` against `Symbol.for('react.element')` before treating a
196
+ // value as renderable. Without it they classify every compat element as a plain
197
+ // object and silently render nothing.
198
+ //
199
+ // The brand is also why React elements are XSS-safe against JSON injection: a
200
+ // symbol cannot survive JSON.parse, so an attacker-supplied object can never
201
+ // impersonate an element. isValidElement() below relies on that.
202
+ //
203
+ // React 19 renamed its internal brand to 'react.transitional.element', but
204
+ // library code in the wild overwhelmingly still compares against
205
+ // 'react.element', which is also what preact/compat brands with.
206
+ //
207
+ // Fragment is deliberately NOT branded here: it is what-core's own export, and
208
+ // stamping a React symbol onto it would mutate a shared object for every
209
+ // consumer of the framework, compat or not. Context is already branded where it
210
+ // is created (hooks.js).
211
+ const REACT_ELEMENT_TYPE = Symbol.for('react.element');
212
+ const REACT_MEMO_TYPE = Symbol.for('react.memo');
213
+ const REACT_LAZY_TYPE = Symbol.for('react.lazy');
214
+ const REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
215
+
192
216
  export function createElement(type, props, ...children) {
193
217
  if (props == null) props = {};
194
218
 
@@ -237,6 +261,7 @@ export function createElement(type, props, ...children) {
237
261
  }
238
262
 
239
263
  return {
264
+ $$typeof: REACT_ELEMENT_TYPE,
240
265
  tag,
241
266
  type,
242
267
  props: finalProps,
@@ -280,6 +305,11 @@ export function memo(Component, areEqual) {
280
305
  Memoized.displayName = `Memo(${Component.displayName || Component.name || 'Anonymous'})`;
281
306
  Memoized._memoCompare = areEqual || shallowEqual;
282
307
  Memoized._memoType = Component;
308
+ // Libraries unwrap a memo with `type.$$typeof === REACT_MEMO_TYPE ? type.type : type`
309
+ // to reach the component underneath (to read its displayName, propTypes, or to
310
+ // decide whether it is a class). Carry both halves of that contract.
311
+ Memoized.$$typeof = REACT_MEMO_TYPE;
312
+ Memoized.type = Component;
283
313
  return Memoized;
284
314
  }
285
315
 
@@ -303,6 +333,7 @@ export function lazy(loader) {
303
333
  }
304
334
  LazyComponent.displayName = 'Lazy';
305
335
  LazyComponent._lazy = true;
336
+ LazyComponent.$$typeof = REACT_LAZY_TYPE;
306
337
  return LazyComponent;
307
338
  }
308
339
 
@@ -315,6 +346,7 @@ export function Suspense(props) {
315
346
  return props.children;
316
347
  }
317
348
  Suspense.displayName = 'Suspense';
349
+ Suspense.$$typeof = REACT_SUSPENSE_TYPE;
318
350
 
319
351
  // ---- Children utilities ----
320
352