@cmtlyt/lingshu-toolkit 0.2.0 → 0.4.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.
Files changed (83) hide show
  1. package/dist/607.js +737 -0
  2. package/dist/707.js +13 -3
  3. package/dist/react/index.d.ts +7 -0
  4. package/dist/react/index.js +120 -3
  5. package/dist/react/use-force-update/index.d.ts +1 -0
  6. package/dist/react/use-force-update/index.js +6 -0
  7. package/dist/react/use-force-update/index.test.d.ts +1 -0
  8. package/dist/react/use-ref-state/index.d.ts +8 -0
  9. package/dist/react/use-ref-state/index.js +33 -0
  10. package/dist/react/use-ref-state/index.test.d.ts +1 -0
  11. package/dist/react/use-storage/index.d.ts +2 -0
  12. package/dist/react/use-storage/index.js +15 -0
  13. package/dist/react/use-storage/index.test.d.ts +1 -0
  14. package/dist/react/use-valid-data/index.d.ts +3 -3
  15. package/dist/shared/allx/__test__/allsettled.test.d.ts +1 -0
  16. package/dist/shared/allx/__test__/basic.test.d.ts +1 -0
  17. package/dist/shared/allx/__test__/circular-dependency.test.d.ts +1 -0
  18. package/dist/shared/allx/__test__/dependency.test.d.ts +1 -0
  19. package/dist/shared/allx/__test__/edge-cases.test.d.ts +1 -0
  20. package/dist/shared/allx/__test__/error-handling.test.d.ts +1 -0
  21. package/dist/shared/allx/__test__/execution-order.test.d.ts +1 -0
  22. package/dist/shared/allx/__test__/falsy-values.test.d.ts +1 -0
  23. package/dist/shared/allx/__test__/performance.test.d.ts +1 -0
  24. package/dist/shared/allx/__test__/type-checking.test.d.ts +1 -0
  25. package/dist/shared/allx/__test__/use-cases.test.d.ts +1 -0
  26. package/dist/shared/allx/index.d.ts +13 -0
  27. package/dist/shared/allx/index.js +44 -0
  28. package/dist/shared/allx/types.d.ts +13 -0
  29. package/dist/shared/allx/types.js +0 -0
  30. package/dist/shared/allx/utils.d.ts +9 -0
  31. package/dist/shared/allx/utils.js +94 -0
  32. package/dist/shared/animation/__test__/animation-pause-resume.test.d.ts +1 -0
  33. package/dist/shared/animation/__test__/animation.test.d.ts +1 -0
  34. package/dist/shared/animation/__test__/step-animation.test.d.ts +1 -0
  35. package/dist/shared/animation/__test__/utils.test.d.ts +1 -0
  36. package/dist/shared/animation/index.d.ts +3 -0
  37. package/dist/shared/animation/index.js +77 -0
  38. package/dist/shared/animation/types.d.ts +24 -0
  39. package/dist/shared/animation/types.js +0 -0
  40. package/dist/shared/animation/utils.d.ts +14 -0
  41. package/dist/shared/animation/utils.js +134 -0
  42. package/dist/shared/condition-merge/index.d.ts +1 -5
  43. package/dist/shared/create-storage-handler/index.browser.test.d.ts +1 -0
  44. package/dist/shared/create-storage-handler/index.d.ts +10 -0
  45. package/dist/shared/create-storage-handler/index.js +68 -0
  46. package/dist/shared/create-storage-handler/index.test.d.ts +1 -0
  47. package/dist/shared/data-handler/index.d.ts +7 -2
  48. package/dist/shared/data-handler/tools.d.ts +36 -12
  49. package/dist/shared/data-handler/tools.js +8 -4
  50. package/dist/shared/data-handler/types.d.ts +2 -2
  51. package/dist/shared/data-mixed-manager/__test__/basic.test.d.ts +1 -0
  52. package/dist/shared/data-mixed-manager/__test__/build-options.test.d.ts +1 -0
  53. package/dist/shared/data-mixed-manager/__test__/constructor-options.test.d.ts +1 -0
  54. package/dist/shared/data-mixed-manager/__test__/data-management.test.d.ts +1 -0
  55. package/dist/shared/data-mixed-manager/__test__/edge-cases.test.d.ts +1 -0
  56. package/dist/shared/data-mixed-manager/__test__/events.browser.test.d.ts +1 -0
  57. package/dist/shared/data-mixed-manager/__test__/events.test.d.ts +1 -0
  58. package/dist/shared/data-mixed-manager/__test__/fixed-slots.test.d.ts +1 -0
  59. package/dist/shared/data-mixed-manager/__test__/insert-mode.test.d.ts +1 -0
  60. package/dist/shared/data-mixed-manager/constants.d.ts +8 -0
  61. package/dist/shared/data-mixed-manager/constants.js +9 -0
  62. package/dist/shared/data-mixed-manager/index.d.ts +128 -0
  63. package/dist/shared/data-mixed-manager/index.js +226 -0
  64. package/dist/shared/data-mixed-manager/types.d.ts +90 -0
  65. package/dist/shared/data-mixed-manager/types.js +0 -0
  66. package/dist/shared/index.d.ts +8 -0
  67. package/dist/shared/index.js +2 -1
  68. package/dist/shared/throw-error/index.d.ts +1 -0
  69. package/dist/shared/throw-error/index.js +5 -2
  70. package/dist/shared/types/base.d.ts +6 -0
  71. package/dist/shared/utils/__test__/base.test.d.ts +1 -0
  72. package/dist/shared/utils/__test__/verify.test.d.ts +1 -0
  73. package/dist/shared/utils/base.d.ts +3 -0
  74. package/dist/shared/utils/base.js +6 -0
  75. package/dist/shared/utils/index.d.ts +2 -0
  76. package/dist/shared/utils/index.js +2 -0
  77. package/dist/shared/utils/verify.d.ts +53 -0
  78. package/dist/shared/utils/verify.js +67 -0
  79. package/dist/shared/with-resolvers/index.d.ts +6 -0
  80. package/dist/shared/with-resolvers/index.js +15 -0
  81. package/dist/shared/with-resolvers/index.test.d.ts +1 -0
  82. package/dist/test/utils.d.ts +13 -0
  83. package/package.json +9 -7
