opencode-context-indicator 1.7.1 → 1.8.1

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/tui-h.ts ADDED
@@ -0,0 +1,73 @@
1
+ // lib/tui-h.ts
2
+ //
3
+ // The two tree builders every TUI surface in this package uses instead of JSX.
4
+ //
5
+ // WHY NO JSX (do not "simplify" this back):
6
+ // OpenCode installs npm plugins inside a `node_modules` tree
7
+ // (~/.cache/opencode/npm/<name>@<version>/<ts>/node_modules/<name>). For such
8
+ // paths the host deliberately skips its Solid/Babel JSX transform (sourceFilter
9
+ // in @opentui/solid/scripts/solid-plugin.js excludes node_modules, upstream
10
+ // anomalyco/opencode#33884). A JSX-compiled file in that position also needs
11
+ // `@opentui/solid` to be installed next to it just to resolve its emitted
12
+ // jsx-runtime import. Files WITHOUT JSX syntax are unaffected: their literal
13
+ // `@opentui/solid/jsx-runtime` import IS rewritten by the host to the
14
+ // in-process OpenTUI module (`nodeModulesRuntimeSpecifiers: true` in
15
+ // DEFAULT_RUNTIME_PLUGIN_REWRITE_OPTIONS of @opentui/core), so the tree stays
16
+ // reactive and the package needs no runtime dependency at all.
17
+ //
18
+ // Therefore: no JSX syntax anywhere in this package's TUI files, and no
19
+ // `@jsxImportSource` pragma. Build the tree with jsx() and mark every DYNAMIC
20
+ // prop as a getter — that is exactly what the Solid compiler emits for
21
+ // `prop={expr}` in JSX, so the runtime semantics are identical:
22
+ //
23
+ // <text fg={base()}>{line}</text>
24
+ // -> h("text", { get fg() { return base() }, get children() { return line } })
25
+ //
26
+ // A plain (non-getter) value is read ONCE, like a literal attribute in JSX.
27
+ // Children follow the same rule: an array of elements is fine (it is diffed by
28
+ // the runtime), a function child is a reactive accessor.
29
+ //
30
+ // RELATIVE IMPORTS OF .ts FILES MUST CARRY THE EXTENSION (`./tui-h.ts`, not
31
+ // `./tui-h`): the host decides which files get the runtime-specifier rewrite by
32
+ // walking the import graph with `import.meta.resolve(specifier, importer)`,
33
+ // which does not probe extensions. An extensionless import is simply not
34
+ // followed, so that file keeps the literal `@opentui/solid/jsx-runtime` import
35
+ // and the npm install dies with `Cannot find package '@opentui/solid'`.
36
+ // test/prepublish.mjs gate (b) enforces this.
37
+ //
38
+ // This module is the only place that imports the jsx runtime, so the allowlist
39
+ // in test/prepublish.mjs stays short.
40
+ //
41
+ // NEVER pass a `key` prop to h()/c(). The jsx runtime's normalizeProps() sees
42
+ // `key`, strips it with `{ ...rest }`, and the spread turns every getter into a
43
+ // plain value read ONCE — the whole subtree freezes with no error. (No list in
44
+ // this package is keyed; if you ever need one, do not add `key` here.)
45
+
46
+ import { jsx } from "@opentui/solid/jsx-runtime"
47
+ import type { JSX } from "@opentui/solid/jsx-runtime"
48
+
49
+ /** An intrinsic OpenTUI element: `h("text", { fg, children })`. */
50
+ export function h<K extends string>(
51
+ tag: K,
52
+ props: K extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[K] : never,
53
+ ): JSX.Element {
54
+ return jsx(tag, props as unknown as Record<string, unknown>)
55
+ }
56
+
57
+ /**
58
+ * A component: `c(Show, { get when() {...}, get fallback() {...} })`.
59
+ *
60
+ * The component's own prop type is intentionally not enforced here: host
61
+ * components (Show, and any OpenTUI component) are generic and their unions do
62
+ * not survive inference through a wrapper, while the shapes used in this
63
+ * package are small and covered by the e2e liveness check.
64
+ */
65
+ export function c<C extends (props: any) => unknown, P extends object>(
66
+ component: C,
67
+ props: P,
68
+ ): JSX.Element {
69
+ return jsx(
70
+ component as unknown as (props: Record<string, unknown>) => unknown,
71
+ props as unknown as Record<string, unknown>,
72
+ )
73
+ }