unite()
unite() reaches a reactive variable declared in another file.
No imports, no prop drilling, no context provider, no store boilerplate.
Every let in a file is already published under a namespace taken from that
file's path, and unite() names the one you want.
<!-- pages/demo.html -->
<script>
let counter = 5
let theme = 'dark'
</script>
<p>Counter: {counter}</p>
<!-- pages/other.html -->
<script>
let counter = unite(demo.counter) // Gets counter from demo.html
let theme = unite(demo.theme) // Gets theme from demo.html
</script>
<button onclick="counter++">Increment</button>
<p>Theme: {theme}</p>
There is one variable, not a copy: writing to counter in either file updates
both.
A consumer's write reaches whatever backs the original too, so uniting a
storage() or url() variable still persists it.
Namespaces
The namespace is the file's path, without the extension:
| File | Namespace | Reached as |
|---|---|---|
pages/demo.html |
demo |
unite(demo.counter) |
pages/demo/index.html |
demo |
unite(demo.counter) |
pages/admin/dashboard.html |
admin.dashboard |
unite(admin.dashboard.theme) |
components/Button.html |
Button |
unite(Button.size) |
components/ui/Modal.html |
ui.Modal |
unite(ui.Modal.settings) |
A Worked Example
A theme owned by the layout, persisted to localStorage, and toggled from a component that knows nothing about the layout:
<!-- pages/layout.html -->
<script>
let theme = storage('light')
</script>
<div class="{theme}">
<slot />
</div>
<!-- components/ThemeToggle.html -->
<script>
let theme = unite(layout.theme)
</script>
<button onclick="theme = theme === 'light' ? 'dark' : 'light'">
Toggle Theme
</button>
The toggle's write lands in the layout's variable, the layout re-renders, and
storage() saves it.
Neither file imports the other.
A united value outlives its declaring component: a page that re-mounts adopts the live value instead of resetting it. A variable nobody unites is ordinary local state and re-initialises as usual.
Type Safety
A Vite plugin generates namespace declarations, so unite() autocompletes and
type-checks:
// vite.config.ts
import { namespaceCodegenPlugin } from 'jafjs/vite'
export default defineConfig({
plugins: [
namespaceCodegenPlugin() // Generates src/generated/namespaces.d.ts
]
})
There is no provide() / inject() in JAF. Share across files
with unite(), or pass props down. If you are writing a library and want
its variable names kept out of the app's namespaces, call
unite.set("my-lib").