package/dist/707.js CHANGED
@@ -1,5 +1,8 @@
1
+ function createError(fnName, message, ErrorClass = Error) {
2
+ return new ErrorClass(`[@cmtlyt/lingshu-toolkit#${fnName}]: ${message}`);
3
+ }
1
4
  function throwError(fnName, message, ErrorClass = Error) {
2
- throw new ErrorClass(`[@cmtlyt/lingshu-toolkit#${fnName}]: ${message}`);
5
+ throw createError(fnName, message, ErrorClass);
3
6
  }
4
7
  function throwType(fnName, message) {
5
8
  throwError(fnName, message, TypeError);
@@ -12,6 +15,8 @@ const logger = new Proxy(console, {
12
15
  };
13
16
  }
14
17
  });
18
+ const noop = ()=>void 0;
19
+ const identity = (_v)=>_v;
15
20
  function getType(_v) {
16
21
  return Object.prototype.toString.call(_v).slice(8, -1).toLowerCase();
17
22
  }
@@ -34,7 +39,12 @@ const $t = {
34
39
  object: typeHandler('object'),
35
40
  array: typeHandler('array'),
36
41
  function: typeHandler('function'),
37
- symbol: typeHandler('symbol')
42
+ symbol: typeHandler('symbol'),
43
+ enum: (list, fullback)=>{
44
+ if (!Array.isArray(list)) throwType('$t.enum', 'list must be an array');
45
+ const set = new Set(list);
46
+ return typeHandler('enum', (_v)=>set.has(_v))(fullback);
47
+ }
38
48
  };
39
49
  function defineTransform(dataInfo) {
40
50
  const verifyInfo = {};
@@ -128,4 +138,4 @@ function dataHandler(data, handler, options) {
128
138
  errors: ctx.errors
129
139
  };
130
140
  }
131
- export { $dt, $t, dataHandler, defineTransform, logger, throwError, throwType };
141
+ export { $dt, $t, createError, dataHandler, defineTransform, getType, identity, logger, noop, throwError, throwType };
@@ -1,3 +1,10 @@
1
+ export * from './use-boolean';
1
2
  export * from './use-controllable-value';
