@dom-expressions/runtime 0.50.0-next.15

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.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Shared type-level helpers used to derive `prop:*` attribute typings from
3
+ * DOM element interfaces (e.g. `HTMLInputElement`, `HTMLButtonElement`).
4
+ *
5
+ * The wrapping of each value (`FunctionMaybe<T>` in `jsx-h.d.ts` vs. the
6
+ * raw value in `jsx.d.ts`) is applied by each consumer when composing its
7
+ * own `Properties<T>` mapped type. That way this file stays identical in
8
+ * both reactive and non-reactive contexts and only needs to exist once.
9
+ *
10
+ * originally from
11
+ * @url https://github.com/potahtml/pota
12
+ */
13
+
14
+ /** Base-class properties shared by all elements — skipped from `prop:*`. */
15
+ export type SkipPropsFrom = HTMLUnknownElement & HTMLElement & Element & Node;
16
+
17
+ /**
18
+ * Value types allowed on a `prop:*`. Primitives plus the writable
19
+ * non-primitive DOM-object props worth exposing:
20
+ *
21
+ * - `HTMLMediaElement.srcObject`
22
+ * - `HTMLButtonElement.popoverTargetElement` / `commandForElement` (and the same via
23
+ * `PopoverTargetAttributes` mixin on `HTMLInputElement`)
24
+ */
25
+ export type PropValue =
26
+ | string
27
+ | number
28
+ | boolean
29
+ | null
30
+ | MediaStream
31
+ | MediaSource
32
+ | Blob
33
+ | File
34
+ | Date
35
+ | Element;
36
+
37
+ /**
38
+ * Ergonomics widening for emitted `prop:*` value types:
39
+ *
40
+ * - general `string` → `string | number` (HTML coerces numbers)
41
+ * - string literal unions (`'on' | 'off'`) stay exact, so users still get autocomplete /
42
+ * narrowing
43
+ * - other types pass through unchanged
44
+ */
45
+ type WidenString<V> = string extends V ? string | number : V;
46
+ export type WidenPropValue<V> = [V] extends [string] ? WidenString<V> : V;
47
+
48
+ /**
49
+ * Structurally identical → `Y`; distinct → `N`. Used by `IsReadonlyKey` to detect
50
+ * readonly keys by comparing `Pick<T, K>` with `Readonly<Pick<T, K>>`.
51
+ */
52
+ export type IfEquals<A, B, Y = unknown, N = never> =
53
+ (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? Y : N;
54
+
55
+ /**
56
+ * True when `K` is readonly on `T`. Singleton-constant properties (e.g.
57
+ * `tagName: "INPUT"`, `nodeType: 1`) are always `readonly` in `lib.dom.d.ts`, so this
58
+ * single check covers both readonly and singleton-literal cases.
59
+ */
60
+ export type IsReadonlyKey<T, K extends keyof T> = IfEquals<
61
+ Pick<T, K>,
62
+ Readonly<Pick<T, K>>,
63
+ true,
64
+ false
65
+ >;
66
+
67
+ /**
68
+ * Resolves to the `prop:K` string literal when `K` is a writable, element-specific
69
+ * property suitable for a `prop:*` attribute; otherwise resolves to `never` so the
70
+ * key is filtered out of the resulting mapped type.
71
+ *
72
+ * Filters out:
73
+ *
74
+ * - base-class keys (via `SkipPropsFrom`)
75
+ * - aria-* keys (already typed via `AriaAttributes`)
76
+ * - readonly keys
77
+ * - keys whose value types fall outside `PropValue`
78
+ * - the generic `string` index signature (e.g. `HTMLFormElement[name: string]: any`),
79
+ * which would otherwise shadow every key with an `any`-typed `prop:*`
80
+ */
81
+ export type PropKey<T, K extends keyof T> = K extends keyof SkipPropsFrom
82
+ ? never
83
+ : K extends string
84
+ ? string extends K
85
+ ? never
86
+ : K extends `aria${string}`
87
+ ? never
88
+ : T[K] extends PropValue
89
+ ? IsReadonlyKey<T, K> extends true
90
+ ? never
91
+ : `prop:${K}`
92
+ : never
93
+ : never;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * This node script naively takes `jsx-h.d.ts` as source and writes a new `jsx.d.ts`:
3
+ *
4
+ * - Takes `jsx-h.d.ts` as source
5
+ * - Removes `FunctionElement` from `type Element`
6
+ * - Strips `FunctionMaybe` from elements attributes
7
+ * - Writes a new `jsx.d.ts`
8
+ *
9
+ * @see https://github.com/ryansolid/dom-expressions/issues/408
10
+ */
11
+
12
+ import fs from "fs";
13
+ import { execSync as $ } from "child_process";
14
+
15
+ process.chdir("packages/runtime/src");
16
+
17
+ // ensures source is always pretty printed at commit and free of errors
18
+
19
+ $(`prettier "./jsx-h.d.ts" --write`);
20
+
21
+ // copy source to temp file
22
+
23
+ fs.copyFileSync("./jsx-h.d.ts", "./jsx-h.temp.d.ts");
24
+
25
+ // make each property a one liner in temp file
26
+
27
+ $(`prettier "./jsx-h.temp.d.ts" --write --no-editorconfig --print-width 100000`);
28
+
29
+ // read source
30
+
31
+ const source = fs.readFileSync("./jsx-h.temp.d.ts").toString().split("\n");
32
+
33
+ // remove `-h` types
34
+
35
+ /**
36
+ * Unwraps every occurrence of `FunctionMaybe<X>` → `X` in a line, with balanced `<>`
37
+ * matching. Handles nested generics like `FunctionMaybe<WidenPropValue<T[K]>>`, which
38
+ * the previous `[^>]+` regex could not match.
39
+ */
40
+ function unwrapFunctionMaybe(line) {
41
+ const marker = "FunctionMaybe<";
42
+ let out = "";
43
+ let i = 0;
44
+ while (i < line.length) {
45
+ const idx = line.indexOf(marker, i);
46
+ if (idx === -1) {
47
+ out += line.slice(i);
48
+ break;
49
+ }
50
+ out += line.slice(i, idx);
51
+ let depth = 1;
52
+ let j = idx + marker.length;
53
+ while (j < line.length && depth > 0) {
54
+ const c = line[j];
55
+ if (c === "<") depth++;
56
+ else if (c === ">") depth--;
57
+ if (depth > 0) j++;
58
+ }
59
+ // `j` now points at the closing `>` that matches `FunctionMaybe<`.
60
+ out += line.slice(idx + marker.length, j);
61
+ i = j + 1;
62
+ }
63
+ return out;
64
+ }
65
+
66
+ for (let i = 0; i < source.length; i++) {
67
+ const line = source[i].trim();
68
+
69
+ if (line.startsWith("type Element")) {
70
+ // remove `| FunctionElement` from 'type Element'
71
+ source[i] = line.replace("| FunctionElement", "");
72
+ } else if (!line.startsWith("type FunctionMaybe") && line.includes("FunctionMaybe")) {
73
+ // unwrap `FunctionMaybe<X>`
74
+ source[i] = unwrapFunctionMaybe(source[i]);
75
+ }
76
+ }
77
+
78
+ // write result
79
+
80
+ const banner = `/**
81
+ THIS FILE IS GENERATED BY \`./jsx-update.mjs\`.
82
+ PLEASE UPDATE \`jsx-h.d.ts\` INSTEAD AND RUN \`pnpm jsx-sync-types\`.
83
+ */
84
+
85
+ `;
86
+ fs.writeFileSync("./jsx.d.ts", banner + source.join("\n"));
87
+
88
+ // reformat file
89
+
90
+ $(`prettier "./jsx.d.ts" --write`);
91
+
92
+ // discard temporal file
93
+
94
+ fs.unlink("./jsx-h.temp.d.ts", () => {
95
+ console.log("DONE\n");
96
+ });