Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

--------------------------------------------------------------------------------

## [0.3.1] - 2024-10-09

### Added

- Context functions now also return results.
- `version` table with current version.

--------------------------------------------------------------------------------

## [0.3.0] - 2024-10-06

### Added
Expand Down
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ Vide for roblox-ts brings JSX support to the library. As a result, this extensio

> [!TIP]
>
> - Vide JSX adds new components for syntax sugar, including `<Show>`, `<Switch>`/`<Case>`, `<For>`, and `<Index>`.
> - Use the `action` prop to create a Vide action that gets the reference of the rendered element.
> - Vide JSX adds new components for syntax sugar, including `<Show>`, `<Switch>`/`<Case>`, `<For>`/`<Index>`, and `<Provider>`.
> - Use the `action` prop to create a Vide action that receives the new instance as an argument.
> - `switch` is a reserved keyword in TypeScript, so the `switch()` function is exposed under the alias `match()`.

### Installation
Expand All @@ -60,8 +60,8 @@ To use JSX with Vide, you need to configure the `jsx` option in your `tsconfig.j
```

> [!NOTE]
> Custom JSX factories are available in an unreleased version of roblox-ts.<br>
> You can install it by running `npm install -D roblox-ts@next`.
> Vide JSX requires roblox-ts version 3.0 or higher.
> You can update roblox-ts by running `npm install -D roblox-ts@latest`.

### Code sample

Expand Down Expand Up @@ -138,3 +138,23 @@ const items = source(["a", "b", "c"]);
}}
</Index>;
```

### `<Provider>`

A component that renders its children with the `value` prop assigned to the context. The value can be accessed by calling the `context` function while the `children` function is running.

`<Provider>` is syntax sugar for `context(value, () => children)`.

> [!NOTE]
> The context function must be called within the top-level of a component. Calling it within an effect or on a new thread may return the default value.

```tsx
const theme = context("light");

<Provider context={theme} value="dark">
{() => {
const value = theme();
return <textbutton Text={value} />;
}}
</Provider>;
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rbxts/vide",
"version": "0.4.6",
"version": "0.5.7",
"description": "A reactive Luau library for creating UI",
"main": "src/init.lua",
"types": "src/index.d.ts",
Expand Down
23 changes: 20 additions & 3 deletions src/components.luau
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
local context = require(script.Parent.context)
local indexes, values = require(script.Parent.maps)()
local show = require(script.Parent.show)
local switch = require(script.Parent.switch)
local indexes, values = require(script.Parent.maps)()

type Context<T> = context.Context<T>

type Case = {
match: any,
Expand Down Expand Up @@ -29,10 +32,15 @@ local function Switch(props: {
condition: () -> any,
children: { Case },
})
local children = props.children :: { [any]: any }
local map = {}

for _, node in props.children do
map[node.match] = node.children
if children.match then
map[children.match] = children.children
else
for _, node in children do
map[node.match] = node.children
end
end

return switch(props.condition)(map)
Expand All @@ -50,11 +58,20 @@ local function Show(props: {
return show(props.when, props.children, props.fallback)
end

local function Provider<T>(props: {
context: Context<T>,
value: T,
children: () -> any,
})
return props.context(props.value, props.children)
end

return {
Fragment = Fragment,
Switch = Switch,
Case = Case,
For = For,
Index = Index,
Show = Show,
Provider = Provider,
}
6 changes: 4 additions & 2 deletions src/context.luau
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local push_scope = graph.push_scope
local pop_scope = graph.pop_scope
local set_context = graph.set_context

export type Context<T> = (() -> T) & ((T, () -> ()) -> ())
export type Context<T> = (() -> T) & (<U>(T, () -> U) -> U)

local nil_symbol = newproxy()
local count = 0
Expand All @@ -21,7 +21,7 @@ local function context<T>(...: T): Context<T>
local has_default = select("#", ...) > 0
local default_value = ...

return function(...)
return function<T>(...): any -- todo: fix type error
local scope: Node<unknown>? | false = get_scope()

if select("#", ...) == 0 then -- get
Expand Down Expand Up @@ -66,6 +66,8 @@ local function context<T>(...: T): Context<T>
if not ok then
throw(`error while running context:\n\n{result}`)
end

return result
end

return nil :: any
Expand Down
Loading
Loading