rask-ui 0.5.1 → 0.7.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/README.md +134 -162
- package/dist/component.d.ts +2 -2
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +4 -4
- package/dist/createComputed.js +2 -2
- package/dist/createEffect.js +2 -2
- package/dist/createTask.d.ts +30 -0
- package/dist/createTask.d.ts.map +1 -0
- package/dist/createTask.js +77 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.js +1 -1
- package/logo.png +0 -0
- package/package.json +3 -2
- package/swc-plugin/target/wasm32-wasip1/release/libswc_plugin_rask_component.d +1 -1
- package/swc-plugin/target/wasm32-wasip1/release/swc_plugin_rask_component.d +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,29 @@ A lightweight reactive component library that combines the simplicity of observa
|
|
|
10
10
|
npm install rask-ui
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 📢 Open For Feedback
|
|
16
|
+
|
|
17
|
+
**RASK is feature-complete and ready for community feedback!**
|
|
18
|
+
|
|
19
|
+
The core implementation is finished, including:
|
|
20
|
+
- ✅ Inferno-based reconciler for powerful UI expression
|
|
21
|
+
- ✅ JSX transformation plugin (Inferno JSX + stateful components)
|
|
22
|
+
- ✅ Reactive primitives for simple state management
|
|
23
|
+
|
|
24
|
+
**Before the official release, we need your input:**
|
|
25
|
+
- Would a library like this be valuable for your projects?
|
|
26
|
+
- Is the API clear and intuitive?
|
|
27
|
+
- Is the documentation helpful and complete?
|
|
28
|
+
- Does the approach resonate with you?
|
|
29
|
+
|
|
30
|
+
**[Share your feedback by creating an issue →](https://github.com/christianalfoni/rask/issues/new)**
|
|
31
|
+
|
|
32
|
+
Your feedback will directly shape the final release. All perspectives welcome!
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
13
36
|
## The Itch with Modern UI Frameworks
|
|
14
37
|
|
|
15
38
|
Modern UI frameworks present developers with a fundamental tradeoff between state management and UI expression:
|
|
@@ -68,79 +91,24 @@ RASK gives you:
|
|
|
68
91
|
|
|
69
92
|
## Getting Started
|
|
70
93
|
|
|
71
|
-
|
|
94
|
+
The fastest way to get started is using `create-rask-ui`:
|
|
72
95
|
|
|
73
96
|
```bash
|
|
74
|
-
npm
|
|
97
|
+
npm create rask-ui my-app
|
|
98
|
+
cd my-app
|
|
99
|
+
npm run dev
|
|
75
100
|
```
|
|
76
101
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
RASK uses a custom Vite plugin powered by SWC for optimal JSX transformation. This plugin transforms JSX to Inferno's highly optimized `createVNode` calls and automatically converts function components to RASK's reactive component pattern.
|
|
102
|
+
This will scaffold a new Vite project with RASK UI pre-configured and ready to go. You'll be prompted to choose between TypeScript or JavaScript.
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Create or update your `vite.config.ts`:
|
|
84
|
-
|
|
85
|
-
```ts
|
|
86
|
-
import { defineConfig } from 'vite';
|
|
87
|
-
import { raskPlugin } from 'rask-ui/plugin';
|
|
88
|
-
|
|
89
|
-
export default defineConfig({
|
|
90
|
-
plugins: [raskPlugin()],
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Plugin Options:**
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
raskPlugin({
|
|
98
|
-
// Enable/disable function component transformation
|
|
99
|
-
// Default: true
|
|
100
|
-
transformComponents: true,
|
|
101
|
-
|
|
102
|
-
// Add imports for Inferno utilities (usually not needed)
|
|
103
|
-
// Default: false
|
|
104
|
-
imports: false,
|
|
105
|
-
|
|
106
|
-
// Package to import from when transformComponents is enabled
|
|
107
|
-
// Default: "rask-ui"
|
|
108
|
-
importSource: "rask-ui",
|
|
109
|
-
|
|
110
|
-
// Define all arguments for createVNode (for debugging)
|
|
111
|
-
// Default: false
|
|
112
|
-
defineAllArguments: false,
|
|
113
|
-
})
|
|
114
|
-
```
|
|
104
|
+
### What's Included
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
The scaffolded project includes:
|
|
117
107
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"compilerOptions": {
|
|
123
|
-
"jsx": "react-jsx",
|
|
124
|
-
"jsxImportSource": "rask-ui",
|
|
125
|
-
"moduleResolution": "bundler",
|
|
126
|
-
"target": "ES2022",
|
|
127
|
-
"module": "ESNext",
|
|
128
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"]
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
**Key settings:**
|
|
134
|
-
|
|
135
|
-
- `"jsx": "react-jsx"` - Tells TypeScript to use the new JSX transform for type checking
|
|
136
|
-
- `"jsxImportSource": "rask-ui"` - Points to RASK's JSX runtime for type definitions
|
|
137
|
-
- `"moduleResolution": "bundler"` - Required for Vite
|
|
138
|
-
|
|
139
|
-
**How it works:**
|
|
140
|
-
|
|
141
|
-
- **TypeScript**: Type-checks JSX using RASK's type definitions (imported from Inferno)
|
|
142
|
-
- **SWC Plugin**: Transforms JSX to Inferno's `createVNode` calls at build time
|
|
143
|
-
- The result: You get full type safety with zero runtime overhead
|
|
108
|
+
- ✅ Vite configured with the RASK plugin
|
|
109
|
+
- ✅ TypeScript or JavaScript with proper JSX configuration
|
|
110
|
+
- ✅ Hot Module Replacement (HMR) working out of the box
|
|
111
|
+
- ✅ Sample counter component to get you started
|
|
144
112
|
|
|
145
113
|
### Basic Example
|
|
146
114
|
|
|
@@ -173,7 +141,7 @@ function MyComponent(props) {
|
|
|
173
141
|
// SETUP PHASE - Runs once when component is created
|
|
174
142
|
const state = createState({ value: props.initial });
|
|
175
143
|
|
|
176
|
-
|
|
144
|
+
createMountEffect(() => {
|
|
177
145
|
console.log("Component mounted!");
|
|
178
146
|
});
|
|
179
147
|
|
|
@@ -250,7 +218,7 @@ When `state.count` changes in Parent, only Child re-renders because it accesses
|
|
|
250
218
|
|
|
251
219
|
### One Rule To Accept
|
|
252
220
|
|
|
253
|
-
**RASK has observable primitives**: Never destructure reactive objects (state, props, context values,
|
|
221
|
+
**RASK has observable primitives**: Never destructure reactive objects (state, props, context values, tasks). Destructuring extracts plain values and breaks reactivity.
|
|
254
222
|
|
|
255
223
|
```tsx
|
|
256
224
|
// ❌ BAD - Destructuring breaks reactivity
|
|
@@ -296,9 +264,7 @@ Reactive objects are implemented using JavaScript Proxies. When you access a pro
|
|
|
296
264
|
- `createState()` - Never destructure state objects
|
|
297
265
|
- Props - Never destructure component props
|
|
298
266
|
- `createContext().get()` - Never destructure context values
|
|
299
|
-
- `
|
|
300
|
-
- `createQuery()` - Never destructure query objects
|
|
301
|
-
- `createMutation()` - Never destructure mutation objects
|
|
267
|
+
- `createTask()` - Never destructure task objects
|
|
302
268
|
- `createView()` - Never destructure view objects
|
|
303
269
|
- `createComputed()` - Never destructure computed objects
|
|
304
270
|
|
|
@@ -614,15 +580,15 @@ function BatchingExample() {
|
|
|
614
580
|
|
|
615
581
|
### Lifecycle Hooks
|
|
616
582
|
|
|
617
|
-
#### `
|
|
583
|
+
#### `createMountEffect(callback)`
|
|
618
584
|
|
|
619
585
|
Registers a callback to run after the component is mounted to the DOM.
|
|
620
586
|
|
|
621
587
|
```tsx
|
|
622
|
-
import {
|
|
588
|
+
import { createMountEffect } from "rask-ui";
|
|
623
589
|
|
|
624
590
|
function Example() {
|
|
625
|
-
|
|
591
|
+
createMountEffect(() => {
|
|
626
592
|
console.log("Component mounted!");
|
|
627
593
|
});
|
|
628
594
|
|
|
@@ -641,12 +607,12 @@ function Example() {
|
|
|
641
607
|
|
|
642
608
|
---
|
|
643
609
|
|
|
644
|
-
#### `
|
|
610
|
+
#### `createCleanup(callback)`
|
|
645
611
|
|
|
646
612
|
Registers a callback to run when the component is unmounted.
|
|
647
613
|
|
|
648
614
|
```tsx
|
|
649
|
-
import {
|
|
615
|
+
import { createCleanup } from "rask-ui";
|
|
650
616
|
|
|
651
617
|
function Example() {
|
|
652
618
|
const state = createState({ time: Date.now() });
|
|
@@ -655,7 +621,7 @@ function Example() {
|
|
|
655
621
|
state.time = Date.now();
|
|
656
622
|
}, 1000);
|
|
657
623
|
|
|
658
|
-
|
|
624
|
+
createCleanup(() => {
|
|
659
625
|
clearInterval(interval);
|
|
660
626
|
});
|
|
661
627
|
|
|
@@ -716,58 +682,38 @@ function Child() {
|
|
|
716
682
|
|
|
717
683
|
### Async Data Management
|
|
718
684
|
|
|
719
|
-
#### `
|
|
685
|
+
#### `createTask<T, P>(task)`
|
|
720
686
|
|
|
721
|
-
Creates reactive
|
|
687
|
+
Creates a low-level reactive primitive for managing async operations with loading, error, and result states. This is a generic primitive that gives you full control over async state management without prescribing patterns.
|
|
722
688
|
|
|
723
689
|
```tsx
|
|
724
|
-
import {
|
|
690
|
+
import { createTask } from "rask-ui";
|
|
725
691
|
|
|
692
|
+
// Simple task without parameters - auto-runs on creation
|
|
726
693
|
function UserProfile() {
|
|
727
|
-
const user =
|
|
694
|
+
const user = createTask(() => fetch("/api/user").then((r) => r.json()));
|
|
728
695
|
|
|
729
|
-
return () =>
|
|
730
|
-
if (user.
|
|
731
|
-
return <p>Loading...</p
|
|
696
|
+
return () => {
|
|
697
|
+
if (user.isRunning) {
|
|
698
|
+
return <p>Loading...</p>;
|
|
732
699
|
}
|
|
733
700
|
|
|
734
701
|
if (user.error) {
|
|
735
|
-
return <p>Error: {user.error}</p
|
|
702
|
+
return <p>Error: {user.error}</p>;
|
|
736
703
|
}
|
|
737
704
|
|
|
738
|
-
return <p>Hello, {user.
|
|
705
|
+
return <p>Hello, {user.result.name}!</p>;
|
|
706
|
+
};
|
|
739
707
|
}
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
**Parameters:**
|
|
743
|
-
|
|
744
|
-
- `promise: Promise<T>` - The promise to track
|
|
745
|
-
|
|
746
|
-
**Returns:** Reactive object with:
|
|
747
|
-
|
|
748
|
-
- `isPending: boolean` - True while promise is pending
|
|
749
|
-
- `value: T | null` - Resolved value (null while pending or on error)
|
|
750
|
-
- `error: string | null` - Error message (null while pending or on success)
|
|
751
|
-
|
|
752
|
-
**States:**
|
|
753
|
-
|
|
754
|
-
- `{ isPending: true, value: null, error: null }` - Loading
|
|
755
|
-
- `{ isPending: false, value: T, error: null }` - Success
|
|
756
|
-
- `{ isPending: false, value: null, error: string }` - Error
|
|
757
|
-
|
|
758
|
-
---
|
|
759
|
-
|
|
760
|
-
#### `createQuery<T>(fetcher)`
|
|
761
|
-
|
|
762
|
-
Creates a query with refetch capability and request cancellation.
|
|
763
|
-
|
|
764
|
-
```tsx
|
|
765
|
-
import { createQuery } from "rask-ui";
|
|
766
708
|
|
|
709
|
+
// Task with parameters - control when to run
|
|
767
710
|
function Posts() {
|
|
768
|
-
const posts =
|
|
711
|
+
const posts = createTask((page: number) =>
|
|
712
|
+
fetch(`/api/posts?page=${page}`).then((r) => r.json())
|
|
713
|
+
);
|
|
714
|
+
|
|
769
715
|
const renderPosts = () => {
|
|
770
|
-
if (posts.
|
|
716
|
+
if (posts.isRunning) {
|
|
771
717
|
return <p>Loading...</p>;
|
|
772
718
|
}
|
|
773
719
|
|
|
@@ -775,61 +721,37 @@ function Posts() {
|
|
|
775
721
|
return <p>Error: {posts.error}</p>;
|
|
776
722
|
}
|
|
777
723
|
|
|
778
|
-
|
|
724
|
+
if (!posts.result) {
|
|
725
|
+
return <p>No posts loaded</p>;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
return posts.result.map((post) => (
|
|
779
729
|
<article key={post.id}>{post.title}</article>
|
|
780
730
|
));
|
|
781
731
|
};
|
|
782
732
|
|
|
783
733
|
return () => (
|
|
784
734
|
<div>
|
|
785
|
-
<button onClick={() => posts.
|
|
786
|
-
<button onClick={() => posts.
|
|
735
|
+
<button onClick={() => posts.run(1)}>Load Page 1</button>
|
|
736
|
+
<button onClick={() => posts.rerun(1)}>Reload Page 1</button>
|
|
787
737
|
{renderPosts()}
|
|
788
738
|
</div>
|
|
789
739
|
);
|
|
790
740
|
}
|
|
791
|
-
```
|
|
792
|
-
|
|
793
|
-
**Parameters:**
|
|
794
|
-
|
|
795
|
-
- `fetcher: () => Promise<T>` - Function that returns a promise
|
|
796
|
-
|
|
797
|
-
**Returns:** Query object with:
|
|
798
|
-
|
|
799
|
-
- `isPending: boolean` - True while fetching
|
|
800
|
-
- `data: T | null` - Fetched data
|
|
801
|
-
- `error: string | null` - Error message
|
|
802
|
-
- `fetch(force?: boolean)` - Refetch data
|
|
803
|
-
- `force: false` (default) - Keep existing data while refetching
|
|
804
|
-
- `force: true` - Clear data before refetching
|
|
805
|
-
|
|
806
|
-
**Features:**
|
|
807
|
-
|
|
808
|
-
- Automatic request cancellation on refetch
|
|
809
|
-
- Keeps old data by default during refetch
|
|
810
|
-
- Automatically fetches on creation
|
|
811
|
-
|
|
812
|
-
---
|
|
813
|
-
|
|
814
|
-
#### `createMutation<T>(mutator)`
|
|
815
|
-
|
|
816
|
-
Creates a mutation for data updates with pending and error states.
|
|
817
|
-
|
|
818
|
-
```tsx
|
|
819
|
-
import { createMutation } from "rask-ui";
|
|
820
741
|
|
|
742
|
+
// Mutation-style usage
|
|
821
743
|
function CreatePost() {
|
|
822
744
|
const state = createState({ title: "", body: "" });
|
|
823
745
|
|
|
824
|
-
const create =
|
|
746
|
+
const create = createTask((data: { title: string; body: string }) =>
|
|
825
747
|
fetch("/api/posts", {
|
|
826
748
|
method: "POST",
|
|
827
749
|
body: JSON.stringify(data),
|
|
828
|
-
}))
|
|
750
|
+
}).then((r) => r.json())
|
|
829
751
|
);
|
|
830
752
|
|
|
831
753
|
const handleSubmit = () => {
|
|
832
|
-
create.
|
|
754
|
+
create.run({ title: state.title, body: state.body });
|
|
833
755
|
};
|
|
834
756
|
|
|
835
757
|
return () => (
|
|
@@ -842,8 +764,8 @@ function CreatePost() {
|
|
|
842
764
|
value={state.body}
|
|
843
765
|
onInput={(e) => (state.body = e.target.value)}
|
|
844
766
|
/>
|
|
845
|
-
<button disabled={create.
|
|
846
|
-
{create.
|
|
767
|
+
<button disabled={create.isRunning}>
|
|
768
|
+
{create.isRunning ? "Creating..." : "Create"}
|
|
847
769
|
</button>
|
|
848
770
|
{create.error && <p>Error: {create.error}</p>}
|
|
849
771
|
</form>
|
|
@@ -851,22 +773,72 @@ function CreatePost() {
|
|
|
851
773
|
}
|
|
852
774
|
```
|
|
853
775
|
|
|
854
|
-
**
|
|
776
|
+
**Type Signatures:**
|
|
855
777
|
|
|
856
|
-
|
|
778
|
+
```tsx
|
|
779
|
+
// Task without parameters - auto-runs on creation
|
|
780
|
+
createTask<T>(task: () => Promise<T>): Task<T, never> & {
|
|
781
|
+
run(): Promise<T>;
|
|
782
|
+
rerun(): Promise<T>;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// Task with parameters - manual control
|
|
786
|
+
createTask<T, P>(task: (params: P) => Promise<T>): Task<T, P> & {
|
|
787
|
+
run(params: P): Promise<T>;
|
|
788
|
+
rerun(params: P): Promise<T>;
|
|
789
|
+
}
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
**Returns:** Task object with reactive state and methods:
|
|
793
|
+
|
|
794
|
+
**State Properties:**
|
|
795
|
+
- `isRunning: boolean` - True while task is executing
|
|
796
|
+
- `result: T | null` - Result of successful execution (null if not yet run, running, or error)
|
|
797
|
+
- `error: string | null` - Error message from failed execution (null if successful or running)
|
|
798
|
+
- `params: P | null` - Current parameters while running (null when idle)
|
|
799
|
+
|
|
800
|
+
**Methods:**
|
|
801
|
+
- `run(params?: P): Promise<T>` - Execute the task, clearing previous result
|
|
802
|
+
- `rerun(params?: P): Promise<T>` - Re-execute the task, keeping previous result until new one arrives
|
|
803
|
+
|
|
804
|
+
**State Transitions:**
|
|
805
|
+
|
|
806
|
+
Initial state (no params):
|
|
807
|
+
```tsx
|
|
808
|
+
{ isRunning: false, params: null, result: null, error: null }
|
|
809
|
+
```
|
|
857
810
|
|
|
858
|
-
|
|
811
|
+
While running:
|
|
812
|
+
```tsx
|
|
813
|
+
{ isRunning: true, result: T | null, params: P, error: null }
|
|
814
|
+
```
|
|
859
815
|
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
816
|
+
Success:
|
|
817
|
+
```tsx
|
|
818
|
+
{ isRunning: false, params: null, result: T, error: null }
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
Error:
|
|
822
|
+
```tsx
|
|
823
|
+
{ isRunning: false, params: null, result: null, error: string }
|
|
824
|
+
```
|
|
864
825
|
|
|
865
826
|
**Features:**
|
|
866
827
|
|
|
867
|
-
- Automatic
|
|
868
|
-
-
|
|
869
|
-
-
|
|
828
|
+
- **Automatic cancellation** - Previous executions are cancelled when a new one starts
|
|
829
|
+
- **Flexible control** - Use `run()` to clear old data or `rerun()` to keep it during loading
|
|
830
|
+
- **Type-safe** - Full TypeScript inference for parameters and results
|
|
831
|
+
- **Auto-run support** - Tasks without parameters run automatically on creation
|
|
832
|
+
- **Generic primitive** - Build your own patterns on top (queries, mutations, etc.)
|
|
833
|
+
|
|
834
|
+
**Usage Patterns:**
|
|
835
|
+
|
|
836
|
+
Use `createTask` as a building block for various async patterns:
|
|
837
|
+
- **Queries**: Tasks that fetch data and can be refetched
|
|
838
|
+
- **Mutations**: Tasks that modify server state
|
|
839
|
+
- **Polling**: Tasks that run periodically
|
|
840
|
+
- **Debounced searches**: Tasks that run based on user input
|
|
841
|
+
- **File uploads**: Tasks that track upload progress
|
|
870
842
|
|
|
871
843
|
---
|
|
872
844
|
|
|
@@ -1223,4 +1195,4 @@ MIT
|
|
|
1223
1195
|
|
|
1224
1196
|
## Why "RASK"?
|
|
1225
1197
|
|
|
1226
|
-
The name comes from Norwegian
|
|
1198
|
+
The name comes from Norwegian meaning "fast" - which captures the essence of this library: fast to write, fast to understand, and fast to run.
|
package/dist/component.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VNode, Component, Props } from "inferno";
|
|
2
2
|
export declare function getCurrentComponent(): RaskComponent<any>;
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
3
|
+
export declare function createMountEffect(cb: () => void): void;
|
|
4
|
+
export declare function createCleanup(cb: () => void): void;
|
|
5
5
|
export type RaskFunctionComponent<P extends Props<any>> = (() => () => VNode) | ((props: P) => () => VNode);
|
|
6
6
|
export declare class RaskComponent<P extends Props<any>> extends Component<P> {
|
|
7
7
|
setup: RaskFunctionComponent<P>;
|
package/dist/component.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EAEN,MAAM,SAAS,CAAC;AAQjB,wBAAgB,mBAAmB,uBAMlC;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EAEN,MAAM,SAAS,CAAC;AAQjB,wBAAgB,mBAAmB,uBAMlC;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,QAM/C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI,QAM3C;AAED,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAClD,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,aAAa,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IAC3D,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,QAAQ,CAEb;IACH,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAUf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACnC,OAAO,CAAC,mBAAmB;IA2D3B,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAG5B;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,GAAG;IAYlC,yBAAyB,IAAI,IAAI;IACjC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;IAerD,MAAM;CAyCP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
|
package/dist/component.js
CHANGED
|
@@ -8,15 +8,15 @@ export function getCurrentComponent() {
|
|
|
8
8
|
}
|
|
9
9
|
return currentComponent;
|
|
10
10
|
}
|
|
11
|
-
export function
|
|
11
|
+
export function createMountEffect(cb) {
|
|
12
12
|
if (!currentComponent) {
|
|
13
|
-
throw new Error("Only use
|
|
13
|
+
throw new Error("Only use createMountEffect in component setup");
|
|
14
14
|
}
|
|
15
15
|
currentComponent.onMounts.push(cb);
|
|
16
16
|
}
|
|
17
|
-
export function
|
|
17
|
+
export function createCleanup(cb) {
|
|
18
18
|
if (!currentComponent) {
|
|
19
|
-
throw new Error("Only use
|
|
19
|
+
throw new Error("Only use createCleanup in component setup");
|
|
20
20
|
}
|
|
21
21
|
currentComponent.onCleanups.push(cb);
|
|
22
22
|
}
|
package/dist/createComputed.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCurrentComponent,
|
|
1
|
+
import { getCurrentComponent, createCleanup } from "./component";
|
|
2
2
|
import { getCurrentObserver, Observer, Signal } from "./observation";
|
|
3
3
|
export function createComputed(computed) {
|
|
4
4
|
let currentComponent;
|
|
@@ -18,7 +18,7 @@ export function createComputed(computed) {
|
|
|
18
18
|
signal.notify();
|
|
19
19
|
});
|
|
20
20
|
if (currentComponent) {
|
|
21
|
-
|
|
21
|
+
createCleanup(() => computedObserver.dispose());
|
|
22
22
|
}
|
|
23
23
|
Object.defineProperty(proxy, prop, {
|
|
24
24
|
get() {
|
package/dist/createEffect.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getCurrentComponent,
|
|
1
|
+
import { getCurrentComponent, createCleanup } from "./component";
|
|
2
2
|
import { Observer } from "./observation";
|
|
3
3
|
export function createEffect(cb) {
|
|
4
4
|
let currentComponent;
|
|
@@ -19,7 +19,7 @@ export function createEffect(cb) {
|
|
|
19
19
|
stopObserving();
|
|
20
20
|
};
|
|
21
21
|
if (currentComponent) {
|
|
22
|
-
|
|
22
|
+
createCleanup(() => observer.dispose());
|
|
23
23
|
}
|
|
24
24
|
runEffect();
|
|
25
25
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type Task<T, P> = {
|
|
2
|
+
isRunning: false;
|
|
3
|
+
params: null;
|
|
4
|
+
result: null;
|
|
5
|
+
error: null;
|
|
6
|
+
} | {
|
|
7
|
+
isRunning: true;
|
|
8
|
+
result: T | null;
|
|
9
|
+
params: P;
|
|
10
|
+
error: null;
|
|
11
|
+
} | {
|
|
12
|
+
isRunning: false;
|
|
13
|
+
params: null;
|
|
14
|
+
result: T;
|
|
15
|
+
error: null;
|
|
16
|
+
} | {
|
|
17
|
+
isRunning: false;
|
|
18
|
+
params: null;
|
|
19
|
+
result: null;
|
|
20
|
+
error: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function createTask<T>(task: () => Promise<T>): Task<T, never> & {
|
|
23
|
+
run(): Promise<T>;
|
|
24
|
+
rerun(): Promise<T>;
|
|
25
|
+
};
|
|
26
|
+
export declare function createTask<T, P>(task: (params: P) => Promise<T>): Task<T, P> & {
|
|
27
|
+
run(params: P): Promise<T>;
|
|
28
|
+
rerun(params: P): Promise<T>;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=createTask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTask.d.ts","sourceRoot":"","sources":["../src/createTask.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,IACjB;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;IACjB,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG;IACtE,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACrB,CAAC;AACF,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAC7B,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC9B,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IACd,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9B,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createState } from "./createState";
|
|
2
|
+
export function createTask(task) {
|
|
3
|
+
const state = createState({
|
|
4
|
+
isRunning: false,
|
|
5
|
+
result: null,
|
|
6
|
+
error: null,
|
|
7
|
+
params: null,
|
|
8
|
+
});
|
|
9
|
+
const assign = (newState) => {
|
|
10
|
+
Object.assign(state, newState);
|
|
11
|
+
};
|
|
12
|
+
let currentAbortController;
|
|
13
|
+
const fetch = (params) => {
|
|
14
|
+
currentAbortController?.abort();
|
|
15
|
+
const abortController = (currentAbortController = new AbortController());
|
|
16
|
+
const promise = task(params);
|
|
17
|
+
promise
|
|
18
|
+
.then((result) => {
|
|
19
|
+
if (abortController.signal.aborted) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
assign({
|
|
23
|
+
isRunning: false,
|
|
24
|
+
result,
|
|
25
|
+
error: null,
|
|
26
|
+
params: null,
|
|
27
|
+
});
|
|
28
|
+
})
|
|
29
|
+
.catch((error) => {
|
|
30
|
+
if (abortController.signal.aborted) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
assign({
|
|
34
|
+
isRunning: false,
|
|
35
|
+
result: null,
|
|
36
|
+
error: String(error),
|
|
37
|
+
params: null,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
return promise;
|
|
41
|
+
};
|
|
42
|
+
fetch();
|
|
43
|
+
return {
|
|
44
|
+
get isRunning() {
|
|
45
|
+
return state.isRunning;
|
|
46
|
+
},
|
|
47
|
+
get result() {
|
|
48
|
+
return state.result;
|
|
49
|
+
},
|
|
50
|
+
get error() {
|
|
51
|
+
return state.error;
|
|
52
|
+
},
|
|
53
|
+
get params() {
|
|
54
|
+
return state.params;
|
|
55
|
+
},
|
|
56
|
+
run(params) {
|
|
57
|
+
const promise = fetch(params);
|
|
58
|
+
assign({
|
|
59
|
+
isRunning: true,
|
|
60
|
+
result: null,
|
|
61
|
+
error: null,
|
|
62
|
+
params: (params || null),
|
|
63
|
+
});
|
|
64
|
+
return promise;
|
|
65
|
+
},
|
|
66
|
+
rerun(params) {
|
|
67
|
+
const promise = fetch(params);
|
|
68
|
+
assign({
|
|
69
|
+
isRunning: true,
|
|
70
|
+
result: state.result,
|
|
71
|
+
error: null,
|
|
72
|
+
params: (params || null),
|
|
73
|
+
});
|
|
74
|
+
return promise;
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
export { render } from "./render";
|
|
2
|
-
export {
|
|
2
|
+
export { createCleanup, createMountEffect, RaskComponent } from "./component";
|
|
3
3
|
export { createContext } from "./createContext";
|
|
4
4
|
export { createState } from "./createState";
|
|
5
|
-
export {
|
|
5
|
+
export { createTask } from "./createTask";
|
|
6
6
|
export { ErrorBoundary } from "./error";
|
|
7
|
-
export { createQuery } from "./createQuery";
|
|
8
|
-
export { createMutation } from "./createMutation";
|
|
9
7
|
export { createRef } from "inferno";
|
|
10
8
|
export { createView } from "./createView";
|
|
11
9
|
export { createEffect } from "./createEffect";
|
|
12
10
|
export { createComputed } from "./createComputed";
|
|
13
11
|
export { syncBatch } from "./batch";
|
|
12
|
+
export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, } from "inferno";
|
|
14
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { render } from "./render";
|
|
2
|
-
export {
|
|
2
|
+
export { createCleanup, createMountEffect, RaskComponent } from "./component";
|
|
3
3
|
export { createContext } from "./createContext";
|
|
4
4
|
export { createState } from "./createState";
|
|
5
|
-
export {
|
|
5
|
+
export { createTask } from "./createTask";
|
|
6
6
|
export { ErrorBoundary } from "./error";
|
|
7
|
-
export { createQuery } from "./createQuery";
|
|
8
|
-
export { createMutation } from "./createMutation";
|
|
9
7
|
export { createRef } from "inferno";
|
|
10
8
|
export { createView } from "./createView";
|
|
11
9
|
export { createEffect } from "./createEffect";
|
|
12
10
|
export { createComputed } from "./createComputed";
|
|
13
11
|
export { syncBatch } from "./batch";
|
|
12
|
+
// Re-export Inferno JSX runtime functions so users don't need to install Inferno directly
|
|
13
|
+
export { createVNode, createComponentVNode, createFragment, createTextVNode, normalizeProps, } from "inferno";
|
package/dist/plugin.d.ts
CHANGED
package/dist/plugin.js
CHANGED
|
@@ -8,7 +8,7 @@ const require = createRequire(import.meta.url);
|
|
|
8
8
|
* Vite plugin for transforming JSX to Inferno and function components to RaskComponent classes
|
|
9
9
|
*/
|
|
10
10
|
export function raskPlugin(options = {}) {
|
|
11
|
-
const { transformComponents = true, imports =
|
|
11
|
+
const { transformComponents = true, imports = true, importSource = 'rask-ui', defineAllArguments = false, } = options;
|
|
12
12
|
// Resolve the path to swc-plugin-inferno WASM file
|
|
13
13
|
const infernoPluginPath = require.resolve('swc-plugin-inferno/swc_plugin_inferno.wasm');
|
|
14
14
|
// Resolve the path to our RaskComponent plugin
|
package/logo.png
ADDED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rask-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -25,10 +25,11 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"swc-plugin",
|
|
28
|
+
"logo.png",
|
|
28
29
|
"README.md"
|
|
29
30
|
],
|
|
30
31
|
"scripts": {
|
|
31
|
-
"build": "npm run build:plugin && tsc && cp ../../README.md .",
|
|
32
|
+
"build": "npm run build:plugin && tsc && cp ../../README.md . && cp ../../logo.png .",
|
|
32
33
|
"build:plugin": "cd swc-plugin && cargo build --release --target wasm32-wasip1",
|
|
33
34
|
"dev": "tsc --watch",
|
|
34
35
|
"test": "vitest",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/Users/christianalfoni/Development/
|
|
1
|
+
/Users/christianalfoni/Development/rask-ui/packages/core/swc-plugin/target/wasm32-wasip1/release/libswc_plugin_rask_component.rlib: /Users/christianalfoni/Development/rask-ui/packages/core/swc-plugin/src/lib.rs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
/Users/christianalfoni/Development/
|
|
1
|
+
/Users/christianalfoni/Development/rask-ui/packages/core/swc-plugin/target/wasm32-wasip1/release/swc_plugin_rask_component.wasm: /Users/christianalfoni/Development/rask-ui/packages/core/swc-plugin/src/lib.rs
|