rask-ui 0.12.0 → 0.12.2

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 CHANGED
@@ -903,13 +903,13 @@ function TodoList() {
903
903
 
904
904
  ```tsx
905
905
  // Task without parameters - auto-runs on creation
906
- createTask<T>(task: () => Promise<T>): Task<T> & {
906
+ createTask<T>(task: (params: undefined, signal: AbortSignal) => Promise<T>): Task<T> & {
907
907
  run(): Promise<T>;
908
908
  rerun(): Promise<T>;
909
909
  }
910
910
 
911
911
  // Task with parameters - manual control
912
- createTask<P, T>(task: (params: P) => Promise<T>): Task<P, T> & {
912
+ createTask<P, T>(task: (params: P, signal: AbortSignal) => Promise<T>): Task<P, T> & {
913
913
  run(params: P): Promise<T>;
914
914
  rerun(params: P): Promise<T>;
915
915
  }
@@ -966,12 +966,82 @@ Error:
966
966
  { isRunning: false, params: null, result: null, error: string }
967
967
  ```
968
968
 
969
+ **Signal Parameter:**
970
+
971
+ The task callback receives an `AbortSignal` as the second parameter. This signal is useful for:
972
+
973
+ - **Passing to fetch requests** - Cancel network requests when the task is aborted
974
+ - **Detecting cancellation** - Check if the task was cancelled after async operations complete
975
+ - **Custom state management** - Detect if the task was rerun and implement your own cleanup logic
976
+
977
+ ```tsx
978
+ function SearchPosts() {
979
+ const state = createState({ query: "" });
980
+
981
+ const search = createTask((query: string, signal: AbortSignal) =>
982
+ fetch(`/api/search?q=${query}`, { signal }).then((r) => r.json())
983
+ );
984
+
985
+ createEffect(() => {
986
+ if (state.query) {
987
+ search.run(state.query);
988
+ }
989
+ });
990
+
991
+ return () => (
992
+ <div>
993
+ <input
994
+ value={state.query}
995
+ onInput={(e) => (state.query = e.target.value)}
996
+ />
997
+ {search.isRunning && <p>Searching...</p>}
998
+ {search.result && (
999
+ <ul>
1000
+ {search.result.map((post) => (
1001
+ <li key={post.id}>{post.title}</li>
1002
+ ))}
1003
+ </ul>
1004
+ )}
1005
+ </div>
1006
+ );
1007
+ }
1008
+
1009
+ // Detecting cancellation for custom state management
1010
+ function CustomStateExample() {
1011
+ const state = createState({ data: null, customLoading: false });
1012
+
1013
+ const task = createTask(async (id: number, signal: AbortSignal) => {
1014
+ state.customLoading = true;
1015
+ const result = await fetch(`/api/data/${id}`).then((r) => r.json());
1016
+
1017
+ // Check if task was cancelled/rerun after the async operation
1018
+ if (signal.aborted) {
1019
+ // Don't update state if the task was cancelled
1020
+ return result;
1021
+ }
1022
+
1023
+ state.data = result;
1024
+ state.customLoading = false;
1025
+ return result;
1026
+ });
1027
+
1028
+ return () => (
1029
+ <div>
1030
+ {state.customLoading && <p>Loading...</p>}
1031
+ {state.data && <p>Data: {JSON.stringify(state.data)}</p>}
1032
+ <button onClick={() => task.run(1)}>Load Data</button>
1033
+ </div>
1034
+ );
1035
+ }
1036
+ ```
1037
+
969
1038
  **Features:**
970
1039
 
971
1040
  - **Automatic cancellation** - Previous executions are cancelled when a new one starts
972
1041
  - **Flexible control** - Use `run()` to clear old data or `rerun()` to keep it during loading
973
1042
  - **Type-safe** - Full TypeScript inference for parameters and results
974
1043
  - **Auto-run support** - Tasks without parameters run automatically on creation
1044
+ - **Signal support** - AbortSignal provided for cancellation detection and request cancellation
975
1045
  - **Generic primitive** - Build your own patterns on top (queries, mutations, etc.)
976
1046
 
977
1047
  **Usage Patterns:**
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,QAAQ,WAEL;IACH,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;IAUrD,MAAM;CAMP;AAID,wBAAgB,mBAAmB,+BAMlC;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,QAM/C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI,QAM3C;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,QAAQ,CAMb;IAEH,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,UAAU,CAAQ;IAG1B,OAAO,CAAC,SAAS,CAAmB;IACpC,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;IAyD3B,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAG5B;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,GAAG;IAoBlC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;IAWrD,MAAM;CA2CP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,QAAQ,WAEL;IACH,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;IAUrD,MAAM;CAMP;AAID,wBAAgB,mBAAmB,+BAMlC;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,IAAI,QAM/C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI,QAM3C;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,QAAQ,CAKb;IAEH,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,UAAU,CAAQ;IAG1B,OAAO,CAAC,SAAS,CAAmB;IACpC,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;IAyD3B,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAG5B;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,GAAG;IAkBlC,qBAAqB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;IAWrD,MAAM;CA0CP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
package/dist/component.js CHANGED
@@ -45,7 +45,6 @@ export class RaskStatefulComponent extends Component {
45
45
  renderFn;
46
46
  reactiveProps;
47
47
  observer = new Observer(() => {
48
- console.log("OBSERVER", this.willRender, this.setup.name);
49
48
  if (this.willRender) {
50
49
  return;
51
50
  }
@@ -130,7 +129,6 @@ export class RaskStatefulComponent extends Component {
130
129
  componentWillUpdate(nextProps) {
131
130
  this.willRender = true;
132
131
  this.nextProps = nextProps;
133
- console.log("Props update", this.setup.name);
134
132
  syncBatch(() => {
135
133
  for (const prop in nextProps) {
136
134
  if (prop === "children" ||
@@ -141,7 +139,6 @@ export class RaskStatefulComponent extends Component {
141
139
  this.reactiveProps[prop] = nextProps[prop];
142
140
  }
143
141
  });
144
- console.log("Props update end");
145
142
  }
146
143
  shouldComponentUpdate(nextProps) {
147
144
  // Shallow comparison of props, excluding internal props
@@ -175,7 +172,6 @@ export class RaskStatefulComponent extends Component {
175
172
  const stopObserving = this.observer.observe();
176
173
  let result = null;
177
174
  try {
178
- console.log("RENDER", this.setup.name);
179
175
  this.isRendering = true;
180
176
  result = this.renderFn();
181
177
  this.isRendering = false;
@@ -1 +1 @@
1
- {"version":3,"file":"createEffect.d.ts","sourceRoot":"","sources":["../src/createEffect.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QA+BzD"}
1
+ {"version":3,"file":"createEffect.d.ts","sourceRoot":"","sources":["../src/createEffect.ts"],"names":[],"mappings":"AAIA,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,QA8BzD"}
@@ -11,7 +11,6 @@ export function createEffect(cb) {
11
11
  }
12
12
  let disposer;
13
13
  const observer = new Observer(() => {
14
- console.log("FIRED");
15
14
  syncBatch(runEffect);
16
15
  });
17
16
  const runEffect = () => {
@@ -26,6 +26,6 @@ export type Task<A, B = never> = [B] extends [never] ? TaskState<null, A> & {
26
26
  run(params: A): Promise<B>;
27
27
  rerun(params: A): Promise<B>;
28
28
  };
29
- export declare function createTask<T>(task: () => Promise<T>): Task<T>;
30
- export declare function createTask<P, T>(task: (params: P) => Promise<T>): Task<P, T>;
29
+ export declare function createTask<T>(task: (params: undefined, signal: AbortSignal) => Promise<T>): Task<T>;
30
+ export declare function createTask<P, T>(task: (params: P, signal: AbortSignal) => Promise<T>): Task<P, T>;
31
31
  //# sourceMappingURL=createTask.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createTask.d.ts","sourceRoot":"","sources":["../src/createTask.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IACtB;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,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAChD,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG;IACnB,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACrB,GACD,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAChB,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;AAEN,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/D,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"createTask.d.ts","sourceRoot":"","sources":["../src/createTask.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IACtB;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,MAAM,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAChD,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG;IACnB,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IAClB,KAAK,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACrB,GACD,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG;IAChB,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;AAEN,wBAAgB,UAAU,CAAC,CAAC,EAC1B,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3D,IAAI,CAAC,CAAC,CAAC,CAAC;AACX,wBAAgB,UAAU,CAAC,CAAC,EAAE,CAAC,EAC7B,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACnD,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC"}
@@ -10,7 +10,7 @@ export function createTask(task) {
10
10
  const fetch = (params) => {
11
11
  currentAbortController?.abort();
12
12
  const abortController = (currentAbortController = new AbortController());
13
- const promise = task(params);
13
+ const promise = task(params, abortController.signal);
14
14
  promise
15
15
  .then((result) => {
16
16
  if (abortController.signal.aborted) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rask-ui",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",