@firsthandjs/jsx-runtime 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Firsthand contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # @firsthandjs/jsx-runtime
2
+
3
+ Runtime JSX for environments where the Firsthand compiler is not configured: a
4
+ REPL, a test that imports TSX directly, a tool that transpiles with
5
+ `jsxImportSource`.
6
+
7
+ **Documentation:** [guide](https://github.com/firsthandjs/firsthand/blob/main/docs/guide/01-getting-started.md) · [API reference](https://github.com/firsthandjs/firsthand/blob/main/docs/reference/jsx-runtime.md) · [all docs](https://github.com/firsthandjs/firsthand/blob/main/docs/README.md)
8
+
9
+ It produces real DOM through the same protocol as the compiled output — there
10
+ is no second semantics and no second runtime. What it cannot do is hoist static
11
+ markup into a `<template>`, and it cannot see an expression that a JSX call has
12
+ already evaluated, so a dynamic value must be written as a thunk:
13
+
14
+ ```tsx
15
+ <p>{() => count.value}</p>
16
+ ```
17
+
18
+ The compiler writes those thunks for you. Use it for production.
19
+
20
+ Full documentation: the [repository README](../../README.md).
21
+
22
+ MIT licensed.
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Runtime JSX.
3
+ *
4
+ * This is the fallback path for environments where the Firsthand compiler is not
5
+ * configured (a REPL, a test that imports TSX directly, a tool that transpiles
6
+ * with `jsxImportSource`). It produces real DOM through the same protocol as
7
+ * the compiled output — there is no second semantics and no second runtime.
8
+ *
9
+ * What it cannot do is hoist static markup into a `<template>`: it creates
10
+ * elements one at a time. The compiled path is what the performance claims are
11
+ * measured against, and the README says so.
12
+ *
13
+ * One convention exists only here: a **function value** in an attribute or
14
+ * child position is treated as a dynamic thunk, because a runtime JSX call has
15
+ * already evaluated its arguments and cannot see the expression. The compiler
16
+ * produces those thunks itself, so compiled code never relies on this.
17
+ */
18
+ export declare const Fragment: unique symbol;
19
+ type Props = Record<string, unknown>;
20
+ export declare function jsx(type: unknown, props: Props): unknown;
21
+ export declare const jsxs: typeof jsx;
22
+ export declare const jsxDEV: typeof jsx;
23
+ /**
24
+ * JSX typings for Firsthand.
25
+ *
26
+ * Three things make TSX behave here without casts at the use site:
27
+ *
28
+ * - `JSX.Element` is the runtime's own `View` type, so what a component returns
29
+ * and what the runtime accepts are the same type rather than two
30
+ * descriptions of each other.
31
+ * - `JSX.IntrinsicAttributes` carries `key`, which every element may take and
32
+ * which the list part consumes — it never reaches a component as a prop.
33
+ * - Every attribute explicitly admits `undefined`, because the project compiles
34
+ * with `exactOptionalPropertyTypes` and `class={active ? 'on' : undefined}`
35
+ * has to be ordinary code.
36
+ *
37
+ * Intrinsic elements are typed from the DOM lib, so `value`, `disabled` and
38
+ * friends keep their real types and their completions.
39
+ */
40
+ type EventHandler<E extends Element, Ev extends Event> = (event: Ev & {
41
+ currentTarget: E;
42
+ target: Element;
43
+ }) => void;
44
+ type StyleValue = string | Record<string, string | number | null | undefined>;
45
+ type ClassValue = string | Record<string, unknown>;
46
+ /** A value, or a thunk producing it (runtime JSX), or absent. */
47
+ type Attribute<T> = T | (() => T) | undefined;
48
+ /** Like `Partial<T>`, but explicit `undefined` is allowed and thunks are too. */
49
+ type OptionalAttributes<T> = {
50
+ [K in keyof T]?: Attribute<T[K]>;
51
+ };
52
+ interface FirsthandAttributes<E extends Element> {
53
+ /**
54
+ * Consumed by the keyed list part; it never reaches a component as a prop.
55
+ *
56
+ * Declared here as well as in `JSX.IntrinsicAttributes` because TypeScript
57
+ * only consults the latter for value-based elements.
58
+ */
59
+ key?: string | number | bigint | undefined;
60
+ class?: Attribute<ClassValue>;
61
+ className?: Attribute<ClassValue>;
62
+ style?: Attribute<StyleValue>;
63
+ id?: Attribute<string>;
64
+ title?: Attribute<string>;
65
+ role?: Attribute<string>;
66
+ tabindex?: Attribute<number | string>;
67
+ hidden?: Attribute<boolean>;
68
+ /** Receives the element once it exists. */
69
+ ref?: ((element: E) => void) | undefined;
70
+ children?: unknown;
71
+ onClick?: EventHandler<E, MouseEvent> | undefined;
72
+ onDblClick?: EventHandler<E, MouseEvent> | undefined;
73
+ onInput?: EventHandler<E, InputEvent> | undefined;
74
+ onChange?: EventHandler<E, Event> | undefined;
75
+ onSubmit?: EventHandler<E, SubmitEvent> | undefined;
76
+ onKeyDown?: EventHandler<E, KeyboardEvent> | undefined;
77
+ onKeyUp?: EventHandler<E, KeyboardEvent> | undefined;
78
+ onFocusIn?: EventHandler<E, FocusEvent> | undefined;
79
+ onFocusOut?: EventHandler<E, FocusEvent> | undefined;
80
+ onPointerDown?: EventHandler<E, PointerEvent> | undefined;
81
+ onPointerUp?: EventHandler<E, PointerEvent> | undefined;
82
+ onMouseOver?: EventHandler<E, MouseEvent> | undefined;
83
+ onMouseOut?: EventHandler<E, MouseEvent> | undefined;
84
+ }
85
+ /** DOM properties of the element that Firsthand does not already describe. */
86
+ type DomAttributes<E extends Element> = OptionalAttributes<Omit<E, keyof FirsthandAttributes<E> | 'style' | 'children' | keyof Node | keyof Element>>;
87
+ type Escapes = {
88
+ [key: `prop:${string}`]: unknown;
89
+ [key: `attr:${string}`]: unknown;
90
+ [key: `on${string}:${string}`]: (event: Event) => void;
91
+ [key: `data-${string}`]: Attribute<string | number | boolean | null>;
92
+ [key: `aria-${string}`]: Attribute<string | number | boolean | null>;
93
+ };
94
+ declare global {
95
+ namespace JSX {
96
+ /**
97
+ * What a component or a dynamic expression may produce. Aliased to the
98
+ * runtime's own `View`, so TSX and the runtime agree by construction.
99
+ */
100
+ type Element = import('@firsthandjs/dom').View;
101
+ /**
102
+ * Element types from another framework.
103
+ *
104
+ * Empty here, and deliberately an interface: a package that teaches Firsthand
105
+ * to render something it does not own — `@firsthandjs/react/auto`, say — adds
106
+ * its own key by declaration merging, and only a project that imports that
107
+ * package sees it. `keyof` an empty interface is `never`, so this
108
+ * contributes nothing until somebody opts in, and no framework is named in
109
+ * this file.
110
+ */
111
+ interface ForeignElementTypes {
112
+ }
113
+ /**
114
+ * What TSX accepts as an element type.
115
+ *
116
+ * Declared rather than left to TypeScript's default so that the foreign
117
+ * types above can be part of it.
118
+ */
119
+ type ElementType = keyof IntrinsicElements | ((props: any) => Element) | ForeignElementTypes[keyof ForeignElementTypes];
120
+ /** Available on every element, including components. Consumed by the list part. */
121
+ interface IntrinsicAttributes {
122
+ key?: string | number | bigint | undefined;
123
+ }
124
+ interface ElementChildrenAttribute {
125
+ children: unknown;
126
+ }
127
+ type IntrinsicElements = {
128
+ [K in keyof HTMLElementTagNameMap]: FirsthandAttributes<HTMLElementTagNameMap[K]> & DomAttributes<HTMLElementTagNameMap[K]> & Escapes;
129
+ } & {
130
+ [K in keyof SVGElementTagNameMap]: FirsthandAttributes<SVGElementTagNameMap[K]> & Escapes;
131
+ } & {
132
+ /** Custom elements, including the ones `defineElement` registers. */
133
+ [tag: `${string}-${string}`]: FirsthandAttributes<HTMLElement> & Escapes;
134
+ };
135
+ }
136
+ }
137
+ export {};
138
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{applyProp as s,createComponent as E,insert as f,isComponent as m,part as u}from"@firsthandjs/dom/internal";import{bind as p}from"@firsthandjs/core";var y=Symbol.for("firsthand.fragment");function d(n,e){if(typeof n=="string")return b(n,e);if(n===y){let t=e.children;return Array.isArray(t)?t.map(r=>typeof r=="function"?u(r):r):typeof t=="function"?u(t):t??null}if(m(n))return E(n,e);if(typeof n=="function")return n(e);throw new TypeError(`Not a valid JSX element type: ${String(n)}`)}var v=d,k=d;function b(n,e){let t=document.createElement(n);for(let i in e){let o=e[i];i!=="children"&&(typeof o=="function"&&!i.startsWith("on")&&i!=="ref"?p(()=>{s(t,i,o())}):s(t,i,o))}let r=e.children;return r!==void 0&&l(t,r),t}function l(n,e){if(Array.isArray(e)){for(let t=0;t<e.length;t++)a(n,e[t]);return}a(n,e)}function a(n,e){if(typeof e=="function"){let t=document.createTextNode("");n.appendChild(t),f(n,e,t);return}if(!(e==null||typeof e=="boolean")){if(Array.isArray(e)){l(n,e);return}if(typeof e=="object"&&typeof e.nodeType=="number"){n.appendChild(e);return}n.appendChild(document.createTextNode(String(e)))}}export{y as Fragment,d as jsx,k as jsxDEV,v as jsxs};
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@firsthandjs/jsx-runtime",
3
+ "version": "0.1.0",
4
+ "description": "Runtime JSX entry points for Firsthand, for environments without the compiler.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./jsx-runtime": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./jsx-dev-runtime": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "types": "./dist/index.d.ts",
23
+ "main": "./dist/index.js",
24
+ "files": [
25
+ "dist",
26
+ "README.md",
27
+ "LICENSE"
28
+ ],
29
+ "dependencies": {
30
+ "@firsthandjs/core": "0.1.0",
31
+ "@firsthandjs/dom": "0.1.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=20.11.0"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public",
38
+ "provenance": true
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/firsthandjs/firsthand.git",
43
+ "directory": "packages/jsx-runtime"
44
+ },
45
+ "bugs": {
46
+ "url": "https://github.com/firsthandjs/firsthand/issues"
47
+ },
48
+ "homepage": "https://github.com/firsthandjs/firsthand#readme",
49
+ "keywords": [
50
+ "reactive",
51
+ "signals",
52
+ "fine-grained",
53
+ "web-components",
54
+ "ui",
55
+ "framework",
56
+ "jsx",
57
+ "no-virtual-dom"
58
+ ]
59
+ }