@cmtlyt/lingshu-toolkit 0.3.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.
- package/dist/607.js +446 -20
- package/dist/707.js +7 -2
- package/dist/react/index.js +1 -3
- package/dist/react/use-ref-state/index.js +1 -3
- package/dist/shared/allx/__test__/allsettled.test.d.ts +1 -0
- package/dist/shared/allx/__test__/basic.test.d.ts +1 -0
- package/dist/shared/allx/__test__/circular-dependency.test.d.ts +1 -0
- package/dist/shared/allx/__test__/dependency.test.d.ts +1 -0
- package/dist/shared/allx/__test__/edge-cases.test.d.ts +1 -0
- package/dist/shared/allx/__test__/error-handling.test.d.ts +1 -0
- package/dist/shared/allx/__test__/execution-order.test.d.ts +1 -0
- package/dist/shared/allx/__test__/falsy-values.test.d.ts +1 -0
- package/dist/shared/allx/__test__/performance.test.d.ts +1 -0
- package/dist/shared/allx/__test__/type-checking.test.d.ts +1 -0
- package/dist/shared/allx/__test__/use-cases.test.d.ts +1 -0
- package/dist/shared/allx/index.d.ts +13 -0
- package/dist/shared/allx/index.js +44 -0
- package/dist/shared/allx/types.d.ts +13 -0
- package/dist/shared/allx/types.js +0 -0
- package/dist/shared/allx/utils.d.ts +9 -0
- package/dist/shared/allx/utils.js +94 -0
- package/dist/shared/animation/index.d.ts +2 -2
- package/dist/shared/animation/index.js +19 -13
- package/dist/shared/animation/types.d.ts +6 -4
- package/dist/shared/animation/utils.d.ts +3 -5
- package/dist/shared/animation/utils.js +2 -6
- package/dist/shared/data-handler/tools.js +1 -3
- package/dist/shared/data-mixed-manager/__test__/basic.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/build-options.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/constructor-options.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/data-management.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/edge-cases.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/events.browser.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/events.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/fixed-slots.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/__test__/insert-mode.test.d.ts +1 -0
- package/dist/shared/data-mixed-manager/constants.d.ts +8 -0
- package/dist/shared/data-mixed-manager/constants.js +9 -0
- package/dist/shared/data-mixed-manager/index.d.ts +128 -0
- package/dist/shared/data-mixed-manager/index.js +226 -0
- package/dist/shared/data-mixed-manager/types.d.ts +90 -0
- package/dist/shared/data-mixed-manager/types.js +0 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +2 -2
- package/dist/shared/throw-error/index.d.ts +1 -0
- package/dist/shared/throw-error/index.js +5 -2
- package/dist/shared/types/base.d.ts +3 -0
- package/dist/shared/utils/__test__/base.test.d.ts +1 -0
- package/dist/shared/utils/__test__/verify.test.d.ts +1 -0
- package/dist/shared/utils/base.d.ts +3 -0
- package/dist/shared/utils/base.js +6 -0
- package/dist/shared/utils/index.d.ts +2 -0
- package/dist/shared/utils/index.js +2 -0
- package/dist/shared/utils/verify.d.ts +53 -0
- package/dist/shared/utils/verify.js +67 -0
- package/package.json +6 -6
package/dist/607.js
CHANGED
|
@@ -1,4 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { throwType, createError, logger, $dt, throwError, getType, identity, dataHandler, $t, noop } from "./707.js";
|
|
2
|
+
function isSymbol(_v) {
|
|
3
|
+
return 'symbol' == typeof _v;
|
|
4
|
+
}
|
|
5
|
+
function isUndef(_v) {
|
|
6
|
+
return void 0 === _v;
|
|
7
|
+
}
|
|
8
|
+
function isNull(_v) {
|
|
9
|
+
return null === _v;
|
|
10
|
+
}
|
|
11
|
+
function isNullOrUndef(_v) {
|
|
12
|
+
return isNull(_v) || isUndef(_v);
|
|
13
|
+
}
|
|
14
|
+
function verify_isNaN(_v) {
|
|
15
|
+
return Number.isNaN(_v);
|
|
16
|
+
}
|
|
17
|
+
function isPlainSymbol(_v) {
|
|
18
|
+
return isSymbol(_v) && isUndef(Symbol.keyFor(_v));
|
|
19
|
+
}
|
|
20
|
+
function isObject(_v) {
|
|
21
|
+
return 'object' == typeof _v && !isNull(_v);
|
|
22
|
+
}
|
|
23
|
+
function isPlainObject(_v) {
|
|
24
|
+
return isObject(_v) && !isArray(_v);
|
|
25
|
+
}
|
|
26
|
+
function isArray(_v) {
|
|
27
|
+
return Array.isArray(_v);
|
|
28
|
+
}
|
|
29
|
+
function isEmptyArray(_v) {
|
|
30
|
+
return isArray(_v) && 0 === _v.length;
|
|
31
|
+
}
|
|
32
|
+
function isString(_v) {
|
|
33
|
+
return 'string' == typeof _v;
|
|
34
|
+
}
|
|
35
|
+
function isEmptyString(_v) {
|
|
36
|
+
return isString(_v) && 0 === _v.length;
|
|
37
|
+
}
|
|
38
|
+
function isNumber(_v) {
|
|
39
|
+
return 'number' == typeof _v;
|
|
40
|
+
}
|
|
41
|
+
function isPlainNumber(_v) {
|
|
42
|
+
return isNumber(_v) && !verify_isNaN(_v);
|
|
43
|
+
}
|
|
44
|
+
function isPropertyKey(_v) {
|
|
45
|
+
return isString(_v) || isNumber(_v) || isSymbol(_v);
|
|
46
|
+
}
|
|
47
|
+
function isBoolean(_v) {
|
|
48
|
+
return 'boolean' == typeof _v;
|
|
49
|
+
}
|
|
50
|
+
function isTrue(_v) {
|
|
51
|
+
return true === _v || isString(_v) && 'true' === _v.toLowerCase();
|
|
52
|
+
}
|
|
53
|
+
function isFalse(_v) {
|
|
54
|
+
return false === _v || isString(_v) && 'false' === _v.toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
function isTruthy(_v) {
|
|
57
|
+
return !!_v;
|
|
58
|
+
}
|
|
59
|
+
function isFalsy(_v) {
|
|
60
|
+
return !(verify_isNaN(_v) || _v);
|
|
61
|
+
}
|
|
62
|
+
function isFunction(_v) {
|
|
63
|
+
return 'function' == typeof _v;
|
|
64
|
+
}
|
|
65
|
+
function isPromiseLike(_v) {
|
|
66
|
+
return isObject(_v) && isFunction(_v.then);
|
|
67
|
+
}
|
|
2
68
|
function withResolvers() {
|
|
3
69
|
return 'function' == typeof Promise.withResolvers ? Promise.withResolvers() : (()=>{
|
|
4
70
|
const resolver = {
|
|
@@ -13,10 +79,135 @@ function withResolvers() {
|
|
|
13
79
|
return resolver;
|
|
14
80
|
})();
|
|
15
81
|
}
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
82
|
+
function detectCycle(from, to, waitingForGraph) {
|
|
83
|
+
const visited = new Set();
|
|
84
|
+
const queue = [
|
|
85
|
+
to
|
|
86
|
+
];
|
|
87
|
+
let head = 0;
|
|
88
|
+
while(head < queue.length){
|
|
89
|
+
const node = queue[head++];
|
|
90
|
+
if (node === from) return true;
|
|
91
|
+
if (visited.has(node)) continue;
|
|
92
|
+
visited.add(node);
|
|
93
|
+
const deps = waitingForGraph.get(node);
|
|
94
|
+
if (deps) {
|
|
95
|
+
const depsIter = deps.values();
|
|
96
|
+
for(let dep = depsIter.next(); !dep.done; dep = depsIter.next())queue.push(dep.value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
function getCached(results, depName, allSettled) {
|
|
102
|
+
if (Reflect.getOwnPropertyDescriptor(results, depName)) {
|
|
103
|
+
const cached = results[depName];
|
|
104
|
+
if (allSettled) return 'rejected' === cached.status ? Promise.reject(cached.reason) : Promise.resolve(cached.value);
|
|
105
|
+
return Promise.resolve(cached);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function createDepResolver(waitingFor, resolverMap, currentTask, depName) {
|
|
109
|
+
waitingFor.set(currentTask, (waitingFor.get(currentTask) || new Set()).add(depName));
|
|
110
|
+
const depResolvers = resolverMap.get(depName) || withResolvers();
|
|
111
|
+
resolverMap.set(depName, depResolvers);
|
|
112
|
+
return depResolvers.promise.then((value)=>{
|
|
113
|
+
waitingFor.get(currentTask)?.delete(depName);
|
|
114
|
+
return value;
|
|
115
|
+
}, (error)=>{
|
|
116
|
+
waitingFor.get(currentTask)?.delete(depName);
|
|
117
|
+
throw error;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function cleanWaitingForGraph(waitingForGraph, depName) {
|
|
121
|
+
waitingForGraph.forEach((deps, task)=>{
|
|
122
|
+
deps.delete(depName);
|
|
123
|
+
if (0 === deps.size) waitingForGraph.delete(task);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function createDepProxy(tasks, results, options) {
|
|
127
|
+
const resolverMap = new Map();
|
|
128
|
+
const taskNameSet = new Set(Reflect.ownKeys(tasks));
|
|
129
|
+
const waitingForGraph = new Map();
|
|
130
|
+
const resolveDepFor = (depName, value)=>{
|
|
131
|
+
const resolver = resolverMap.get(depName);
|
|
132
|
+
if (resolver) {
|
|
133
|
+
resolver.resolve(value);
|
|
134
|
+
resolverMap.delete(depName);
|
|
135
|
+
}
|
|
136
|
+
cleanWaitingForGraph(waitingForGraph, depName);
|
|
137
|
+
};
|
|
138
|
+
const rejectDepFor = (depName, error)=>{
|
|
139
|
+
const resolver = resolverMap.get(depName);
|
|
140
|
+
if (resolver) {
|
|
141
|
+
resolver.reject(error);
|
|
142
|
+
resolverMap.delete(depName);
|
|
143
|
+
}
|
|
144
|
+
cleanWaitingForGraph(waitingForGraph, depName);
|
|
145
|
+
};
|
|
146
|
+
const createContextFor = (currentTask)=>new Proxy({}, {
|
|
147
|
+
get (_, depName) {
|
|
148
|
+
if (!taskNameSet.has(depName)) return Promise.reject(createError('allx', `Unknown task "${String(depName)}"`));
|
|
149
|
+
const cached = getCached(results, depName, options.allSettled);
|
|
150
|
+
if (cached) return cached;
|
|
151
|
+
if (detectCycle(currentTask, depName, waitingForGraph)) return Promise.reject(createError('allx', `Circular dependency detected: "${String(currentTask)}" -> "${String(depName)}"`));
|
|
152
|
+
return createDepResolver(waitingForGraph, resolverMap, currentTask, depName);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
taskNameSet,
|
|
157
|
+
createContextFor,
|
|
158
|
+
resolveDepFor,
|
|
159
|
+
rejectDepFor
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function getValueFormatFunc(options) {
|
|
163
|
+
if (!options) return (value, _type = 'fulfilled')=>value;
|
|
164
|
+
if (options.allSettled) return (value, status = 'fulfilled')=>'fulfilled' === status ? {
|
|
165
|
+
status,
|
|
166
|
+
value
|
|
167
|
+
} : {
|
|
168
|
+
status,
|
|
169
|
+
reason: value
|
|
170
|
+
};
|
|
171
|
+
return (value, _type = 'fulfilled')=>value;
|
|
172
|
+
}
|
|
173
|
+
const validInfo = $dt({
|
|
174
|
+
allSettled: $t.boolean(false)
|
|
175
|
+
});
|
|
176
|
+
async function allx(tasks, options) {
|
|
177
|
+
const validOptions = dataHandler(options || {}, validInfo, {
|
|
178
|
+
unwrap: true
|
|
179
|
+
});
|
|
180
|
+
const { allSettled } = validOptions;
|
|
181
|
+
const results = {};
|
|
182
|
+
const depCtrl = createDepProxy(tasks, results, validOptions);
|
|
183
|
+
const valueFormat = getValueFormatFunc(options);
|
|
184
|
+
const promises = [];
|
|
185
|
+
depCtrl.taskNameSet.forEach(async (taskName)=>{
|
|
186
|
+
const taskFn = tasks[taskName];
|
|
187
|
+
const context = {
|
|
188
|
+
$: depCtrl.createContextFor(taskName)
|
|
189
|
+
};
|
|
190
|
+
const taskResolvers = withResolvers();
|
|
191
|
+
taskResolvers.promise.then((value)=>{
|
|
192
|
+
results[taskName] = valueFormat(value, 'fulfilled');
|
|
193
|
+
depCtrl.resolveDepFor(taskName, value);
|
|
194
|
+
return value;
|
|
195
|
+
}, (error)=>{
|
|
196
|
+
if (allSettled) results[taskName] = valueFormat(error, 'rejected');
|
|
197
|
+
depCtrl.rejectDepFor(taskName, error);
|
|
198
|
+
});
|
|
199
|
+
promises.push(taskResolvers.promise);
|
|
200
|
+
if (isPromiseLike(taskFn)) return void await taskFn.then(taskResolvers.resolve, taskResolvers.reject);
|
|
201
|
+
if (!isFunction(taskFn)) return void taskResolvers.resolve(taskFn);
|
|
202
|
+
try {
|
|
203
|
+
const result = await taskFn.call(context);
|
|
204
|
+
taskResolvers.resolve(result);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
taskResolvers.reject(error);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
if (allSettled) return Promise.allSettled(promises).then(()=>results);
|
|
210
|
+
return Promise.all(promises).then(()=>results);
|
|
20
211
|
}
|
|
21
212
|
function getNextValueHandler(from, to, valueFormatter) {
|
|
22
213
|
const type = getType(from);
|
|
@@ -148,17 +339,7 @@ function createRunningControllerSignal(startFn, options) {
|
|
|
148
339
|
};
|
|
149
340
|
return ctrl;
|
|
150
341
|
}
|
|
151
|
-
|
|
152
|
-
if (!Number.isInteger(step) || step <= 0) throwError('stepAnimation', 'step must be a positive integer', RangeError);
|
|
153
|
-
const { parser: valueParser = identity, formatter: valueFormatter = identity } = options;
|
|
154
|
-
const [validFrom, validTo] = matchValid(from, to, valueParser);
|
|
155
|
-
const getNextValue = getNextValueHandler(validFrom, validTo, valueFormatter);
|
|
156
|
-
for(let i = 0; i <= step; i++){
|
|
157
|
-
const value = getNextValue(i / step);
|
|
158
|
-
yield value;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const validInfo = $dt({
|
|
342
|
+
const animation_validInfo = $dt({
|
|
162
343
|
autoStart: $t.boolean(true),
|
|
163
344
|
easing: $t["function"](()=>identity),
|
|
164
345
|
onStart: $t["function"](()=>noop),
|
|
@@ -166,17 +347,32 @@ const validInfo = $dt({
|
|
|
166
347
|
onClear: $t["function"](()=>noop),
|
|
167
348
|
onUpdate: $t["function"](()=>noop),
|
|
168
349
|
onComplete: $t["function"](()=>noop),
|
|
350
|
+
formatterValue: $t["function"](()=>identity),
|
|
169
351
|
formatter: $t["function"](()=>identity),
|
|
170
352
|
parser: $t["function"](()=>identity)
|
|
171
353
|
});
|
|
354
|
+
function* stepAnimation(from, to, step, options = {}) {
|
|
355
|
+
if (!Number.isInteger(step) || step <= 0) throwError('stepAnimation', 'step must be a positive integer', RangeError);
|
|
356
|
+
const validOptions = dataHandler(options, animation_validInfo, {
|
|
357
|
+
unwrap: true
|
|
358
|
+
});
|
|
359
|
+
const { parser: valueParser = identity, formatterValue = identity, formatter } = validOptions;
|
|
360
|
+
const [validFrom, validTo] = matchValid(from, to, valueParser);
|
|
361
|
+
const getNextValue = getNextValueHandler(validFrom, validTo, formatterValue);
|
|
362
|
+
for(let i = 0; i <= step; i++){
|
|
363
|
+
const value = formatter(getNextValue(i / step));
|
|
364
|
+
yield value;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
172
367
|
function animation(from, to, duration, options = {}) {
|
|
173
368
|
if (duration <= 0 || !Number.isInteger(duration)) throwError('animation', 'duration must be a positive integer', RangeError);
|
|
174
|
-
const validOptions = dataHandler(options,
|
|
369
|
+
const validOptions = dataHandler(options, animation_validInfo, {
|
|
175
370
|
unwrap: true
|
|
176
371
|
});
|
|
177
372
|
const [validFrom, validTo] = matchValid(from, to, validOptions.parser);
|
|
178
|
-
const { autoStart, easing, onComplete, onUpdate, formatter
|
|
179
|
-
const
|
|
373
|
+
const { autoStart, easing, onComplete, onUpdate, formatterValue, formatter } = validOptions;
|
|
374
|
+
const _getNextValue = getNextValueHandler(validFrom, validTo, formatterValue);
|
|
375
|
+
const getNextValue = (...args)=>formatter(_getNextValue(...args));
|
|
180
376
|
let startTime = 0;
|
|
181
377
|
let hasStarted = false;
|
|
182
378
|
const rcSignal = createRunningControllerSignal(()=>{
|
|
@@ -307,5 +503,235 @@ function createStorageHandler(storageKey, initialData, options = {}) {
|
|
|
307
503
|
}
|
|
308
504
|
};
|
|
309
505
|
}
|
|
506
|
+
const SLOT_TYPE = {
|
|
507
|
+
fixed: {
|
|
508
|
+
fixedFlag: Symbol('fixed')
|
|
509
|
+
},
|
|
510
|
+
insert: {
|
|
511
|
+
insertFlag: Symbol('insert')
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
const data_mixed_manager_validInfo = $dt({
|
|
515
|
+
name: $t.string('default'),
|
|
516
|
+
fixedSlots: $t.array([]),
|
|
517
|
+
dataList: $t.array([]),
|
|
518
|
+
listener: $t.object({})
|
|
519
|
+
});
|
|
520
|
+
class DataMixedManager extends EventTarget {
|
|
521
|
+
addEventListener(...args) {
|
|
522
|
+
return super.addEventListener.apply(this, args);
|
|
523
|
+
}
|
|
524
|
+
removeEventListener(...args) {
|
|
525
|
+
return super.removeEventListener.apply(this, args);
|
|
526
|
+
}
|
|
527
|
+
options;
|
|
528
|
+
fixedSlots = new Map();
|
|
529
|
+
dataList = [];
|
|
530
|
+
mixedData = [];
|
|
531
|
+
lastMixedSlotIdx = -1;
|
|
532
|
+
prevDataLength = 0;
|
|
533
|
+
isBatching = false;
|
|
534
|
+
constructor(options){
|
|
535
|
+
super();
|
|
536
|
+
const validOptions = dataHandler(options || {}, data_mixed_manager_validInfo, {
|
|
537
|
+
unwrap: true
|
|
538
|
+
});
|
|
539
|
+
const { fixedSlots, dataList, listener } = validOptions;
|
|
540
|
+
this.options = validOptions;
|
|
541
|
+
this.addFixedSlots(fixedSlots, {
|
|
542
|
+
lazy: true
|
|
543
|
+
});
|
|
544
|
+
this.appendList(dataList);
|
|
545
|
+
try {
|
|
546
|
+
this.initListener(listener);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
throwError('dataMixedManager', error.message, error.constructor);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
initListener(listener) {
|
|
552
|
+
const listenerNames = Object.keys(listener);
|
|
553
|
+
for(let i = 0, name = listenerNames[i], handler = listener[name]; i < listenerNames.length; name = listenerNames[++i], handler = listener[name])this.addEventListener(name, handler);
|
|
554
|
+
}
|
|
555
|
+
getTypeText(_type) {
|
|
556
|
+
switch(_type){
|
|
557
|
+
case SLOT_TYPE.fixed:
|
|
558
|
+
return 'fixed';
|
|
559
|
+
case SLOT_TYPE.insert:
|
|
560
|
+
return 'insert';
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
buildSlotConfig(config, type) {
|
|
564
|
+
const typeText = this.getTypeText(config.type || type);
|
|
565
|
+
return {
|
|
566
|
+
...config,
|
|
567
|
+
type: typeText,
|
|
568
|
+
inputPosition: config.position,
|
|
569
|
+
insertMode: config.insertMode || 'cover'
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
addFixedSlot(config, buildOptions) {
|
|
573
|
+
const realConfig = this.reorderFixedSlots(this.buildSlotConfig(config, SLOT_TYPE.fixed));
|
|
574
|
+
this.fixedSlots.set(realConfig.position, realConfig);
|
|
575
|
+
this.buildMixedData(buildOptions);
|
|
576
|
+
return realConfig.position;
|
|
577
|
+
}
|
|
578
|
+
reorderFixedSlots(config) {
|
|
579
|
+
const { position: oldPosition, insertMode } = config;
|
|
580
|
+
if (null == insertMode || 'cover' === insertMode || !this.fixedSlots.has(oldPosition)) return {
|
|
581
|
+
...config,
|
|
582
|
+
inputPosition: oldPosition
|
|
583
|
+
};
|
|
584
|
+
const position = 'after' === insertMode ? oldPosition + 1 : oldPosition;
|
|
585
|
+
for(let i = position + 1, preItem = this.fixedSlots.get(i - 1), currItem = this.fixedSlots.get(i); preItem; ++i, preItem = currItem, currItem = this.fixedSlots.get(i)){
|
|
586
|
+
preItem.position = i;
|
|
587
|
+
this.fixedSlots.set(i, preItem);
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
...config,
|
|
591
|
+
position,
|
|
592
|
+
inputPosition: oldPosition
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
addFixedSlots(configs, buildOptions) {
|
|
596
|
+
if (!configs.length) return [];
|
|
597
|
+
const positions = this.batchUpdate(()=>configs.map((config)=>this.addFixedSlot(config)));
|
|
598
|
+
this.buildMixedData(buildOptions);
|
|
599
|
+
return positions;
|
|
600
|
+
}
|
|
601
|
+
deleteFixedSlot(position, buildOptions) {
|
|
602
|
+
this.fixedSlots.delete(position);
|
|
603
|
+
this.buildMixedData(buildOptions);
|
|
604
|
+
}
|
|
605
|
+
deleteFixedSlots(positions, buildOptions) {
|
|
606
|
+
if (!positions.length) return;
|
|
607
|
+
this.batchUpdate(()=>positions.forEach((position)=>void this.deleteFixedSlot(position)));
|
|
608
|
+
this.buildMixedData(buildOptions);
|
|
609
|
+
}
|
|
610
|
+
batchUpdate(callback) {
|
|
611
|
+
try {
|
|
612
|
+
this.isBatching = true;
|
|
613
|
+
const result = callback();
|
|
614
|
+
return result;
|
|
615
|
+
} finally{
|
|
616
|
+
this.isBatching = false;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
clearFixedSlots(buildOptions) {
|
|
620
|
+
this.fixedSlots.clear();
|
|
621
|
+
this.buildMixedData(buildOptions);
|
|
622
|
+
}
|
|
623
|
+
appendList(list, buildOptions) {
|
|
624
|
+
if (!list.length) return;
|
|
625
|
+
this.dataList.push(...list);
|
|
626
|
+
this.buildMixedData({
|
|
627
|
+
...buildOptions,
|
|
628
|
+
lazy: true === (buildOptions || {}).lazy
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
clearList() {
|
|
632
|
+
this.dataList.length = 0;
|
|
633
|
+
this.mixedData.length = 0;
|
|
634
|
+
this.dispatch('change', {
|
|
635
|
+
mode: 'clear',
|
|
636
|
+
mixedData: this.getMixedData({
|
|
637
|
+
mode: 'rebuild'
|
|
638
|
+
})
|
|
639
|
+
});
|
|
640
|
+
this.dispatch('clear');
|
|
641
|
+
}
|
|
642
|
+
getMixedData(buildOptions) {
|
|
643
|
+
this.buildMixedData({
|
|
644
|
+
...buildOptions,
|
|
645
|
+
lazy: false
|
|
646
|
+
});
|
|
647
|
+
return this.mixedData.slice();
|
|
648
|
+
}
|
|
649
|
+
dispatch(name, data) {
|
|
650
|
+
const detail = {
|
|
651
|
+
name: this.options.name,
|
|
652
|
+
...data
|
|
653
|
+
};
|
|
654
|
+
this.dispatchEvent(new CustomEvent(name, {
|
|
655
|
+
detail
|
|
656
|
+
}));
|
|
657
|
+
if ("u" > typeof window) window.dispatchEvent(new CustomEvent(`[DMM]:${name}`, {
|
|
658
|
+
detail
|
|
659
|
+
}));
|
|
660
|
+
}
|
|
661
|
+
buildMixedData(buildOptions) {
|
|
662
|
+
if (this.isBatching) return;
|
|
663
|
+
const { lazy, mode } = buildOptions || {};
|
|
664
|
+
if ('rebuild' === mode) {
|
|
665
|
+
this.prevDataLength = 0;
|
|
666
|
+
this.lastMixedSlotIdx = -1;
|
|
667
|
+
}
|
|
668
|
+
if (false !== lazy || this.dataList.length <= this.prevDataLength) return;
|
|
669
|
+
let dataStartIdx = this.prevDataLength;
|
|
670
|
+
const dataEndIdx = this.dataList.length;
|
|
671
|
+
const newItemCount = dataEndIdx - dataStartIdx;
|
|
672
|
+
this.prevDataLength = dataEndIdx;
|
|
673
|
+
const isPatchMode = dataStartIdx > 0;
|
|
674
|
+
const filteredSlots = this.sliceSlots(isPatchMode ? this.mixedData.length : this.lastMixedSlotIdx, this.mixedData.length + newItemCount);
|
|
675
|
+
this.lastMixedSlotIdx = filteredSlots.at(-1) ?? this.lastMixedSlotIdx;
|
|
676
|
+
let mixedStartIdx = isPatchMode ? this.mixedData.length : 0;
|
|
677
|
+
this.mixedData.length = (isPatchMode ? newItemCount + mixedStartIdx : dataEndIdx) + filteredSlots.length;
|
|
678
|
+
for(let fpIdx = 0, fpItem = filteredSlots[fpIdx]; dataStartIdx < dataEndIdx; ++mixedStartIdx)if (mixedStartIdx === fpItem) {
|
|
679
|
+
const fixedSlot = this.fixedSlots.get(fpItem);
|
|
680
|
+
this.mixedData[mixedStartIdx] = {
|
|
681
|
+
isFixed: true,
|
|
682
|
+
type: fixedSlot.type,
|
|
683
|
+
data: fixedSlot.data
|
|
684
|
+
};
|
|
685
|
+
fpItem = filteredSlots[++fpIdx];
|
|
686
|
+
} else {
|
|
687
|
+
this.mixedData[mixedStartIdx] = {
|
|
688
|
+
isFixed: false,
|
|
689
|
+
type: 'plain',
|
|
690
|
+
data: this.dataList[dataStartIdx]
|
|
691
|
+
};
|
|
692
|
+
++dataStartIdx;
|
|
693
|
+
}
|
|
694
|
+
this.dispatch('change', {
|
|
695
|
+
mode: isPatchMode ? 'patch' : 'rebuild',
|
|
696
|
+
mixedData: this.mixedData.slice()
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
sliceSlots(startIdx, endIdx = 1 / 0) {
|
|
700
|
+
let prevItem = -2;
|
|
701
|
+
let count = 0;
|
|
702
|
+
return Array.from(this.fixedSlots.keys()).sort((ai, bi)=>ai - bi).filter((item)=>{
|
|
703
|
+
if (item >= startIdx && item < endIdx + count || item - 1 === prevItem) {
|
|
704
|
+
++count;
|
|
705
|
+
prevItem = item;
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
return false;
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
insertSlot(config) {
|
|
712
|
+
const realPosition = this.addFixedSlot({
|
|
713
|
+
...config,
|
|
714
|
+
type: SLOT_TYPE.insert
|
|
715
|
+
});
|
|
716
|
+
if (realPosition > this.mixedData.length) return realPosition;
|
|
717
|
+
this.buildMixedData({
|
|
718
|
+
lazy: false,
|
|
719
|
+
mode: 'rebuild'
|
|
720
|
+
});
|
|
721
|
+
return realPosition;
|
|
722
|
+
}
|
|
723
|
+
insertSlots(configs) {
|
|
724
|
+
if (!configs.length) return [];
|
|
725
|
+
const positions = this.batchUpdate(()=>configs.map((config)=>this.insertSlot(config)));
|
|
726
|
+
this.buildMixedData({
|
|
727
|
+
lazy: false,
|
|
728
|
+
mode: 'rebuild'
|
|
729
|
+
});
|
|
730
|
+
return positions;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
function dataMixedManager(options) {
|
|
734
|
+
return new DataMixedManager(options);
|
|
735
|
+
}
|
|
310
736
|
Symbol('__PACK__');
|
|
311
|
-
export { animation, conditionMerge, createStorageHandler, stepAnimation, withResolvers };
|
|
737
|
+
export { allx, animation, conditionMerge, createStorageHandler, dataMixedManager, isArray, isBoolean, isEmptyArray, isEmptyString, isFalse, isFalsy, isFunction, isNull, isNullOrUndef, isNumber, isObject, isPlainNumber, isPlainObject, isPlainSymbol, isPromiseLike, isPropertyKey, isString, isSymbol, isTrue, isTruthy, isUndef, stepAnimation, verify_isNaN as isNaN, withResolvers };
|
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
|
|
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
|
}
|
|
@@ -133,4 +138,4 @@ function dataHandler(data, handler, options) {
|
|
|
133
138
|
errors: ctx.errors
|
|
134
139
|
};
|
|
135
140
|
}
|
|
136
|
-
export { $dt, $t, dataHandler, defineTransform, logger, throwError, throwType };
|
|
141
|
+
export { $dt, $t, createError, dataHandler, defineTransform, getType, identity, logger, noop, throwError, throwType };
|
package/dist/react/index.js
CHANGED
|
@@ -138,9 +138,7 @@ function useMount(callback) {
|
|
|
138
138
|
callbackRef.current();
|
|
139
139
|
}, []);
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
return structuredClone(_v);
|
|
143
|
-
}
|
|
141
|
+
const clone = structuredClone;
|
|
144
142
|
function useRefState(initialState) {
|
|
145
143
|
const stateRef = useRef(initialState);
|
|
146
144
|
const forceUpdate = useForceUpdate();
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { useMemo, useRef } from "react";
|
|
2
2
|
import { useForceUpdate } from "../use-force-update/index.js";
|
|
3
|
-
|
|
4
|
-
return structuredClone(_v);
|
|
5
|
-
}
|
|
3
|
+
const clone = structuredClone;
|
|
6
4
|
function useRefState(initialState) {
|
|
7
5
|
const stateRef = useRef(initialState);
|
|
8
6
|
const forceUpdate = useForceUpdate();
|
|
@@ -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 @@
|
|
|
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;
|