@pyreon/core 0.15.0 → 0.16.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/lib/analysis/index.js.html +1 -1
- package/lib/analysis/jsx-dev-runtime.js.html +1 -1
- package/lib/analysis/jsx-runtime.js.html +1 -1
- package/lib/index.js +16 -2
- package/lib/jsx-dev-runtime.js +16 -2
- package/lib/jsx-runtime.js +16 -2
- package/lib/types/index.d.ts +64 -5
- package/lib/types/jsx-dev-runtime.d.ts +16 -2
- package/lib/types/jsx-runtime.d.ts +16 -2
- package/package.json +2 -2
- package/src/for.ts +13 -1
- package/src/h.ts +16 -2
- package/src/manifest.ts +12 -4
- package/src/tests/core.test.ts +1 -1
- package/src/tests/extract-props-overloads.types.test.ts +135 -0
- package/src/tests/for.test.ts +23 -0
- package/src/tests/h.test.ts +21 -0
- package/src/types.ts +43 -2
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src","children":[{"uid":"46e89893-1","name":"lifecycle.ts"},{"uid":"46e89893-3","name":"component.ts"},{"uid":"46e89893-5","name":"compat-marker.ts"},{"uid":"46e89893-7","name":"context.ts"},{"uid":"46e89893-9","name":"h.ts"},{"uid":"46e89893-11","name":"dynamic.ts"},{"uid":"46e89893-13","name":"telemetry.ts"},{"uid":"46e89893-15","name":"error-boundary.ts"},{"uid":"46e89893-17","name":"for.ts"},{"uid":"46e89893-19","name":"lazy.ts"},{"uid":"46e89893-21","name":"map-array.ts"},{"uid":"46e89893-23","name":"portal.ts"},{"uid":"46e89893-25","name":"props.ts"},{"uid":"46e89893-27","name":"ref.ts"},{"uid":"46e89893-29","name":"show.ts"},{"uid":"46e89893-31","name":"style.ts"},{"uid":"46e89893-33","name":"suspense.ts"},{"uid":"46e89893-35","name":"index.ts"}]}]}],"isRoot":true},"nodeParts":{"46e89893-1":{"renderedLength":3078,"gzipLength":1313,"brotliLength":0,"metaUid":"46e89893-0"},"46e89893-3":{"renderedLength":1471,"gzipLength":693,"brotliLength":0,"metaUid":"46e89893-2"},"46e89893-5":{"renderedLength":3173,"gzipLength":1409,"brotliLength":0,"metaUid":"46e89893-4"},"46e89893-7":{"renderedLength":3600,"gzipLength":1542,"brotliLength":0,"metaUid":"46e89893-6"},"46e89893-9":{"renderedLength":1813,"gzipLength":957,"brotliLength":0,"metaUid":"46e89893-8"},"46e89893-11":{"renderedLength":490,"gzipLength":291,"brotliLength":0,"metaUid":"46e89893-10"},"46e89893-13":{"renderedLength":1208,"gzipLength":633,"brotliLength":0,"metaUid":"46e89893-12"},"46e89893-15":{"renderedLength":1659,"gzipLength":842,"brotliLength":0,"metaUid":"46e89893-14"},"46e89893-17":{"renderedLength":700,"gzipLength":478,"brotliLength":0,"metaUid":"46e89893-16"},"46e89893-19":{"renderedLength":461,"gzipLength":273,"brotliLength":0,"metaUid":"46e89893-18"},"46e89893-21":{"renderedLength":1018,"gzipLength":571,"brotliLength":0,"metaUid":"46e89893-20"},"46e89893-23":{"renderedLength":818,"gzipLength":491,"brotliLength":0,"metaUid":"46e89893-22"},"46e89893-25":{"renderedLength":4339,"gzipLength":1641,"brotliLength":0,"metaUid":"46e89893-24"},"46e89893-27":{"renderedLength":86,"gzipLength":98,"brotliLength":0,"metaUid":"46e89893-26"},"46e89893-29":{"renderedLength":2022,"gzipLength":854,"brotliLength":0,"metaUid":"46e89893-28"},"46e89893-31":{"renderedLength":1858,"gzipLength":825,"brotliLength":0,"metaUid":"46e89893-30"},"46e89893-33":{"renderedLength":1104,"gzipLength":614,"brotliLength":0,"metaUid":"46e89893-32"},"46e89893-35":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"46e89893-34"}},"nodeMetas":{"46e89893-0":{"id":"/src/lifecycle.ts","moduleParts":{"index.js":"46e89893-1"},"imported":[],"importedBy":[{"uid":"46e89893-34"},{"uid":"46e89893-2"},{"uid":"46e89893-6"},{"uid":"46e89893-14"}]},"46e89893-2":{"id":"/src/component.ts","moduleParts":{"index.js":"46e89893-3"},"imported":[{"uid":"46e89893-0"}],"importedBy":[{"uid":"46e89893-34"},{"uid":"46e89893-14"}]},"46e89893-4":{"id":"/src/compat-marker.ts","moduleParts":{"index.js":"46e89893-5"},"imported":[],"importedBy":[{"uid":"46e89893-34"},{"uid":"46e89893-14"}]},"46e89893-6":{"id":"/src/context.ts","moduleParts":{"index.js":"46e89893-7"},"imported":[{"uid":"46e89893-36"},{"uid":"46e89893-0"}],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-8":{"id":"/src/h.ts","moduleParts":{"index.js":"46e89893-9"},"imported":[],"importedBy":[{"uid":"46e89893-34"},{"uid":"46e89893-10"},{"uid":"46e89893-18"},{"uid":"46e89893-32"}]},"46e89893-10":{"id":"/src/dynamic.ts","moduleParts":{"index.js":"46e89893-11"},"imported":[{"uid":"46e89893-8"}],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-12":{"id":"/src/telemetry.ts","moduleParts":{"index.js":"46e89893-13"},"imported":[],"importedBy":[{"uid":"46e89893-34"},{"uid":"46e89893-14"}]},"46e89893-14":{"id":"/src/error-boundary.ts","moduleParts":{"index.js":"46e89893-15"},"imported":[{"uid":"46e89893-36"},{"uid":"46e89893-4"},{"uid":"46e89893-2"},{"uid":"46e89893-0"},{"uid":"46e89893-12"}],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-16":{"id":"/src/for.ts","moduleParts":{"index.js":"46e89893-17"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-18":{"id":"/src/lazy.ts","moduleParts":{"index.js":"46e89893-19"},"imported":[{"uid":"46e89893-36"},{"uid":"46e89893-8"}],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-20":{"id":"/src/map-array.ts","moduleParts":{"index.js":"46e89893-21"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-22":{"id":"/src/portal.ts","moduleParts":{"index.js":"46e89893-23"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-24":{"id":"/src/props.ts","moduleParts":{"index.js":"46e89893-25"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-26":{"id":"/src/ref.ts","moduleParts":{"index.js":"46e89893-27"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-28":{"id":"/src/show.ts","moduleParts":{"index.js":"46e89893-29"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-30":{"id":"/src/style.ts","moduleParts":{"index.js":"46e89893-31"},"imported":[],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-32":{"id":"/src/suspense.ts","moduleParts":{"index.js":"46e89893-33"},"imported":[{"uid":"46e89893-8"}],"importedBy":[{"uid":"46e89893-34"}]},"46e89893-34":{"id":"/src/index.ts","moduleParts":{"index.js":"46e89893-35"},"imported":[{"uid":"46e89893-2"},{"uid":"46e89893-4"},{"uid":"46e89893-6"},{"uid":"46e89893-10"},{"uid":"46e89893-14"},{"uid":"46e89893-16"},{"uid":"46e89893-8"},{"uid":"46e89893-18"},{"uid":"46e89893-0"},{"uid":"46e89893-20"},{"uid":"46e89893-22"},{"uid":"46e89893-24"},{"uid":"46e89893-26"},{"uid":"46e89893-28"},{"uid":"46e89893-30"},{"uid":"46e89893-32"},{"uid":"46e89893-12"}],"importedBy":[],"isEntry":true},"46e89893-36":{"id":"@pyreon/reactivity","moduleParts":{},"imported":[],"importedBy":[{"uid":"46e89893-6"},{"uid":"46e89893-14"},{"uid":"46e89893-18"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-dev-runtime.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-dev-runtime.js","children":[{"name":"src","children":[{"uid":"235a8e25-1","name":"h.ts"},{"uid":"235a8e25-3","name":"jsx-runtime.ts"},{"uid":"235a8e25-5","name":"jsx-dev-runtime.ts"}]}]}],"isRoot":true},"nodeParts":{"235a8e25-1":{"renderedLength":1813,"gzipLength":957,"brotliLength":0,"metaUid":"235a8e25-0"},"235a8e25-3":{"renderedLength":1103,"gzipLength":640,"brotliLength":0,"metaUid":"235a8e25-2"},"235a8e25-5":{"renderedLength":0,"gzipLength":0,"brotliLength":0,"metaUid":"235a8e25-4"}},"nodeMetas":{"235a8e25-0":{"id":"/src/h.ts","moduleParts":{"jsx-dev-runtime.js":"235a8e25-1"},"imported":[],"importedBy":[{"uid":"235a8e25-2"}]},"235a8e25-2":{"id":"/src/jsx-runtime.ts","moduleParts":{"jsx-dev-runtime.js":"235a8e25-3"},"imported":[{"uid":"235a8e25-0"}],"importedBy":[{"uid":"235a8e25-4"}]},"235a8e25-4":{"id":"/src/jsx-dev-runtime.ts","moduleParts":{"jsx-dev-runtime.js":"235a8e25-5"},"imported":[{"uid":"235a8e25-2"}],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-runtime.js","children":[{"name":"src","children":[{"uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"jsx-runtime.js","children":[{"name":"src","children":[{"uid":"8c2807f7-1","name":"h.ts"},{"uid":"8c2807f7-3","name":"jsx-runtime.ts"}]}]}],"isRoot":true},"nodeParts":{"8c2807f7-1":{"renderedLength":1813,"gzipLength":957,"brotliLength":0,"metaUid":"8c2807f7-0"},"8c2807f7-3":{"renderedLength":1103,"gzipLength":640,"brotliLength":0,"metaUid":"8c2807f7-2"}},"nodeMetas":{"8c2807f7-0":{"id":"/src/h.ts","moduleParts":{"jsx-runtime.js":"8c2807f7-1"},"imported":[],"importedBy":[{"uid":"8c2807f7-2"}]},"8c2807f7-2":{"id":"/src/jsx-runtime.ts","moduleParts":{"jsx-runtime.js":"8c2807f7-3"},"imported":[{"uid":"8c2807f7-0"}],"importedBy":[],"isEntry":true}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -350,8 +350,22 @@ setSnapshotCapture({
|
|
|
350
350
|
|
|
351
351
|
//#endregion
|
|
352
352
|
//#region src/h.ts
|
|
353
|
-
/**
|
|
354
|
-
|
|
353
|
+
/**
|
|
354
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
355
|
+
*
|
|
356
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
357
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
358
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
359
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
360
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
361
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
362
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
363
|
+
* fell through to `renderElement` and crashed SSG with
|
|
364
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
365
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
366
|
+
* bundle evaluations — same identity everywhere.
|
|
367
|
+
*/
|
|
368
|
+
const Fragment = Symbol.for("Pyreon.Fragment");
|
|
355
369
|
/**
|
|
356
370
|
* Hyperscript function — the compiled output of JSX.
|
|
357
371
|
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
package/lib/jsx-dev-runtime.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
//#region src/h.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
4
|
+
*
|
|
5
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
6
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
7
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
8
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
9
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
10
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
11
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
12
|
+
* fell through to `renderElement` and crashed SSG with
|
|
13
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
14
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
15
|
+
* bundle evaluations — same identity everywhere.
|
|
16
|
+
*/
|
|
17
|
+
const Fragment = Symbol.for("Pyreon.Fragment");
|
|
4
18
|
/**
|
|
5
19
|
* Hyperscript function — the compiled output of JSX.
|
|
6
20
|
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
package/lib/jsx-runtime.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
//#region src/h.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
4
|
+
*
|
|
5
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
6
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
7
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
8
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
9
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
10
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
11
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
12
|
+
* fell through to `renderElement` and crashed SSG with
|
|
13
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
14
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
15
|
+
* bundle evaluations — same identity everywhere.
|
|
16
|
+
*/
|
|
17
|
+
const Fragment = Symbol.for("Pyreon.Fragment");
|
|
4
18
|
/**
|
|
5
19
|
* Hyperscript function — the compiled output of JSX.
|
|
6
20
|
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
package/lib/types/index.d.ts
CHANGED
|
@@ -16,8 +16,41 @@ type Props = Record<string, unknown>;
|
|
|
16
16
|
* It returns any renderable content and may call lifecycle hooks during setup.
|
|
17
17
|
*/
|
|
18
18
|
type ComponentFn<P extends Props = Props> = (props: P) => VNodeChild;
|
|
19
|
-
/**
|
|
20
|
-
type
|
|
19
|
+
/**
|
|
20
|
+
* Extract the props type from a component function, or pass through if already
|
|
21
|
+
* a props type. **Multi-overload aware** — matches up to 4 call signatures and
|
|
22
|
+
* produces the UNION of their first-argument types. A single-overload function
|
|
23
|
+
* still works (the union of 4 copies of the same props type dedupes back to
|
|
24
|
+
* the single shape).
|
|
25
|
+
*
|
|
26
|
+
* **Why this shape**. `T extends (props: infer P) => any ? P : never` only
|
|
27
|
+
* captures the LAST overload of a multi-overload function — TS's overload-
|
|
28
|
+
* resolution-against-conditional-types semantics. Multi-overload primitives
|
|
29
|
+
* (Iterator, List, Element, etc.) need the union of every overload's props
|
|
30
|
+
* to survive HOC wrapping (`rocketstyle()`, `attrs()`) without silently
|
|
31
|
+
* downgrading the public prop surface to the loosest overload. Mirrors
|
|
32
|
+
* vitus-labs PR #222.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* function Iterator<T extends SimpleValue>(p: { data: T[]; valueName?: string }): VNodeChild
|
|
36
|
+
* function Iterator<T extends ObjectValue>(p: { data: T[]; component: ComponentFn<T> }): VNodeChild
|
|
37
|
+
* type Props = ExtractProps<typeof Iterator>
|
|
38
|
+
* // → { data: SimpleValue[]; valueName?: string }
|
|
39
|
+
* // | { data: ObjectValue[]; component: ComponentFn<ObjectValue> }
|
|
40
|
+
*/
|
|
41
|
+
type ExtractProps<T> = T extends {
|
|
42
|
+
(props: infer P1, ...args: any): any;
|
|
43
|
+
(props: infer P2, ...args: any): any;
|
|
44
|
+
(props: infer P3, ...args: any): any;
|
|
45
|
+
(props: infer P4, ...args: any): any;
|
|
46
|
+
} ? P1 | P2 | P3 | P4 : T extends {
|
|
47
|
+
(props: infer P1, ...args: any): any;
|
|
48
|
+
(props: infer P2, ...args: any): any;
|
|
49
|
+
(props: infer P3, ...args: any): any;
|
|
50
|
+
} ? P1 | P2 | P3 : T extends {
|
|
51
|
+
(props: infer P1, ...args: any): any;
|
|
52
|
+
(props: infer P2, ...args: any): any;
|
|
53
|
+
} ? P1 | P2 : T extends ComponentFn<infer P> ? P : T;
|
|
21
54
|
/** A higher-order component that wraps a component, optionally transforming its props. */
|
|
22
55
|
type HigherOrderComponent<HOP extends Props, P extends Props | undefined = undefined> = (Component: ComponentFn<HOP>) => ComponentFn<P extends undefined ? HOP : P>;
|
|
23
56
|
/**
|
|
@@ -282,7 +315,19 @@ declare function ErrorBoundary(props: {
|
|
|
282
315
|
*/
|
|
283
316
|
declare const ForSymbol: unique symbol;
|
|
284
317
|
interface ForProps<T> {
|
|
285
|
-
|
|
318
|
+
/**
|
|
319
|
+
* The list to iterate. Accepts EITHER a function returning the array
|
|
320
|
+
* (preferred — keeps reactivity intact when the array comes from a
|
|
321
|
+
* signal accessor) OR the array directly (convenient for static lists
|
|
322
|
+
* or already-resolved arrays). The runtime in `runtime-dom/src/mount.ts`
|
|
323
|
+
* normalizes both shapes; this type matches the runtime so users aren't
|
|
324
|
+
* forced to write `each={() => items}` for a plain array.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* <For each={items}>{r => <li>{r.label}</li>}</For> // static
|
|
328
|
+
* <For each={() => store.items()}>{r => <li>...</li>}</For> // reactive
|
|
329
|
+
*/
|
|
330
|
+
each: T[] | (() => T[]);
|
|
286
331
|
/** Keying function — use `by` not `key` (JSX extracts `key` for VNode reconciliation). */
|
|
287
332
|
by: (item: T) => string | number;
|
|
288
333
|
children: (item: T) => VNode | NativeItem;
|
|
@@ -306,8 +351,22 @@ interface ForProps<T> {
|
|
|
306
351
|
declare function For<T>(props: ForProps<T>): VNode;
|
|
307
352
|
//#endregion
|
|
308
353
|
//#region src/h.d.ts
|
|
309
|
-
/**
|
|
310
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
356
|
+
*
|
|
357
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
358
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
359
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
360
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
361
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
362
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
363
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
364
|
+
* fell through to `renderElement` and crashed SSG with
|
|
365
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
366
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
367
|
+
* bundle evaluations — same identity everywhere.
|
|
368
|
+
*/
|
|
369
|
+
declare const Fragment: symbol;
|
|
311
370
|
/**
|
|
312
371
|
* Hyperscript function — the compiled output of JSX.
|
|
313
372
|
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
|
@@ -18,8 +18,22 @@ type Props = Record<string, unknown>;
|
|
|
18
18
|
type ComponentFn<P extends Props = Props> = (props: P) => VNodeChild;
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/h.d.ts
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
23
|
+
*
|
|
24
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
25
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
26
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
27
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
28
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
29
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
30
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
31
|
+
* fell through to `renderElement` and crashed SSG with
|
|
32
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
33
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
34
|
+
* bundle evaluations — same identity everywhere.
|
|
35
|
+
*/
|
|
36
|
+
declare const Fragment: symbol;
|
|
23
37
|
//#endregion
|
|
24
38
|
//#region src/ref.d.ts
|
|
25
39
|
/**
|
|
@@ -18,8 +18,22 @@ type Props = Record<string, unknown>;
|
|
|
18
18
|
type ComponentFn<P extends Props = Props> = (props: P) => VNodeChild;
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/h.d.ts
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
23
|
+
*
|
|
24
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
25
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
26
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
27
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
28
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
29
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
30
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
31
|
+
* fell through to `renderElement` and crashed SSG with
|
|
32
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
33
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
34
|
+
* bundle evaluations — same identity everywhere.
|
|
35
|
+
*/
|
|
36
|
+
declare const Fragment: symbol;
|
|
23
37
|
//#endregion
|
|
24
38
|
//#region src/ref.d.ts
|
|
25
39
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Core component model and lifecycle for Pyreon",
|
|
5
5
|
"homepage": "https://github.com/pyreon/pyreon/tree/main/packages/core#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"prepublishOnly": "bun run build"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@pyreon/reactivity": "^0.
|
|
56
|
+
"@pyreon/reactivity": "^0.16.0"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@pyreon/manifest": "0.13.1"
|
package/src/for.ts
CHANGED
|
@@ -7,7 +7,19 @@ import type { NativeItem, Props, VNode } from './types'
|
|
|
7
7
|
export const ForSymbol: unique symbol = Symbol('pyreon.For')
|
|
8
8
|
|
|
9
9
|
export interface ForProps<T> {
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* The list to iterate. Accepts EITHER a function returning the array
|
|
12
|
+
* (preferred — keeps reactivity intact when the array comes from a
|
|
13
|
+
* signal accessor) OR the array directly (convenient for static lists
|
|
14
|
+
* or already-resolved arrays). The runtime in `runtime-dom/src/mount.ts`
|
|
15
|
+
* normalizes both shapes; this type matches the runtime so users aren't
|
|
16
|
+
* forced to write `each={() => items}` for a plain array.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <For each={items}>{r => <li>{r.label}</li>}</For> // static
|
|
20
|
+
* <For each={() => store.items()}>{r => <li>...</li>}</For> // reactive
|
|
21
|
+
*/
|
|
22
|
+
each: T[] | (() => T[])
|
|
11
23
|
/** Keying function — use `by` not `key` (JSX extracts `key` for VNode reconciliation). */
|
|
12
24
|
by: (item: T) => string | number
|
|
13
25
|
children: (item: T) => VNode | NativeItem
|
package/src/h.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
import type { ComponentFn, Props, VNode, VNodeChild } from './types'
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Marker for fragment nodes — renders children without a wrapper element.
|
|
5
|
+
*
|
|
6
|
+
* MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
|
|
7
|
+
* `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
|
|
8
|
+
* main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
|
|
9
|
+
* each bundle's evaluation of a bare `Symbol(...)` would produce a
|
|
10
|
+
* DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
|
|
11
|
+
* resolves to jsx-runtime's identity; `runtime-server` checks
|
|
12
|
+
* `vnode.type === Fragment` against the main-entry identity. Mismatch
|
|
13
|
+
* fell through to `renderElement` and crashed SSG with
|
|
14
|
+
* `TypeError: Cannot convert a Symbol value to a string`.
|
|
15
|
+
* `Symbol.for()` keys by string in a global registry shared across all
|
|
16
|
+
* bundle evaluations — same identity everywhere.
|
|
17
|
+
*/
|
|
18
|
+
export const Fragment: symbol = Symbol.for('Pyreon.Fragment')
|
|
5
19
|
|
|
6
20
|
/**
|
|
7
21
|
* Hyperscript function — the compiled output of JSX.
|
package/src/manifest.ts
CHANGED
|
@@ -524,11 +524,19 @@ return wrapCompatComponent(type)(props)`,
|
|
|
524
524
|
{
|
|
525
525
|
name: 'ExtractProps',
|
|
526
526
|
kind: 'type',
|
|
527
|
-
signature:
|
|
527
|
+
signature:
|
|
528
|
+
'type ExtractProps<T> = /* matches up to 4 overloads, unions the props */ T extends ComponentFn<infer P> ? P : T',
|
|
528
529
|
summary:
|
|
529
|
-
|
|
530
|
-
example: `
|
|
531
|
-
|
|
530
|
+
"Extracts the props type from a `ComponentFn`. Passes through unchanged if `T` is not a `ComponentFn`. **Multi-overload aware** — matches up to 4 call signatures and produces the UNION of their first-argument types. Critical for multi-overload primitives (Iterator, List, Element) whose loosest overload is last; without overload-aware extraction, HOC wrapping (`rocketstyle()`, `attrs()`) silently downgraded their public prop surface. Single-overload functions still work — the union of 4 copies of the same props type dedupes back to the single shape.",
|
|
531
|
+
example: `function Iterator<T extends SimpleValue>(p: { data: T[]; valueName?: string }): VNodeChild
|
|
532
|
+
function Iterator<T extends ObjectValue>(p: { data: T[]; component: ComponentFn<T> }): VNodeChild
|
|
533
|
+
type Props = ExtractProps<typeof Iterator>
|
|
534
|
+
// → { data: SimpleValue[]; valueName?: string }
|
|
535
|
+
// | { data: ObjectValue[]; component: ComponentFn<ObjectValue> }`,
|
|
536
|
+
mistakes: [
|
|
537
|
+
'Assuming `ExtractProps<T>` returns only the LAST overload — pre-fix it did, post-fix it returns the UNION of up to 4 overloads. Functions with more than 4 overloads still drop the extras.',
|
|
538
|
+
'Using `T extends (props: infer P) => any ? P : never` directly in user code — that pattern captures only the LAST overload of a multi-overload function. Use `ExtractProps<T>` to get the full union.',
|
|
539
|
+
],
|
|
532
540
|
seeAlso: ['HigherOrderComponent'],
|
|
533
541
|
},
|
|
534
542
|
{
|
package/src/tests/core.test.ts
CHANGED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile-time type tests for `ExtractProps` multi-overload narrowing.
|
|
3
|
+
*
|
|
4
|
+
* Regression: pre-fix, `ExtractProps<T>` collapsed multi-overload functions
|
|
5
|
+
* to the LAST overload's props — TS's overload-resolution-against-conditional-
|
|
6
|
+
* types semantics. Multi-overload primitives (Iterator / List / Element in
|
|
7
|
+
* `@pyreon/elements`) silently downgraded their public prop surface to the
|
|
8
|
+
* loosest overload when wrapped through `rocketstyle()` / `attrs()`. The
|
|
9
|
+
* fix matches up to 4 call signatures via pattern matching and produces the
|
|
10
|
+
* UNION of every overload's first-argument type.
|
|
11
|
+
*
|
|
12
|
+
* Mirrors vitus-labs PR #222. Kept in sync across the 4 copies in
|
|
13
|
+
* `@pyreon/core`, `@pyreon/elements`, `@pyreon/attrs`, and `@pyreon/rocketstyle`
|
|
14
|
+
* — the canonical reference test lives here.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { describe, expectTypeOf, it } from 'vitest'
|
|
18
|
+
import type { ComponentFn, ExtractProps, VNodeChild } from '../index'
|
|
19
|
+
|
|
20
|
+
describe('ExtractProps — single-overload functions still work', () => {
|
|
21
|
+
it('extracts props from a ComponentFn<P>', () => {
|
|
22
|
+
type Greet = ComponentFn<{ name: string }>
|
|
23
|
+
expectTypeOf<ExtractProps<Greet>>().toEqualTypeOf<{ name: string }>()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('extracts props from a bare (props: P) => any signature', () => {
|
|
27
|
+
type Fn = (props: { count: number }) => string
|
|
28
|
+
expectTypeOf<ExtractProps<Fn>>().toEqualTypeOf<{ count: number }>()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('passes through a non-function shape unchanged', () => {
|
|
32
|
+
type Props = { id: string; value: number }
|
|
33
|
+
expectTypeOf<ExtractProps<Props>>().toEqualTypeOf<Props>()
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
describe('ExtractProps — multi-overload narrowing (load-bearing assertions)', () => {
|
|
38
|
+
it('unions both arms of a 2-overload function', () => {
|
|
39
|
+
interface TwoOverloads {
|
|
40
|
+
(props: { kind: 'a'; value: number }): VNodeChild
|
|
41
|
+
(props: { kind: 'b'; value: string }): VNodeChild
|
|
42
|
+
}
|
|
43
|
+
type Props = ExtractProps<TwoOverloads>
|
|
44
|
+
// Both shapes appear in the extracted union.
|
|
45
|
+
expectTypeOf<Props>().toEqualTypeOf<
|
|
46
|
+
{ kind: 'a'; value: number } | { kind: 'b'; value: string }
|
|
47
|
+
>()
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('unions all three arms of a 3-overload function (Iterator/List/Element shape)', () => {
|
|
51
|
+
interface ThreeOverloads {
|
|
52
|
+
(props: { mode: 'simple'; data: string[] }): VNodeChild
|
|
53
|
+
(props: { mode: 'object'; data: { id: number }[] }): VNodeChild
|
|
54
|
+
(props: { mode: 'children'; children: unknown }): VNodeChild
|
|
55
|
+
}
|
|
56
|
+
type Props = ExtractProps<ThreeOverloads>
|
|
57
|
+
expectTypeOf<Props>().toEqualTypeOf<
|
|
58
|
+
| { mode: 'simple'; data: string[] }
|
|
59
|
+
| { mode: 'object'; data: { id: number }[] }
|
|
60
|
+
| { mode: 'children'; children: unknown }
|
|
61
|
+
>()
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('unions all four arms of a 4-overload function', () => {
|
|
65
|
+
interface FourOverloads {
|
|
66
|
+
(props: { variant: 'a' }): VNodeChild
|
|
67
|
+
(props: { variant: 'b' }): VNodeChild
|
|
68
|
+
(props: { variant: 'c' }): VNodeChild
|
|
69
|
+
(props: { variant: 'd' }): VNodeChild
|
|
70
|
+
}
|
|
71
|
+
type Props = ExtractProps<FourOverloads>
|
|
72
|
+
expectTypeOf<Props>().toEqualTypeOf<
|
|
73
|
+
{ variant: 'a' } | { variant: 'b' } | { variant: 'c' } | { variant: 'd' }
|
|
74
|
+
>()
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
describe('ExtractProps — bisect-load-bearing: pre-fix shape would FAIL these', () => {
|
|
79
|
+
/**
|
|
80
|
+
* If `ExtractProps<T>` were reverted to `T extends ComponentFn<infer P> ? P : T`,
|
|
81
|
+
* each of these would extract only the LAST overload's props and the
|
|
82
|
+
* `toEqualTypeOf<union>` check would fail at compile time. This is the
|
|
83
|
+
* structural anchor — the load-bearing regression guard.
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
it('a 2-overload function MUST extract BOTH arms (not just the last)', () => {
|
|
87
|
+
interface OverloadedComp {
|
|
88
|
+
(props: { mode: 'a'; valueA: number }): VNodeChild
|
|
89
|
+
(props: { mode: 'b'; valueB: string }): VNodeChild
|
|
90
|
+
}
|
|
91
|
+
// The first arm `{ mode: 'a'; valueA: number }` must be present in the
|
|
92
|
+
// union. Pre-fix, the conditional collapsed to just the LAST arm.
|
|
93
|
+
type Props = ExtractProps<OverloadedComp>
|
|
94
|
+
// Assignability check: both shapes must be assignable to the extracted type.
|
|
95
|
+
const a: Props = { mode: 'a', valueA: 1 }
|
|
96
|
+
const b: Props = { mode: 'b', valueB: 'x' }
|
|
97
|
+
void a
|
|
98
|
+
void b
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
it("a 3-overload Iterator-shaped surface MUST surface SimpleProps + ObjectProps + ChildrenProps", () => {
|
|
102
|
+
// Synthetic Iterator overload-shape — mirrors the real
|
|
103
|
+
// `@pyreon/elements` Iterator. The structural failure mode pre-fix:
|
|
104
|
+
// `ExtractProps<typeof Iterator>` returned just `ChildrenProps`, so any
|
|
105
|
+
// HOC wrapping (rocketstyle, attrs) lost the SimpleProps + ObjectProps
|
|
106
|
+
// surfaces from the public typed API.
|
|
107
|
+
type SimpleItem = ComponentFn<{ value: string }>
|
|
108
|
+
type ObjectItem = ComponentFn<{ id: number }>
|
|
109
|
+
interface IteratorLike {
|
|
110
|
+
<T extends string | number>(props: {
|
|
111
|
+
data: T[]
|
|
112
|
+
component: SimpleItem
|
|
113
|
+
valueName?: string
|
|
114
|
+
}): VNodeChild
|
|
115
|
+
<T extends { id: number }>(props: {
|
|
116
|
+
data: T[]
|
|
117
|
+
component: ObjectItem
|
|
118
|
+
}): VNodeChild
|
|
119
|
+
(props: { children: VNodeChild }): VNodeChild
|
|
120
|
+
}
|
|
121
|
+
type Props = ExtractProps<IteratorLike>
|
|
122
|
+
|
|
123
|
+
const noopSimple: SimpleItem = () => null
|
|
124
|
+
const noopObject: ObjectItem = () => null
|
|
125
|
+
// SimpleProps arm assignable:
|
|
126
|
+
const simple: Props = { data: ['a', 'b'], component: noopSimple, valueName: 'text' }
|
|
127
|
+
// ObjectProps arm assignable:
|
|
128
|
+
const obj: Props = { data: [{ id: 1 }], component: noopObject }
|
|
129
|
+
// ChildrenProps arm assignable:
|
|
130
|
+
const ch: Props = { children: null }
|
|
131
|
+
void simple
|
|
132
|
+
void obj
|
|
133
|
+
void ch
|
|
134
|
+
})
|
|
135
|
+
})
|
package/src/tests/for.test.ts
CHANGED
|
@@ -91,4 +91,27 @@ describe('For', () => {
|
|
|
91
91
|
expect((result as VNode).type).toBe('li')
|
|
92
92
|
expect((result as VNode).key).toBe(1)
|
|
93
93
|
})
|
|
94
|
+
|
|
95
|
+
// Regression: `ForProps.each` previously typed as `() => T[]` only.
|
|
96
|
+
// Users writing `<For each={items}>` (with `items: T[]` directly) hit
|
|
97
|
+
// a confusing TS error: `Type 'T[]' is not assignable to type
|
|
98
|
+
// '() => T[]'`. The runtime in `runtime-dom/src/mount.ts:144-147`
|
|
99
|
+
// already accepted both shapes — only the type was forcing the
|
|
100
|
+
// accessor form. Type now accepts `T[] | (() => T[])` so users with
|
|
101
|
+
// already-resolved arrays don't need to wrap them in a thunk just to
|
|
102
|
+
// satisfy the type.
|
|
103
|
+
test('each accepts T[] directly (not just () => T[])', () => {
|
|
104
|
+
// TypeScript-level test: this would not compile pre-fix.
|
|
105
|
+
const items = [1, 2, 3]
|
|
106
|
+
const childFn = (n: number): VNode => h('li', { key: n }, String(n))
|
|
107
|
+
const node = For<number>({ each: items, by: (n) => n, children: childFn })
|
|
108
|
+
expect(node.type).toBe(ForSymbol as unknown as string)
|
|
109
|
+
// Both shapes still work — function form continues to typecheck.
|
|
110
|
+
const node2 = For<number>({
|
|
111
|
+
each: () => items,
|
|
112
|
+
by: (n) => n,
|
|
113
|
+
children: childFn,
|
|
114
|
+
})
|
|
115
|
+
expect(node2.type).toBe(ForSymbol as unknown as string)
|
|
116
|
+
})
|
|
94
117
|
})
|
package/src/tests/h.test.ts
CHANGED
|
@@ -176,6 +176,27 @@ describe('h() — VNode creation', () => {
|
|
|
176
176
|
expect(outer.children).toHaveLength(2)
|
|
177
177
|
expect((outer.children[0] as VNode).type).toBe(Fragment)
|
|
178
178
|
})
|
|
179
|
+
|
|
180
|
+
// Regression: pre-fix, `Fragment` was `Symbol('Pyreon.Fragment')` — a
|
|
181
|
+
// fresh symbol per module evaluation. When `h.ts` got bundled into BOTH
|
|
182
|
+
// `lib/index.js` AND `lib/jsx-runtime.js` (each a separate published
|
|
183
|
+
// entry point), each bundle created a DISTINCT Symbol identity. JSX
|
|
184
|
+
// `<>` compiles to `jsx(Fragment, ...)` referring to jsx-runtime's
|
|
185
|
+
// Fragment; `runtime-server` checks `vnode.type === Fragment` against
|
|
186
|
+
// `@pyreon/core`'s main-entry Fragment. The two never matched →
|
|
187
|
+
// fell through to `renderElement` → tried to stringify the Symbol →
|
|
188
|
+
// SSG crashed with `TypeError: Cannot convert a Symbol value to
|
|
189
|
+
// a string`.
|
|
190
|
+
//
|
|
191
|
+
// Fix: use `Symbol.for('Pyreon.Fragment')` — the global registry keys
|
|
192
|
+
// by string, so all bundles inlining h.ts share the same identity.
|
|
193
|
+
//
|
|
194
|
+
// This test asserts the global-registry contract: Fragment IS
|
|
195
|
+
// retrievable from the registry. Bisect-verifiable: reverting h.ts to
|
|
196
|
+
// `Symbol(...)` makes this fail.
|
|
197
|
+
test('Fragment uses Symbol.for() for cross-bundle identity stability', () => {
|
|
198
|
+
expect(Fragment).toBe(Symbol.for('Pyreon.Fragment'))
|
|
199
|
+
})
|
|
179
200
|
})
|
|
180
201
|
})
|
|
181
202
|
|
package/src/types.ts
CHANGED
|
@@ -30,8 +30,49 @@ export type ComponentFn<P extends Props = Props> = (props: P) => VNodeChild
|
|
|
30
30
|
|
|
31
31
|
// ─── Utility types ───────────────────────────────────────────────────────────
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Extract the props type from a component function, or pass through if already
|
|
35
|
+
* a props type. **Multi-overload aware** — matches up to 4 call signatures and
|
|
36
|
+
* produces the UNION of their first-argument types. A single-overload function
|
|
37
|
+
* still works (the union of 4 copies of the same props type dedupes back to
|
|
38
|
+
* the single shape).
|
|
39
|
+
*
|
|
40
|
+
* **Why this shape**. `T extends (props: infer P) => any ? P : never` only
|
|
41
|
+
* captures the LAST overload of a multi-overload function — TS's overload-
|
|
42
|
+
* resolution-against-conditional-types semantics. Multi-overload primitives
|
|
43
|
+
* (Iterator, List, Element, etc.) need the union of every overload's props
|
|
44
|
+
* to survive HOC wrapping (`rocketstyle()`, `attrs()`) without silently
|
|
45
|
+
* downgrading the public prop surface to the loosest overload. Mirrors
|
|
46
|
+
* vitus-labs PR #222.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* function Iterator<T extends SimpleValue>(p: { data: T[]; valueName?: string }): VNodeChild
|
|
50
|
+
* function Iterator<T extends ObjectValue>(p: { data: T[]; component: ComponentFn<T> }): VNodeChild
|
|
51
|
+
* type Props = ExtractProps<typeof Iterator>
|
|
52
|
+
* // → { data: SimpleValue[]; valueName?: string }
|
|
53
|
+
* // | { data: ObjectValue[]; component: ComponentFn<ObjectValue> }
|
|
54
|
+
*/
|
|
55
|
+
export type ExtractProps<T> = T extends {
|
|
56
|
+
(props: infer P1, ...args: any): any
|
|
57
|
+
(props: infer P2, ...args: any): any
|
|
58
|
+
(props: infer P3, ...args: any): any
|
|
59
|
+
(props: infer P4, ...args: any): any
|
|
60
|
+
}
|
|
61
|
+
? P1 | P2 | P3 | P4
|
|
62
|
+
: T extends {
|
|
63
|
+
(props: infer P1, ...args: any): any
|
|
64
|
+
(props: infer P2, ...args: any): any
|
|
65
|
+
(props: infer P3, ...args: any): any
|
|
66
|
+
}
|
|
67
|
+
? P1 | P2 | P3
|
|
68
|
+
: T extends {
|
|
69
|
+
(props: infer P1, ...args: any): any
|
|
70
|
+
(props: infer P2, ...args: any): any
|
|
71
|
+
}
|
|
72
|
+
? P1 | P2
|
|
73
|
+
: T extends ComponentFn<infer P>
|
|
74
|
+
? P
|
|
75
|
+
: T
|
|
35
76
|
|
|
36
77
|
/** A higher-order component that wraps a component, optionally transforming its props. */
|
|
37
78
|
export type HigherOrderComponent<HOP extends Props, P extends Props | undefined = undefined> = (
|