2
3
  export * from './use-counter';
4
+ export * from './use-force-update';
5
+ export * from './use-mount';
6
+ export * from './use-ref-state';
7
+ export * from './use-storage';
8
+ export * from './use-title';
9
+ export * from './use-toggle';
3
10
  export * from './use-valid-data';
@@ -1,5 +1,42 @@
1
- import { useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
2
- import { dataHandler, logger, $dt, $t } from "../707.js";
1
+ import { useEffect, useEffectEvent, useMemo, useReducer, useRef, useState } from "react";
2
+ import { dataHandler, logger, $dt, $t, throwType } from "../707.js";
3
+ import { createStorageHandler } from "../607.js";
4
+ function useToggle(defualtValue = false, reverseValue) {
5
+ const [state, setState] = useState(defualtValue);
6
+ const toggleRef = useRef([
7
+ defualtValue,
8
+ void 0 === reverseValue ? !defualtValue : reverseValue
9
+ ]);
10
+ const actions = useMemo(()=>{
11
+ const [left, right] = toggleRef.current;
12
+ return {
13
+ set: (value)=>{
14
+ if (value !== left && value !== right) throwType('useToggle', 'value is not left or right');
15
+ setState(value);
16
+ },
17
+ setLeft: ()=>setState(left),
18
+ setRight: ()=>setState(right),
19
+ toggle: ()=>setState((prev)=>prev === left ? right : left)
20
+ };
21
+ }, []);
22
+ return [
23
+ state,
24
+ actions
25
+ ];
26
+ }
27
+ function useBoolean(defaultValue = false) {
28
+ const [state, { toggle, set }] = useToggle(!!defaultValue);
29
+ const actions = useMemo(()=>({
30
+ toggle,
31
+ setTrue: ()=>set(true),
32
+ setFalse: ()=>set(false),
33
+ set: (value)=>set(!!value)
34
+ }), []);
35
+ return [
36
+ state,
37
+ actions
38
+ ];
39
+ }
3
40
  function useValidData(data, verifyInfo, options) {
4
41
  const verifyInfoRef = useRef(verifyInfo);
5
42
  const optionsRef = useRef(options);
@@ -84,5 +121,85 @@ function useCounter(initialValue = 0, options = {}) {
84
121
  actions
85
122
  ];
86
123
  }
124
+ function useForceUpdate() {
125
+ const [, forceUpdate] = useReducer((prev)=>(prev + 1) % 10, 0);
126
+ return forceUpdate;
127
+ }
128
+ function useMount(callback) {
129
+ const callbackRef = useRef(callback);
130
+ useEffect(()=>{
131
+ dataHandler({
132
+ fn: callbackRef.current
133
+ }, {
134
+ fn: $t["function"]()
135
+ }, {
136
+ strict: true
137
+ });
138
+ callbackRef.current();
139
+ }, []);
140
+ }
141
+ const clone = structuredClone;
142
+ function useRefState(initialState) {
143
+ const stateRef = useRef(initialState);
144
+ const forceUpdate = useForceUpdate();
145
+ const ctrl = useMemo(()=>{
146
+ const origin = clone(stateRef.current);
147
+ const updateHandler = (update = true)=>void (update && forceUpdate());
148
+ const patchState = (updater, update = true)=>{
149
+ updater(stateRef.current);
150
+ updateHandler(update);
151
+ };
152
+ const setState = (state, update = true)=>{
153
+ stateRef.current = state;
154
+ updateHandler(update);
155
+ };
156
+ return {
157
+ patchState,
158
+ forceUpdate,
159
+ getState: ()=>stateRef.current,
160
+ setState,
161
+ reset: (update = true)=>setState(clone(origin), update)
162
+ };
163
+ }, [
164
+ forceUpdate
165
+ ]);
166
+ return [
167
+ stateRef.current,
168
+ ctrl
169
+ ];
170
+ }
171
+ function useStorage(storageKey, options, initialData) {
172
+ const optionsRef = useRef({
173
+ initialData,
174
+ options
175
+ });
176
+ return useMemo(()=>{
177
+ const { initialData: _initialData, options: _options } = optionsRef.current;
178
+ return createStorageHandler(storageKey, _initialData || {}, _options);
179
+ }, [
180
+ storageKey
181
+ ]);
182
+ }
183
+ function setTitle(title) {
184
+ if (!title) return;
185
+ document.title = title;
186
+ }
187
+ const use_title_validInfo = $dt({
188
+ restoreOnUnmount: $t.boolean(true)
189
+ });
190
+ function useTitle(title, options = {}) {
191
+ const { restoreOnUnmount } = useValidData(options, use_title_validInfo);
192
+ useEffect(()=>{
193
+ const originalTitle = document.title;
194
+ setTitle(title);
195
+ return ()=>{
196
+ if (restoreOnUnmount) setTitle(originalTitle);
197
+ };
198
+ }, [
199
+ title,
200
+ restoreOnUnmount
201
+ ]);
202
+ return setTitle;
203
+ }
87
204
  export { $dt, $t, defineTransform } from "../707.js";
88
- export { useControllableValue, useCounter, useValidData };
205
+ export { useBoolean, useControllableValue, useCounter, useForceUpdate, useMount, useRefState, useStorage, useTitle, useToggle, useValidData };
@@ -0,0 +1 @@
1
+ export declare function useForceUpdate(): import("react").ActionDispatch<[]>;
@@ -0,0 +1,6 @@
1
+ import { useReducer } from "react";
2
+ function useForceUpdate() {
3
+ const [, forceUpdate] = useReducer((prev)=>(prev + 1) % 10, 0);
4
+ return forceUpdate;
5
+ }
6
+ export { useForceUpdate };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ export interface UseRefStateCtrl<T> {
2
+ patchState: (updater: (draft: T) => void, update?: boolean) => void;
3
+ forceUpdate: () => void;
4
+ getState: () => T;
5
+ setState: (state: T, update?: boolean) => void;
6
+ reset: (update?: boolean) => void;
7
+ }
8
+ export declare function useRefState<T>(initialState: T): readonly [T, UseRefStateCtrl<T>];
@@ -0,0 +1,33 @@
1
+ import { useMemo, useRef } from "react";
2
+ import { useForceUpdate } from "../use-force-update/index.js";
3
+ const clone = structuredClone;
4
+ function useRefState(initialState) {
5
+ const stateRef = useRef(initialState);
6
+ const forceUpdate = useForceUpdate();
7
+ const ctrl = useMemo(()=>{
8
+ const origin = clone(stateRef.current);
9
+ const updateHandler = (update = true)=>void (update && forceUpdate());
10
+ const patchState = (updater, update = true)=>{
11
+ updater(stateRef.current);
12
+ updateHandler(update);
13
+ };
14
+ const setState = (state, update = true)=>{
15
+ stateRef.current = state;
16
+ updateHandler(update);
17
+ };
18
+ return {
19
+ patchState,
20
+ forceUpdate,
21
+ getState: ()=>stateRef.current,
22
+ setState,
23
+ reset: (update = true)=>setState(clone(origin), update)
24
+ };
25
+ }, [
26
+ forceUpdate
27
+ ]);
28
+ return [
29
+ stateRef.current,
30
+ ctrl
31
+ ];
32
+ }
33
+ export { useRefState };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { type CreateStorageOptions } from '../../shared/create-storage-handler';
2
+ export declare function useStorage<T extends Record<string, any>>(storageKey: string, options?: Partial<CreateStorageOptions>, initialData?: T): import("../../shared/create-storage-handler").StorageHandler<T>;
@@ -0,0 +1,15 @@
1
+ import { useMemo, useRef } from "react";
2
+ import { createStorageHandler } from "../../shared/create-storage-handler/index.js";
3
+ function useStorage(storageKey, options, initialData) {
4
+ const optionsRef = useRef({
5
+ initialData,
6
+ options
7
+ });
8
+ return useMemo(()=>{
9
+ const { initialData: _initialData, options: _options } = optionsRef.current;
10
+ return createStorageHandler(storageKey, _initialData || {}, _options);
11
+ }, [
12
+ storageKey
13
+ ]);
14
+ }
15
+ export { useStorage };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,8 @@
1
1
  import type { DataHandlerOptions, Handler } from '../../shared/data-handler/types';
2
2
  export * from '../../shared/data-handler/tools';
3
- export declare function useValidData<T extends Record<PropertyKey, any>, O extends DataHandlerOptions<T> = DataHandlerOptions<T> & {
3
+ export declare function useValidData<T extends Record<PropertyKey, any>, H extends Handler<T> = Handler<T>, O extends DataHandlerOptions<T> = DataHandlerOptions<T> & {
4
4
  unwrap: true;
5
- }>(data: T, verifyInfo: Handler<T>, options?: O): O["unwrap"] extends true ? T & O["defaultValue"] : {
6
- result: T & O["defaultValue"];
5
+ }>(data: T, verifyInfo: H, options?: O): O["unwrap"] extends true ? import("../../shared").Printify<import("../../shared/data-handler").Transform2Type<H> extends infer T_1 ? T_1 extends import("../../shared/data-handler").Transform2Type<H> ? T_1 extends (...args: any[]) => any ? T & O["defaultValue"] : T & O["defaultValue"] & { [K in keyof T_1]: import("../../shared").Equal<T_1[K], any> extends true ? Required<T & O["defaultValue"]>[K] : T_1[K]; } : never : never> : {
6
+ result: import("../../shared").Printify<import("../../shared/data-handler").Transform2Type<H> extends infer T_2 ? T_2 extends import("../../shared/data-handler").Transform2Type<H> ? T_2 extends (...args: any[]) => any ? T & O["defaultValue"] : T & O["defaultValue"] & { [K_1 in keyof T_2]: import("../../shared").Equal<T_2[K_1], any> extends true ? Required<T & O["defaultValue"]>[K_1] : T_2[K_1]; } : never : never>;
7
7
  errors: string[];
8
8
  };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import type { AllxContext, AllxOptions, AllxResult } from './types';
2
+ /**
3
+ * 支持自动依赖优化和完整类型推断的 Promise.all, 执行任务时自动解决依赖关系。
4
+ *
5
+ * @platform web, node, webworker
6
+ * @example
7
+ * const { a, b, c } = await allx({
8
+ * a() { return 1 },
9
+ * async b() { return 'hello' },
10
+ * async c() { return (await this.$.a) + 10 }
11
+ * })
12
+ */
13
+ export declare function allx<M extends Record<PropertyKey, any>, O extends AllxOptions>(tasks: M & ThisType<AllxContext<M>>, options?: O): Promise<AllxResult<M, O>>;
@@ -0,0 +1,44 @@
1
+ import { $dt, $t, dataHandler } from "../data-handler/index.js";
2
+ import { isFunction, isPromiseLike } from "../utils/verify.js";
3
+ import { withResolvers } from "../with-resolvers/index.js";
4
+ import { createDepProxy, getValueFormatFunc } from "./utils.js";
5
+ const validInfo = $dt({
6
+ allSettled: $t.boolean(false)
7
+ });
8
+ async function allx(tasks, options) {
9
+ const validOptions = dataHandler(options || {}, validInfo, {
10
+ unwrap: true
11
+ });
12
+ const { allSettled } = validOptions;
13
+ const results = {};
14
+ const depCtrl = createDepProxy(tasks, results, validOptions);
15
+ const valueFormat = getValueFormatFunc(options);
16
+ const promises = [];
17
+ depCtrl.taskNameSet.forEach(async (taskName)=>{
18
+ const taskFn = tasks[taskName];
19
+ const context = {
20
+ $: depCtrl.createContextFor(taskName)
21
+ };
22
+ const taskResolvers = withResolvers();
23
+ taskResolvers.promise.then((value)=>{
24
+ results[taskName] = valueFormat(value, 'fulfilled');
25
+ depCtrl.resolveDepFor(taskName, value);
26
+ return value;
27
+ }, (error)=>{
28
+ if (allSettled) results[taskName] = valueFormat(error, 'rejected');
29
+ depCtrl.rejectDepFor(taskName, error);
30
+ });
31
+ promises.push(taskResolvers.promise);
32
+ if (isPromiseLike(taskFn)) return void await taskFn.then(taskResolvers.resolve, taskResolvers.reject);
33
+ if (!isFunction(taskFn)) return void taskResolvers.resolve(taskFn);
34
+ try {
35
+ const result = await taskFn.call(context);
36
+ taskResolvers.resolve(result);
37
+ } catch (error) {
38
+ taskResolvers.reject(error);
39
+ }
40
+ });
41
+ if (allSettled) return Promise.allSettled(promises).then(()=>results);
42
+ return Promise.all(promises).then(()=>results);
43
+ }
44
+ export { allx };
@@ -0,0 +1,13 @@
1
+ import type { AnyFunc } from '../types/base';
2
+ export interface AllxOptions {
3
+ allSettled?: boolean;
4
+ }
5
+ export type AllxTaskValue<T> = T extends AnyFunc ? Awaited<ReturnType<T>> : Awaited<T>;
6
+ export interface AllxContext<M extends Record<PropertyKey, AnyFunc>> {
7
+ $: {
8
+ [P in keyof M]: Promise<AllxTaskValue<M[P]>>;
9
+ };
10
+ }
11
+ export type AllxResult<M extends Record<PropertyKey, AnyFunc>, O extends AllxOptions = AllxOptions> = {
12
+ [P in keyof M]: O['allSettled'] extends true ? PromiseSettledResult<Awaited<ReturnType<M[P]>>> : AllxTaskValue<M[P]>;
13
+ };
File without changes
@@ -0,0 +1,9 @@
1
+ import type { AnyFunc } from '../types/base';
2
+ import type { AllxOptions } from './types';
3
+ export declare function createDepProxy(tasks: Record<PropertyKey, AnyFunc>, results: Record<PropertyKey, any>, options: Required<AllxOptions>): {
4
+ taskNameSet: Set<PropertyKey>;
5
+ createContextFor: (currentTask: PropertyKey) => {};
6
+ resolveDepFor: (depName: PropertyKey, value: any) => void;
7
+ rejectDepFor: (depName: PropertyKey, error: any) => void;
8
+ };
9
+ export declare function getValueFormatFunc(options?: AllxOptions): (value: any, _type?: PromiseSettledResult<any>["status"]) => any;
@@ -0,0 +1,94 @@
1
+ import { createError } from "../throw-error/index.js";
2
+ import { withResolvers } from "../with-resolvers/index.js";
3
+ function detectCycle(from, to, waitingForGraph) {
4
+ const visited = new Set();
5
+ const queue = [
6
+ to
7
+ ];
8
+ let head = 0;
9
+ while(head < queue.length){
10
+ const node = queue[head++];
11
+ if (node === from) return true;
12
+ if (visited.has(node)) continue;
13
+ visited.add(node);
14
+ const deps = waitingForGraph.get(node);
15
+ if (deps) {
16
+ const depsIter = deps.values();
17
+ for(let dep = depsIter.next(); !dep.done; dep = depsIter.next())queue.push(dep.value);
18
+ }
19
+ }
20
+ return false;
21
+ }
22
+ function getCached(results, depName, allSettled) {
23
+ if (Reflect.getOwnPropertyDescriptor(results, depName)) {
24
+ const cached = results[depName];
25
+ if (allSettled) return 'rejected' === cached.status ? Promise.reject(cached.reason) : Promise.resolve(cached.value);
26
+ return Promise.resolve(cached);
27
+ }
28
+ }
29
+ function createDepResolver(waitingFor, resolverMap, currentTask, depName) {
30
+ waitingFor.set(currentTask, (waitingFor.get(currentTask) || new Set()).add(depName));
31
+ const depResolvers = resolverMap.get(depName) || withResolvers();
32
+ resolverMap.set(depName, depResolvers);
33
+ return depResolvers.promise.then((value)=>{
34
+ waitingFor.get(currentTask)?.delete(depName);
35
+ return value;
36
+ }, (error)=>{
37
+ waitingFor.get(currentTask)?.delete(depName);
38
+ throw error;
39
+ });
40
+ }
41
+ function cleanWaitingForGraph(waitingForGraph, depName) {
42
+ waitingForGraph.forEach((deps, task)=>{
43
+ deps.delete(depName);
44
+ if (0 === deps.size) waitingForGraph.delete(task);
45
+ });
46
+ }
47
+ function createDepProxy(tasks, results, options) {
48
+ const resolverMap = new Map();
49
+ const taskNameSet = new Set(Reflect.ownKeys(tasks));
50
+ const waitingForGraph = new Map();
51
+ const resolveDepFor = (depName, value)=>{
52
+ const resolver = resolverMap.get(depName);
53
+ if (resolver) {
54
+ resolver.resolve(value);
55
+ resolverMap.delete(depName);
56
+ }
57
+ cleanWaitingForGraph(waitingForGraph, depName);
58
+ };
59
+ const rejectDepFor = (depName, error)=>{
60
+ const resolver = resolverMap.get(depName);
61
+ if (resolver) {
62
+ resolver.reject(error);
63
+ resolverMap.delete(depName);
64
+ }
65
+ cleanWaitingForGraph(waitingForGraph, depName);
66
+ };
67
+ const createContextFor = (currentTask)=>new Proxy({}, {
68
+ get (_, depName) {
69
+ if (!taskNameSet.has(depName)) return Promise.reject(createError('allx', `Unknown task "${String(depName)}"`));
70
+ const cached = getCached(results, depName, options.allSettled);
71
+ if (cached) return cached;
72
+ if (detectCycle(currentTask, depName, waitingForGraph)) return Promise.reject(createError('allx', `Circular dependency detected: "${String(currentTask)}" -> "${String(depName)}"`));
73
+ return createDepResolver(waitingForGraph, resolverMap, currentTask, depName);
74
+ }
75
+ });
76
+ return {
77
+ taskNameSet,
78
+ createContextFor,
79
+ resolveDepFor,
80
+ rejectDepFor
81
+ };
82
+ }
83
+ function getValueFormatFunc(options) {
84
+ if (!options) return (value, _type = 'fulfilled')=>value;
85
+ if (options.allSettled) return (value, status = 'fulfilled')=>'fulfilled' === status ? {
86
+ status,
87
+ value
88
+ } : {
89
+ status,
90
+ reason: value
91
+ };
92
+ return (value, _type = 'fulfilled')=>value;
93
+ }
94
+ export { createDepProxy, getValueFormatFunc };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { AnimationBaseOptions, AnimationOptions, AnimationResult } from './types';
2
+ export declare function stepAnimation<T>(from: T, to: T, step: number, options?: AnimationBaseOptions<T>): Generator<any, void, unknown>;
3
+ export declare function animation<T>(from: T, to: T, duration: number, options?: AnimationOptions<T>): AnimationResult;
@@ -0,0 +1,77 @@
1
+ import { $dt, $t, dataHandler } from "../data-handler/index.js";
2
+ import { throwError } from "../throw-error/index.js";
3
+ import { identity, noop } from "../utils/base.js";
4
+ import { createNextTick, createRunningControllerSignal, getNextValueHandler, matchValid } from "./utils.js";
5
+ const validInfo = $dt({
6
+ autoStart: $t.boolean(true),
7
+ easing: $t["function"](()=>identity),
8
+ onStart: $t["function"](()=>noop),
9
+ onStop: $t["function"](()=>noop),
10
+ onClear: $t["function"](()=>noop),
11
+ onUpdate: $t["function"](()=>noop),
12
+ onComplete: $t["function"](()=>noop),
13
+ formatterValue: $t["function"](()=>identity),
14
+ formatter: $t["function"](()=>identity),
15
+ parser: $t["function"](()=>identity)
16
+ });
17
+ function* stepAnimation(from, to, step, options = {}) {
18
+ if (!Number.isInteger(step) || step <= 0) throwError('stepAnimation', 'step must be a positive integer', RangeError);
19
+ const validOptions = dataHandler(options, validInfo, {
20
+ unwrap: true
21
+ });
22
+ const { parser: valueParser = identity, formatterValue = identity, formatter } = validOptions;
23
+ const [validFrom, validTo] = matchValid(from, to, valueParser);
24
+ const getNextValue = getNextValueHandler(validFrom, validTo, formatterValue);
25
+ for(let i = 0; i <= step; i++){
26
+ const value = formatter(getNextValue(i / step));
27
+ yield value;
28
+ }
29
+ }
30
+ function animation(from, to, duration, options = {}) {
31
+ if (duration <= 0 || !Number.isInteger(duration)) throwError('animation', 'duration must be a positive integer', RangeError);
32
+ const validOptions = dataHandler(options, validInfo, {
33
+ unwrap: true
34
+ });
35
+ const [validFrom, validTo] = matchValid(from, to, validOptions.parser);
36
+ const { autoStart, easing, onComplete, onUpdate, formatterValue, formatter } = validOptions;
37
+ const _getNextValue = getNextValueHandler(validFrom, validTo, formatterValue);
38
+ const getNextValue = (...args)=>formatter(_getNextValue(...args));
39
+ let startTime = 0;
40
+ let hasStarted = false;
41
+ const rcSignal = createRunningControllerSignal(()=>{
42
+ const now = performance.now();
43
+ startTime += now;
44
+ const stopFlag = nextTick(tick);
45
+ if (stopFlag) {
46
+ startTime -= performance.now();
47
+ return;
48
+ }
49
+ if (!hasStarted) {
50
+ onUpdate(getNextValue(0));
51
+ hasStarted = true;
52
+ }
53
+ }, validOptions);
54
+ const { resolvers } = rcSignal;
55
+ const nextTick = createNextTick(resolvers, rcSignal);
56
+ const tick = ()=>{
57
+ const elapsed = performance.now() - startTime;
58
+ const progress = easing(Math.min(elapsed / duration, 1));
59
+ const value = getNextValue(progress);
60
+ onUpdate(value);
61
+ if (elapsed < duration) {
62
+ const stopFlag = nextTick(tick);
63
+ if (stopFlag) startTime = -elapsed;
64
+ } else {
65
+ onComplete();
66
+ resolvers.resolve(false);
67
+ }
68
+ };
69
+ if (false !== autoStart) rcSignal.start();
70
+ return {
71
+ promise: resolvers.promise,
72
+ stop: rcSignal.stop,
73
+ start: rcSignal.start,
74
+ clear: rcSignal.clear
75
+ };
76
+ }
77
+ export { animation, stepAnimation };
@@ -0,0 +1,24 @@
1
+ export type FormatterValue = (value: number) => any;
2
+ export type Formatter<T> = (value: T) => any;
3
+ export interface AnimationBaseOptions<T> {
4
+ parser?: (value: any) => number;
5
+ formatterValue?: FormatterValue;
6
+ formatter?: Formatter<T>;
7
+ }
8
+ export interface AnimationOptions<T> extends AnimationBaseOptions<T> {
9
+ autoStart?: boolean;
10
+ easing?: (time: number) => number;
11
+ onStart?: () => void;
12
+ onStop?: () => void;
13
+ onClear?: () => void;
14
+ onUpdate?: (value: any) => void;
15
+ onComplete?: () => void;
16
+ }
17
+ export interface AnimationCtrl {
18
+ stop: () => void;
19
+ start: () => void;
20
+ clear: () => void;
21
+ }
22
+ export type AnimationResult = AnimationCtrl & {
23
+ promise: Promise<boolean>;
24
+ };
File without changes
@@ -0,0 +1,14 @@
1
+ import { type Resolver } from '../with-resolvers';
2
+ import type { AnimationOptions, FormatterValue } from './types';
3
+ export declare function getNextValueHandler<T>(from: T, to: T, valueFormatter: FormatterValue): (progress: number) => any;
4
+ export declare function matchValid(from: any, to: any, valueParser: (value: any) => number): number[] | unknown[][] | [Record<PropertyKey, any>, Record<PropertyKey, any>];
5
+ export declare function createNextTick(resolvers: Resolver<any>, rcSignal: RCSignal): (callback: (...args: any[]) => void) => boolean;
6
+ export declare function tryRun(callback: () => any, resolvers: Resolver<any>, customErrorHandler?: (err: any) => void): Promise<void>;
7
+ export declare function createRunningControllerSignal(startFn: () => void, options: Required<AnimationOptions<any>>): {
8
+ stopSignal: boolean;
9
+ resolvers: Resolver<boolean>;
10
+ stop: () => void;
11
+ start: () => void;
12
+ clear: () => void;
13
+ };
14
+ export type RCSignal = Omit<ReturnType<typeof createRunningControllerSignal>, 'resolvers'>;