@djvlc/runtime-host-vue 1.0.1 → 1.0.3
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/index.cjs +674 -81
- package/dist/index.d.cts +247 -18
- package/dist/index.d.ts +247 -18
- package/dist/index.js +699 -97
- package/package.json +4 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/vue-runtime.ts
|
|
2
|
-
import { ref, shallowRef, readonly } from "vue";
|
|
2
|
+
import { ref, shallowRef, readonly, computed } from "vue";
|
|
3
3
|
import {
|
|
4
4
|
createRuntime
|
|
5
5
|
} from "@djvlc/runtime-core";
|
|
@@ -10,11 +10,33 @@ function createVueRuntime(options) {
|
|
|
10
10
|
const page = shallowRef(null);
|
|
11
11
|
const error = shallowRef(null);
|
|
12
12
|
const hostApi = shallowRef(null);
|
|
13
|
+
const isReady = computed(() => phase.value === "ready");
|
|
14
|
+
const hasError = computed(() => phase.value === "error" || error.value !== null);
|
|
15
|
+
const metrics = shallowRef({
|
|
16
|
+
initTime: 0,
|
|
17
|
+
loadTime: 0,
|
|
18
|
+
renderTime: 0,
|
|
19
|
+
totalTime: 0,
|
|
20
|
+
initTimestamp: null,
|
|
21
|
+
readyTimestamp: null
|
|
22
|
+
});
|
|
23
|
+
let startTime = 0;
|
|
24
|
+
let initStartTime = 0;
|
|
25
|
+
let loadStartTime = 0;
|
|
26
|
+
let renderStartTime = 0;
|
|
13
27
|
const init = async () => {
|
|
14
28
|
const container = options.containerRef?.value;
|
|
15
29
|
if (!container) {
|
|
16
30
|
throw new Error("Container element not found");
|
|
17
31
|
}
|
|
32
|
+
startTime = performance.now();
|
|
33
|
+
initStartTime = startTime;
|
|
34
|
+
if (options.enableMetrics) {
|
|
35
|
+
metrics.value = {
|
|
36
|
+
...metrics.value,
|
|
37
|
+
initTimestamp: Date.now()
|
|
38
|
+
};
|
|
39
|
+
}
|
|
18
40
|
const runtimeInstance = createRuntime({
|
|
19
41
|
...options,
|
|
20
42
|
container,
|
|
@@ -39,22 +61,45 @@ function createVueRuntime(options) {
|
|
|
39
61
|
});
|
|
40
62
|
await runtimeInstance.init();
|
|
41
63
|
hostApi.value = runtimeInstance.getHostApi();
|
|
64
|
+
if (options.enableMetrics) {
|
|
65
|
+
metrics.value = {
|
|
66
|
+
...metrics.value,
|
|
67
|
+
initTime: performance.now() - initStartTime
|
|
68
|
+
};
|
|
69
|
+
}
|
|
42
70
|
};
|
|
43
71
|
const load = async () => {
|
|
44
72
|
if (!runtime.value) {
|
|
45
73
|
throw new Error("Runtime not initialized");
|
|
46
74
|
}
|
|
75
|
+
loadStartTime = performance.now();
|
|
47
76
|
const result = await runtime.value.load();
|
|
48
77
|
page.value = result;
|
|
49
78
|
hostApi.value = runtime.value.getHostApi();
|
|
79
|
+
if (options.enableMetrics) {
|
|
80
|
+
metrics.value = {
|
|
81
|
+
...metrics.value,
|
|
82
|
+
loadTime: performance.now() - loadStartTime
|
|
83
|
+
};
|
|
84
|
+
}
|
|
50
85
|
return result;
|
|
51
86
|
};
|
|
52
87
|
const render = async () => {
|
|
53
88
|
if (!runtime.value) {
|
|
54
89
|
throw new Error("Runtime not initialized");
|
|
55
90
|
}
|
|
91
|
+
renderStartTime = performance.now();
|
|
56
92
|
await runtime.value.render();
|
|
57
93
|
loading.value = false;
|
|
94
|
+
if (options.enableMetrics) {
|
|
95
|
+
const now = performance.now();
|
|
96
|
+
metrics.value = {
|
|
97
|
+
...metrics.value,
|
|
98
|
+
renderTime: now - renderStartTime,
|
|
99
|
+
totalTime: now - startTime,
|
|
100
|
+
readyTimestamp: Date.now()
|
|
101
|
+
};
|
|
102
|
+
}
|
|
58
103
|
};
|
|
59
104
|
const destroy = () => {
|
|
60
105
|
runtime.value?.destroy();
|
|
@@ -65,12 +110,41 @@ function createVueRuntime(options) {
|
|
|
65
110
|
phase.value = "idle";
|
|
66
111
|
loading.value = true;
|
|
67
112
|
};
|
|
113
|
+
const reload = async () => {
|
|
114
|
+
if (!runtime.value) {
|
|
115
|
+
throw new Error("Runtime not initialized");
|
|
116
|
+
}
|
|
117
|
+
error.value = null;
|
|
118
|
+
loading.value = true;
|
|
119
|
+
await load();
|
|
120
|
+
await render();
|
|
121
|
+
};
|
|
68
122
|
const setVariable = (key, value) => {
|
|
69
123
|
runtime.value?.setVariable(key, value);
|
|
70
124
|
};
|
|
125
|
+
const setVariables = (variables) => {
|
|
126
|
+
if (!runtime.value) return;
|
|
127
|
+
Object.entries(variables).forEach(([key, value]) => {
|
|
128
|
+
runtime.value?.setVariable(key, value);
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
const getVariable = (key) => {
|
|
132
|
+
return runtime.value?.getState().variables[key];
|
|
133
|
+
};
|
|
71
134
|
const refreshData = async (queryId) => {
|
|
72
135
|
await runtime.value?.refreshData(queryId);
|
|
73
136
|
};
|
|
137
|
+
const executeAction = async (actionType, params) => {
|
|
138
|
+
const api = hostApi.value;
|
|
139
|
+
if (!api) {
|
|
140
|
+
throw new Error("HostAPI not available");
|
|
141
|
+
}
|
|
142
|
+
const response = await api.executeAction(actionType, params || {});
|
|
143
|
+
if (response.success) {
|
|
144
|
+
return response.data;
|
|
145
|
+
}
|
|
146
|
+
throw new Error(response.errorMessage || "Action failed");
|
|
147
|
+
};
|
|
74
148
|
return {
|
|
75
149
|
runtime,
|
|
76
150
|
loading: readonly(loading),
|
|
@@ -78,12 +152,19 @@ function createVueRuntime(options) {
|
|
|
78
152
|
page,
|
|
79
153
|
error,
|
|
80
154
|
hostApi,
|
|
155
|
+
isReady,
|
|
156
|
+
hasError,
|
|
157
|
+
metrics,
|
|
81
158
|
init,
|
|
82
159
|
load,
|
|
83
160
|
render,
|
|
84
161
|
destroy,
|
|
162
|
+
reload,
|
|
85
163
|
setVariable,
|
|
86
|
-
|
|
164
|
+
setVariables,
|
|
165
|
+
getVariable,
|
|
166
|
+
refreshData,
|
|
167
|
+
executeAction
|
|
87
168
|
};
|
|
88
169
|
}
|
|
89
170
|
|
|
@@ -91,15 +172,25 @@ function createVueRuntime(options) {
|
|
|
91
172
|
import {
|
|
92
173
|
defineComponent,
|
|
93
174
|
ref as ref3,
|
|
94
|
-
shallowRef as
|
|
95
|
-
onMounted,
|
|
175
|
+
shallowRef as shallowRef3,
|
|
176
|
+
onMounted as onMounted2,
|
|
96
177
|
onUnmounted as onUnmounted2,
|
|
97
|
-
watch,
|
|
178
|
+
watch as watch2,
|
|
98
179
|
h
|
|
99
180
|
} from "vue";
|
|
100
181
|
|
|
101
182
|
// src/composables/useRuntime.ts
|
|
102
|
-
import {
|
|
183
|
+
import {
|
|
184
|
+
inject,
|
|
185
|
+
provide,
|
|
186
|
+
readonly as readonly2,
|
|
187
|
+
ref as ref2,
|
|
188
|
+
shallowRef as shallowRef2,
|
|
189
|
+
computed as computed2,
|
|
190
|
+
watch,
|
|
191
|
+
onMounted,
|
|
192
|
+
onUnmounted
|
|
193
|
+
} from "vue";
|
|
103
194
|
var RuntimeContextKey = /* @__PURE__ */ Symbol("DJVRuntime");
|
|
104
195
|
function provideRuntime(value) {
|
|
105
196
|
provide(RuntimeContextKey, value);
|
|
@@ -113,16 +204,30 @@ function injectRuntime() {
|
|
|
113
204
|
}
|
|
114
205
|
function useDJVRuntime() {
|
|
115
206
|
const context = injectRuntime();
|
|
207
|
+
const loading = computed2(() => {
|
|
208
|
+
const phase = context.value.state.phase;
|
|
209
|
+
return phase !== "ready" && phase !== "error";
|
|
210
|
+
});
|
|
211
|
+
const isReady = computed2(() => context.value.state.phase === "ready");
|
|
212
|
+
const hasError = computed2(() => context.value.state.phase === "error" || context.value.state.error !== null);
|
|
213
|
+
const reload = async () => {
|
|
214
|
+
const runtime = context.value.runtime;
|
|
215
|
+
if (!runtime) {
|
|
216
|
+
throw new Error("Runtime not available");
|
|
217
|
+
}
|
|
218
|
+
await runtime.load();
|
|
219
|
+
await runtime.render();
|
|
220
|
+
};
|
|
116
221
|
return {
|
|
117
|
-
runtime:
|
|
118
|
-
state:
|
|
119
|
-
loading
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
222
|
+
runtime: computed2(() => context.value.runtime),
|
|
223
|
+
state: computed2(() => context.value.state),
|
|
224
|
+
loading,
|
|
225
|
+
phase: computed2(() => context.value.state.phase),
|
|
226
|
+
error: computed2(() => context.value.state.error),
|
|
227
|
+
page: computed2(() => context.value.state.page),
|
|
228
|
+
isReady,
|
|
229
|
+
hasError,
|
|
230
|
+
reload
|
|
126
231
|
};
|
|
127
232
|
}
|
|
128
233
|
function useHostApi() {
|
|
@@ -135,13 +240,13 @@ function useHostApi() {
|
|
|
135
240
|
}
|
|
136
241
|
function useRuntimeState(key) {
|
|
137
242
|
const context = injectRuntime();
|
|
138
|
-
return
|
|
243
|
+
return computed2(() => {
|
|
139
244
|
return context.value.state.variables[key];
|
|
140
245
|
});
|
|
141
246
|
}
|
|
142
247
|
function useRuntimeStateWritable(key, defaultValue) {
|
|
143
248
|
const context = injectRuntime();
|
|
144
|
-
const value =
|
|
249
|
+
const value = computed2(() => {
|
|
145
250
|
return context.value.state.variables[key] ?? defaultValue;
|
|
146
251
|
});
|
|
147
252
|
const setValue = (newValue) => {
|
|
@@ -149,11 +254,13 @@ function useRuntimeStateWritable(key, defaultValue) {
|
|
|
149
254
|
};
|
|
150
255
|
return [value, setValue];
|
|
151
256
|
}
|
|
152
|
-
function useQuery(queryId) {
|
|
257
|
+
function useQuery(queryId, options) {
|
|
153
258
|
const context = injectRuntime();
|
|
154
259
|
const loading = ref2(false);
|
|
155
260
|
const error = ref2(null);
|
|
156
|
-
const
|
|
261
|
+
const lastUpdated = ref2(null);
|
|
262
|
+
let intervalTimer = null;
|
|
263
|
+
const data = computed2(() => {
|
|
157
264
|
return context.value.state.queries[queryId];
|
|
158
265
|
});
|
|
159
266
|
const refetch = async () => {
|
|
@@ -161,41 +268,84 @@ function useQuery(queryId) {
|
|
|
161
268
|
error.value = null;
|
|
162
269
|
try {
|
|
163
270
|
await context.value.runtime?.refreshData(queryId);
|
|
271
|
+
lastUpdated.value = Date.now();
|
|
164
272
|
} catch (e) {
|
|
165
273
|
error.value = e;
|
|
166
274
|
} finally {
|
|
167
275
|
loading.value = false;
|
|
168
276
|
}
|
|
169
277
|
};
|
|
278
|
+
onMounted(() => {
|
|
279
|
+
if (options?.refreshOnMount && context.value.runtime) {
|
|
280
|
+
refetch();
|
|
281
|
+
}
|
|
282
|
+
if (options?.refreshInterval && options.refreshInterval > 0) {
|
|
283
|
+
intervalTimer = setInterval(refetch, options.refreshInterval);
|
|
284
|
+
}
|
|
285
|
+
if (options?.refreshOnFocus) {
|
|
286
|
+
window.addEventListener("focus", refetch);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
onUnmounted(() => {
|
|
290
|
+
if (intervalTimer) {
|
|
291
|
+
clearInterval(intervalTimer);
|
|
292
|
+
}
|
|
293
|
+
if (options?.refreshOnFocus) {
|
|
294
|
+
window.removeEventListener("focus", refetch);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
170
297
|
return {
|
|
171
298
|
data,
|
|
172
299
|
loading,
|
|
173
300
|
error,
|
|
174
|
-
refetch
|
|
301
|
+
refetch,
|
|
302
|
+
lastUpdated
|
|
175
303
|
};
|
|
176
304
|
}
|
|
177
|
-
function useAction(actionType) {
|
|
305
|
+
function useAction(actionType, options) {
|
|
178
306
|
const context = injectRuntime();
|
|
179
307
|
const loading = ref2(false);
|
|
180
|
-
const result =
|
|
308
|
+
const result = shallowRef2();
|
|
181
309
|
const error = ref2(null);
|
|
182
|
-
const
|
|
310
|
+
const executionCount = ref2(0);
|
|
311
|
+
const reset = () => {
|
|
312
|
+
result.value = void 0;
|
|
313
|
+
error.value = null;
|
|
314
|
+
executionCount.value = 0;
|
|
315
|
+
};
|
|
316
|
+
const executeWithRetry = async (params, retriesLeft) => {
|
|
183
317
|
const hostApi = context.value.hostApi;
|
|
184
318
|
if (!hostApi) {
|
|
185
319
|
throw new Error("HostAPI not available");
|
|
186
320
|
}
|
|
187
|
-
loading.value = true;
|
|
188
|
-
error.value = null;
|
|
189
321
|
try {
|
|
190
322
|
const response = await hostApi.executeAction(actionType, params);
|
|
191
323
|
if (response.success) {
|
|
192
|
-
result.value = response.data;
|
|
193
324
|
return response.data;
|
|
194
325
|
} else {
|
|
195
|
-
throw new Error(response.
|
|
326
|
+
throw new Error(response.errorMessage || "Action failed");
|
|
196
327
|
}
|
|
197
328
|
} catch (e) {
|
|
198
|
-
|
|
329
|
+
if (retriesLeft > 0) {
|
|
330
|
+
await new Promise((resolve) => setTimeout(resolve, options?.retryDelay || 1e3));
|
|
331
|
+
return executeWithRetry(params, retriesLeft - 1);
|
|
332
|
+
}
|
|
333
|
+
throw e;
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const execute = async (params) => {
|
|
337
|
+
loading.value = true;
|
|
338
|
+
error.value = null;
|
|
339
|
+
executionCount.value++;
|
|
340
|
+
try {
|
|
341
|
+
const data = await executeWithRetry(params, options?.retryCount || 0);
|
|
342
|
+
result.value = data;
|
|
343
|
+
options?.onSuccess?.(data);
|
|
344
|
+
return data;
|
|
345
|
+
} catch (e) {
|
|
346
|
+
const err = e;
|
|
347
|
+
error.value = err;
|
|
348
|
+
options?.onError?.(err);
|
|
199
349
|
throw e;
|
|
200
350
|
} finally {
|
|
201
351
|
loading.value = false;
|
|
@@ -205,14 +355,25 @@ function useAction(actionType) {
|
|
|
205
355
|
execute,
|
|
206
356
|
loading,
|
|
207
357
|
result,
|
|
208
|
-
error
|
|
358
|
+
error,
|
|
359
|
+
reset,
|
|
360
|
+
executionCount
|
|
209
361
|
};
|
|
210
362
|
}
|
|
211
363
|
function useData(queryId, params, options) {
|
|
212
364
|
const context = injectRuntime();
|
|
213
|
-
const data =
|
|
365
|
+
const data = shallowRef2();
|
|
214
366
|
const loading = ref2(false);
|
|
215
367
|
const error = ref2(null);
|
|
368
|
+
const isFetched = ref2(false);
|
|
369
|
+
let intervalTimer = null;
|
|
370
|
+
const getCurrentParams = () => {
|
|
371
|
+
if (!params) return void 0;
|
|
372
|
+
if (typeof params === "object" && "value" in params) {
|
|
373
|
+
return params.value;
|
|
374
|
+
}
|
|
375
|
+
return params;
|
|
376
|
+
};
|
|
216
377
|
const refetch = async (newParams) => {
|
|
217
378
|
const hostApi = context.value.hostApi;
|
|
218
379
|
if (!hostApi) {
|
|
@@ -221,29 +382,47 @@ function useData(queryId, params, options) {
|
|
|
221
382
|
loading.value = true;
|
|
222
383
|
error.value = null;
|
|
223
384
|
try {
|
|
224
|
-
const
|
|
385
|
+
const result = await hostApi.requestData(
|
|
225
386
|
queryId,
|
|
226
|
-
newParams ||
|
|
387
|
+
newParams || getCurrentParams()
|
|
227
388
|
);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
throw new Error(response.message || "Query failed");
|
|
232
|
-
}
|
|
389
|
+
data.value = result;
|
|
390
|
+
isFetched.value = true;
|
|
391
|
+
options?.onSuccess?.(result);
|
|
233
392
|
} catch (e) {
|
|
234
|
-
|
|
393
|
+
const err = e;
|
|
394
|
+
error.value = err;
|
|
395
|
+
options?.onError?.(err);
|
|
235
396
|
} finally {
|
|
236
397
|
loading.value = false;
|
|
237
398
|
}
|
|
238
399
|
};
|
|
239
|
-
if (options?.
|
|
240
|
-
|
|
400
|
+
if (params && typeof params === "object" && "value" in params && options?.refreshOnParamsChange !== false) {
|
|
401
|
+
watch(params, () => {
|
|
402
|
+
if (isFetched.value) {
|
|
403
|
+
refetch();
|
|
404
|
+
}
|
|
405
|
+
}, { deep: true });
|
|
241
406
|
}
|
|
407
|
+
onMounted(() => {
|
|
408
|
+
if (options?.immediate !== false && context.value.hostApi) {
|
|
409
|
+
refetch();
|
|
410
|
+
}
|
|
411
|
+
if (options?.refreshInterval && options.refreshInterval > 0) {
|
|
412
|
+
intervalTimer = setInterval(refetch, options.refreshInterval);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
onUnmounted(() => {
|
|
416
|
+
if (intervalTimer) {
|
|
417
|
+
clearInterval(intervalTimer);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
242
420
|
return {
|
|
243
421
|
data,
|
|
244
422
|
loading,
|
|
245
423
|
error,
|
|
246
|
-
refetch
|
|
424
|
+
refetch,
|
|
425
|
+
isFetched
|
|
247
426
|
};
|
|
248
427
|
}
|
|
249
428
|
function useRuntimeEvent(eventType, handler) {
|
|
@@ -255,6 +434,145 @@ function useRuntimeEvent(eventType, handler) {
|
|
|
255
434
|
unsubscribe?.();
|
|
256
435
|
});
|
|
257
436
|
}
|
|
437
|
+
function usePageInfo() {
|
|
438
|
+
const context = injectRuntime();
|
|
439
|
+
return {
|
|
440
|
+
/** 页面 UID */
|
|
441
|
+
pageUid: computed2(() => context.value.state.page?.pageUid),
|
|
442
|
+
/** 页面版本 ID */
|
|
443
|
+
pageVersionId: computed2(() => context.value.state.page?.pageVersionId),
|
|
444
|
+
/** Schema 版本 */
|
|
445
|
+
schemaVersion: computed2(() => context.value.state.page?.pageJson?.schemaVersion),
|
|
446
|
+
/** 页面标题 */
|
|
447
|
+
title: computed2(() => {
|
|
448
|
+
const page = context.value.state.page;
|
|
449
|
+
return page?.title;
|
|
450
|
+
}),
|
|
451
|
+
/** 页面配置 */
|
|
452
|
+
config: computed2(() => {
|
|
453
|
+
const page = context.value.state.page;
|
|
454
|
+
return page?.config;
|
|
455
|
+
}),
|
|
456
|
+
/** 页面是否已加载 */
|
|
457
|
+
isLoaded: computed2(() => context.value.state.page !== null)
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
function useComponentState(componentId) {
|
|
461
|
+
const context = injectRuntime();
|
|
462
|
+
const componentStatus = computed2(() => {
|
|
463
|
+
return context.value.state.components.get(componentId);
|
|
464
|
+
});
|
|
465
|
+
return {
|
|
466
|
+
/** 组件是否已加载 */
|
|
467
|
+
isLoaded: computed2(() => componentStatus.value?.status === "loaded"),
|
|
468
|
+
/** 组件是否加载中 */
|
|
469
|
+
isLoading: computed2(() => componentStatus.value?.status === "loading"),
|
|
470
|
+
/** 组件是否加载失败 */
|
|
471
|
+
hasError: computed2(() => componentStatus.value?.status === "failed"),
|
|
472
|
+
/** 加载耗时 */
|
|
473
|
+
loadTime: computed2(() => componentStatus.value?.loadTime),
|
|
474
|
+
/** 组件信息 */
|
|
475
|
+
info: componentStatus
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function useLifecycle(options) {
|
|
479
|
+
const context = injectRuntime();
|
|
480
|
+
const hasMounted = ref2(false);
|
|
481
|
+
const hasReady = ref2(false);
|
|
482
|
+
watch(
|
|
483
|
+
() => context.value.state.phase,
|
|
484
|
+
async (newPhase, oldPhase) => {
|
|
485
|
+
options?.onPhaseChange?.(newPhase);
|
|
486
|
+
if (!hasMounted.value && newPhase !== "idle") {
|
|
487
|
+
hasMounted.value = true;
|
|
488
|
+
try {
|
|
489
|
+
await options?.onMounted?.();
|
|
490
|
+
} catch (error) {
|
|
491
|
+
options?.onError?.(error);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
if (!hasReady.value && newPhase === "ready") {
|
|
495
|
+
hasReady.value = true;
|
|
496
|
+
try {
|
|
497
|
+
await options?.onReady?.();
|
|
498
|
+
} catch (error) {
|
|
499
|
+
options?.onError?.(error);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (newPhase === "error" && oldPhase !== "error") {
|
|
503
|
+
options?.onError?.(context.value.state.error);
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
{ immediate: true }
|
|
507
|
+
);
|
|
508
|
+
return {
|
|
509
|
+
/** 当前阶段 */
|
|
510
|
+
phase: computed2(() => context.value.state.phase),
|
|
511
|
+
/** 是否已 mounted */
|
|
512
|
+
hasMounted: readonly2(hasMounted),
|
|
513
|
+
/** 是否已 ready */
|
|
514
|
+
hasReady: readonly2(hasReady)
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
function useWhen(condition, callback, options) {
|
|
518
|
+
const executed = ref2(false);
|
|
519
|
+
const { once = true, immediate = true } = options || {};
|
|
520
|
+
const stop = watch(
|
|
521
|
+
condition,
|
|
522
|
+
async (value) => {
|
|
523
|
+
if (value && (!once || !executed.value)) {
|
|
524
|
+
executed.value = true;
|
|
525
|
+
await callback();
|
|
526
|
+
if (once) {
|
|
527
|
+
stop();
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
{ immediate }
|
|
532
|
+
);
|
|
533
|
+
onUnmounted(() => {
|
|
534
|
+
stop();
|
|
535
|
+
});
|
|
536
|
+
return {
|
|
537
|
+
/** 是否已执行 */
|
|
538
|
+
executed: readonly2(executed),
|
|
539
|
+
/** 手动停止监听 */
|
|
540
|
+
stop
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function useDebouncedAction(actionType, delay = 300) {
|
|
544
|
+
const { execute: rawExecute, loading, result, error } = useAction(actionType);
|
|
545
|
+
let timeoutId = null;
|
|
546
|
+
const execute = (params) => {
|
|
547
|
+
if (timeoutId) {
|
|
548
|
+
clearTimeout(timeoutId);
|
|
549
|
+
}
|
|
550
|
+
timeoutId = setTimeout(() => {
|
|
551
|
+
rawExecute(params).catch(() => {
|
|
552
|
+
});
|
|
553
|
+
}, delay);
|
|
554
|
+
};
|
|
555
|
+
const cancel = () => {
|
|
556
|
+
if (timeoutId) {
|
|
557
|
+
clearTimeout(timeoutId);
|
|
558
|
+
timeoutId = null;
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
onUnmounted(() => {
|
|
562
|
+
cancel();
|
|
563
|
+
});
|
|
564
|
+
return {
|
|
565
|
+
execute,
|
|
566
|
+
loading,
|
|
567
|
+
result,
|
|
568
|
+
error,
|
|
569
|
+
cancel
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function useGlobalConfig() {
|
|
573
|
+
const config = inject("djvlc-config", {});
|
|
574
|
+
return config;
|
|
575
|
+
}
|
|
258
576
|
|
|
259
577
|
// src/components/DJVRenderer.ts
|
|
260
578
|
var DJVRenderer = defineComponent({
|
|
@@ -287,12 +605,27 @@ var DJVRenderer = defineComponent({
|
|
|
287
605
|
enableSRI: {
|
|
288
606
|
type: Boolean,
|
|
289
607
|
default: true
|
|
608
|
+
},
|
|
609
|
+
retryCount: {
|
|
610
|
+
type: Number,
|
|
611
|
+
default: 3
|
|
612
|
+
},
|
|
613
|
+
retryDelay: {
|
|
614
|
+
type: Number,
|
|
615
|
+
default: 1e3
|
|
616
|
+
},
|
|
617
|
+
timeout: {
|
|
618
|
+
type: Number,
|
|
619
|
+
default: 3e4
|
|
290
620
|
}
|
|
291
621
|
},
|
|
292
|
-
emits: ["load", "error", "ready"],
|
|
622
|
+
emits: ["load", "error", "ready", "phase-change"],
|
|
293
623
|
setup(props, { emit, slots }) {
|
|
294
624
|
const containerRef = ref3(null);
|
|
295
|
-
const
|
|
625
|
+
const mounted = ref3(true);
|
|
626
|
+
const retryAttempt = ref3(0);
|
|
627
|
+
const phase = ref3("idle");
|
|
628
|
+
const contextValue = shallowRef3({
|
|
296
629
|
runtime: null,
|
|
297
630
|
state: {
|
|
298
631
|
phase: "idle",
|
|
@@ -307,8 +640,16 @@ var DJVRenderer = defineComponent({
|
|
|
307
640
|
});
|
|
308
641
|
provideRuntime(contextValue);
|
|
309
642
|
let vueRuntime = null;
|
|
310
|
-
const
|
|
311
|
-
|
|
643
|
+
const withTimeout = (promise, ms) => {
|
|
644
|
+
return Promise.race([
|
|
645
|
+
promise,
|
|
646
|
+
new Promise(
|
|
647
|
+
(_, reject) => setTimeout(() => reject(new Error("\u52A0\u8F7D\u8D85\u65F6")), ms)
|
|
648
|
+
)
|
|
649
|
+
]);
|
|
650
|
+
};
|
|
651
|
+
const initWithRetry = async () => {
|
|
652
|
+
if (!containerRef.value || !mounted.value) return;
|
|
312
653
|
const options = {
|
|
313
654
|
pageUid: props.pageUid,
|
|
314
655
|
apiBaseUrl: props.apiBaseUrl,
|
|
@@ -327,56 +668,126 @@ var DJVRenderer = defineComponent({
|
|
|
327
668
|
};
|
|
328
669
|
vueRuntime = createVueRuntime(options);
|
|
329
670
|
try {
|
|
330
|
-
await
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
671
|
+
await withTimeout(
|
|
672
|
+
(async () => {
|
|
673
|
+
await vueRuntime.init();
|
|
674
|
+
if (!mounted.value) return;
|
|
675
|
+
phase.value = "loading";
|
|
676
|
+
emit("phase-change", "loading");
|
|
677
|
+
contextValue.value = {
|
|
678
|
+
runtime: vueRuntime.runtime.value,
|
|
679
|
+
state: vueRuntime.runtime.value?.getState() || contextValue.value.state,
|
|
680
|
+
hostApi: vueRuntime.hostApi.value
|
|
681
|
+
};
|
|
682
|
+
const pageData = await vueRuntime.load();
|
|
683
|
+
if (!mounted.value) return;
|
|
684
|
+
emit("load", pageData);
|
|
685
|
+
contextValue.value = {
|
|
686
|
+
...contextValue.value,
|
|
687
|
+
state: vueRuntime.runtime.value?.getState() || contextValue.value.state,
|
|
688
|
+
hostApi: vueRuntime.hostApi.value
|
|
689
|
+
};
|
|
690
|
+
await vueRuntime.render();
|
|
691
|
+
if (!mounted.value) return;
|
|
692
|
+
phase.value = "ready";
|
|
693
|
+
emit("phase-change", "ready");
|
|
694
|
+
emit("ready");
|
|
695
|
+
retryAttempt.value = 0;
|
|
696
|
+
vueRuntime.runtime.value?.onStateChange((state) => {
|
|
697
|
+
if (!mounted.value) return;
|
|
698
|
+
contextValue.value = {
|
|
699
|
+
...contextValue.value,
|
|
700
|
+
state
|
|
701
|
+
};
|
|
702
|
+
phase.value = state.phase;
|
|
703
|
+
emit("phase-change", state.phase);
|
|
704
|
+
});
|
|
705
|
+
})(),
|
|
706
|
+
props.timeout
|
|
707
|
+
);
|
|
351
708
|
} catch (error) {
|
|
352
|
-
|
|
709
|
+
if (!mounted.value) return;
|
|
710
|
+
if (retryAttempt.value < props.retryCount) {
|
|
711
|
+
retryAttempt.value++;
|
|
712
|
+
if (props.debug) {
|
|
713
|
+
console.log(`[DJVRenderer] \u91CD\u8BD5 ${retryAttempt.value}/${props.retryCount}...`);
|
|
714
|
+
}
|
|
715
|
+
setTimeout(() => {
|
|
716
|
+
if (mounted.value) {
|
|
717
|
+
initWithRetry();
|
|
718
|
+
}
|
|
719
|
+
}, props.retryDelay);
|
|
720
|
+
} else {
|
|
721
|
+
phase.value = "error";
|
|
722
|
+
emit("phase-change", "error");
|
|
723
|
+
emit("error", error);
|
|
724
|
+
}
|
|
353
725
|
}
|
|
354
726
|
};
|
|
355
|
-
|
|
356
|
-
|
|
727
|
+
const handleRetry = () => {
|
|
728
|
+
retryAttempt.value = 0;
|
|
729
|
+
initWithRetry();
|
|
730
|
+
};
|
|
731
|
+
onMounted2(() => {
|
|
732
|
+
mounted.value = true;
|
|
733
|
+
initWithRetry();
|
|
357
734
|
});
|
|
358
735
|
onUnmounted2(() => {
|
|
736
|
+
mounted.value = false;
|
|
359
737
|
vueRuntime?.destroy();
|
|
360
738
|
});
|
|
361
|
-
|
|
739
|
+
watch2(
|
|
362
740
|
() => props.pageUid,
|
|
363
741
|
() => {
|
|
364
742
|
vueRuntime?.destroy();
|
|
365
|
-
|
|
743
|
+
retryAttempt.value = 0;
|
|
744
|
+
initWithRetry();
|
|
366
745
|
}
|
|
367
746
|
);
|
|
747
|
+
const renderDefaultLoading = () => {
|
|
748
|
+
return h("div", { class: "djvlc-loading" }, [
|
|
749
|
+
h("div", { class: "djvlc-loading-spinner" }),
|
|
750
|
+
h("span", {}, "\u52A0\u8F7D\u4E2D..."),
|
|
751
|
+
retryAttempt.value > 0 && h("span", { class: "djvlc-loading-retry" }, `\u91CD\u8BD5 ${retryAttempt.value}/${props.retryCount}`)
|
|
752
|
+
]);
|
|
753
|
+
};
|
|
754
|
+
const renderDefaultError = (error) => {
|
|
755
|
+
return h("div", { class: "djvlc-error" }, [
|
|
756
|
+
h("div", { class: "djvlc-error-icon" }, "\u26A0\uFE0F"),
|
|
757
|
+
h("span", { class: "djvlc-error-message" }, `\u52A0\u8F7D\u5931\u8D25\uFF1A${error.message}`),
|
|
758
|
+
h(
|
|
759
|
+
"button",
|
|
760
|
+
{
|
|
761
|
+
class: "djvlc-error-retry-btn",
|
|
762
|
+
onClick: handleRetry,
|
|
763
|
+
type: "button"
|
|
764
|
+
},
|
|
765
|
+
"\u91CD\u8BD5"
|
|
766
|
+
)
|
|
767
|
+
]);
|
|
768
|
+
};
|
|
769
|
+
const renderDefaultEmpty = () => {
|
|
770
|
+
return h("div", { class: "djvlc-empty" }, [h("span", {}, "\u6682\u65E0\u5185\u5BB9")]);
|
|
771
|
+
};
|
|
368
772
|
return () => {
|
|
773
|
+
const isLoading = vueRuntime?.loading.value ?? false;
|
|
774
|
+
const currentError = vueRuntime?.error.value;
|
|
775
|
+
const currentPage = vueRuntime?.page.value;
|
|
369
776
|
return h(
|
|
370
777
|
"div",
|
|
371
778
|
{
|
|
372
779
|
ref: containerRef,
|
|
373
|
-
class: "djvlc-renderer"
|
|
780
|
+
class: "djvlc-renderer",
|
|
781
|
+
"data-phase": phase.value,
|
|
782
|
+
"data-page-uid": props.pageUid
|
|
374
783
|
},
|
|
375
784
|
[
|
|
376
785
|
// 加载中插槽
|
|
377
|
-
|
|
786
|
+
isLoading && (slots.loading?.() || renderDefaultLoading()),
|
|
378
787
|
// 错误插槽
|
|
379
|
-
|
|
788
|
+
currentError && (slots.error?.({ error: currentError, retry: handleRetry }) || renderDefaultError(currentError)),
|
|
789
|
+
// 空状态
|
|
790
|
+
!isLoading && !currentError && !currentPage && phase.value === "ready" && (slots.empty?.() || renderDefaultEmpty()),
|
|
380
791
|
// 默认插槽(额外内容)
|
|
381
792
|
slots.default?.()
|
|
382
793
|
]
|
|
@@ -386,7 +797,22 @@ var DJVRenderer = defineComponent({
|
|
|
386
797
|
});
|
|
387
798
|
|
|
388
799
|
// src/components/DJVProvider.ts
|
|
389
|
-
import {
|
|
800
|
+
import {
|
|
801
|
+
defineComponent as defineComponent2,
|
|
802
|
+
shallowRef as shallowRef4,
|
|
803
|
+
watch as watch3,
|
|
804
|
+
onUnmounted as onUnmounted3,
|
|
805
|
+
h as h2
|
|
806
|
+
} from "vue";
|
|
807
|
+
var defaultState = {
|
|
808
|
+
phase: "idle",
|
|
809
|
+
page: null,
|
|
810
|
+
variables: {},
|
|
811
|
+
queries: {},
|
|
812
|
+
components: /* @__PURE__ */ new Map(),
|
|
813
|
+
error: null,
|
|
814
|
+
destroyed: false
|
|
815
|
+
};
|
|
390
816
|
var DJVProvider = defineComponent2({
|
|
391
817
|
name: "DJVProvider",
|
|
392
818
|
props: {
|
|
@@ -397,49 +823,219 @@ var DJVProvider = defineComponent2({
|
|
|
397
823
|
hostApi: {
|
|
398
824
|
type: Object,
|
|
399
825
|
default: null
|
|
826
|
+
},
|
|
827
|
+
class: {
|
|
828
|
+
type: String,
|
|
829
|
+
default: ""
|
|
830
|
+
},
|
|
831
|
+
debug: {
|
|
832
|
+
type: Boolean,
|
|
833
|
+
default: false
|
|
400
834
|
}
|
|
401
835
|
},
|
|
402
|
-
|
|
403
|
-
|
|
836
|
+
emits: ["state-change", "phase-change", "error"],
|
|
837
|
+
setup(props, { slots, emit }) {
|
|
838
|
+
let unsubscribe = null;
|
|
839
|
+
const contextValue = shallowRef4({
|
|
404
840
|
runtime: props.runtime,
|
|
405
|
-
state: props.runtime?.getState() ||
|
|
406
|
-
phase: "idle",
|
|
407
|
-
page: null,
|
|
408
|
-
variables: {},
|
|
409
|
-
queries: {},
|
|
410
|
-
components: /* @__PURE__ */ new Map(),
|
|
411
|
-
error: null,
|
|
412
|
-
destroyed: false
|
|
413
|
-
},
|
|
841
|
+
state: props.runtime?.getState() || defaultState,
|
|
414
842
|
hostApi: props.hostApi
|
|
415
843
|
});
|
|
416
844
|
provideRuntime(contextValue);
|
|
417
|
-
|
|
418
|
-
|
|
845
|
+
const subscribeToRuntime = (runtime) => {
|
|
846
|
+
if (unsubscribe) {
|
|
847
|
+
unsubscribe();
|
|
848
|
+
unsubscribe = null;
|
|
849
|
+
}
|
|
850
|
+
if (!runtime) return;
|
|
851
|
+
unsubscribe = runtime.onStateChange((state) => {
|
|
852
|
+
const prevPhase = contextValue.value.state.phase;
|
|
419
853
|
contextValue.value = {
|
|
420
854
|
...contextValue.value,
|
|
421
855
|
state
|
|
422
856
|
};
|
|
857
|
+
emit("state-change", state);
|
|
858
|
+
if (state.phase !== prevPhase) {
|
|
859
|
+
emit("phase-change", state.phase);
|
|
860
|
+
if (props.debug) {
|
|
861
|
+
console.log(`[DJVProvider] Phase changed: ${prevPhase} -> ${state.phase}`);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if (state.error) {
|
|
865
|
+
emit("error", state.error);
|
|
866
|
+
}
|
|
423
867
|
});
|
|
424
|
-
}
|
|
425
|
-
|
|
868
|
+
};
|
|
869
|
+
subscribeToRuntime(props.runtime);
|
|
870
|
+
watch3(
|
|
871
|
+
() => props.runtime,
|
|
872
|
+
(newRuntime, oldRuntime) => {
|
|
873
|
+
if (newRuntime !== oldRuntime) {
|
|
874
|
+
contextValue.value = {
|
|
875
|
+
runtime: newRuntime,
|
|
876
|
+
state: newRuntime?.getState() || defaultState,
|
|
877
|
+
hostApi: props.hostApi
|
|
878
|
+
};
|
|
879
|
+
subscribeToRuntime(newRuntime);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
);
|
|
883
|
+
watch3(
|
|
884
|
+
() => props.hostApi,
|
|
885
|
+
(newHostApi) => {
|
|
886
|
+
contextValue.value = {
|
|
887
|
+
...contextValue.value,
|
|
888
|
+
hostApi: newHostApi
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
);
|
|
892
|
+
onUnmounted3(() => {
|
|
893
|
+
if (unsubscribe) {
|
|
894
|
+
unsubscribe();
|
|
895
|
+
unsubscribe = null;
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
return () => h2(
|
|
899
|
+
"div",
|
|
900
|
+
{
|
|
901
|
+
class: ["djvlc-provider", props.class].filter(Boolean).join(" "),
|
|
902
|
+
"data-phase": contextValue.value.state.phase
|
|
903
|
+
},
|
|
904
|
+
slots.default?.()
|
|
905
|
+
);
|
|
426
906
|
}
|
|
427
907
|
});
|
|
428
908
|
|
|
429
909
|
// src/plugin.ts
|
|
910
|
+
var DJVLC_CONFIG_KEY = "djvlc-config";
|
|
911
|
+
function createTrackDirective() {
|
|
912
|
+
const observedElements = /* @__PURE__ */ new WeakSet();
|
|
913
|
+
return {
|
|
914
|
+
mounted(el, binding) {
|
|
915
|
+
const { event, data = {}, trigger = "click" } = binding.value;
|
|
916
|
+
if (trigger === "click") {
|
|
917
|
+
el.addEventListener("click", () => {
|
|
918
|
+
dispatchTrackEvent(event, { ...data, element: el.tagName });
|
|
919
|
+
});
|
|
920
|
+
} else if (trigger === "view") {
|
|
921
|
+
if (!observedElements.has(el)) {
|
|
922
|
+
observedElements.add(el);
|
|
923
|
+
const observer = new IntersectionObserver(
|
|
924
|
+
(entries) => {
|
|
925
|
+
entries.forEach((entry) => {
|
|
926
|
+
if (entry.isIntersecting) {
|
|
927
|
+
dispatchTrackEvent(event, { ...data, element: el.tagName });
|
|
928
|
+
observer.unobserve(el);
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
},
|
|
932
|
+
{ threshold: 0.5 }
|
|
933
|
+
);
|
|
934
|
+
observer.observe(el);
|
|
935
|
+
}
|
|
936
|
+
} else if (trigger === "mounted") {
|
|
937
|
+
dispatchTrackEvent(event, { ...data, element: el.tagName });
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function dispatchTrackEvent(event, data) {
|
|
943
|
+
window.dispatchEvent(
|
|
944
|
+
new CustomEvent("djvlc:track", {
|
|
945
|
+
detail: { event, data, timestamp: Date.now() }
|
|
946
|
+
})
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
function createVisibleDirective() {
|
|
950
|
+
return {
|
|
951
|
+
mounted(el, binding) {
|
|
952
|
+
updateVisibility(el, binding.value);
|
|
953
|
+
},
|
|
954
|
+
updated(el, binding) {
|
|
955
|
+
updateVisibility(el, binding.value);
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
function updateVisibility(el, visible) {
|
|
960
|
+
el.style.display = visible ? "" : "none";
|
|
961
|
+
}
|
|
962
|
+
function createLoadingDirective() {
|
|
963
|
+
const loadingOverlays = /* @__PURE__ */ new WeakMap();
|
|
964
|
+
return {
|
|
965
|
+
mounted(el, binding) {
|
|
966
|
+
el.style.position = "relative";
|
|
967
|
+
updateLoading(el, binding.value, loadingOverlays);
|
|
968
|
+
},
|
|
969
|
+
updated(el, binding) {
|
|
970
|
+
updateLoading(el, binding.value, loadingOverlays);
|
|
971
|
+
},
|
|
972
|
+
unmounted(el) {
|
|
973
|
+
const overlay = loadingOverlays.get(el);
|
|
974
|
+
if (overlay) {
|
|
975
|
+
overlay.remove();
|
|
976
|
+
loadingOverlays.delete(el);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
function updateLoading(el, loading, overlays) {
|
|
982
|
+
let overlay = overlays.get(el);
|
|
983
|
+
if (loading) {
|
|
984
|
+
if (!overlay) {
|
|
985
|
+
overlay = document.createElement("div");
|
|
986
|
+
overlay.className = "djvlc-loading-overlay";
|
|
987
|
+
overlay.innerHTML = `
|
|
988
|
+
<div class="djvlc-loading-spinner"></div>
|
|
989
|
+
`;
|
|
990
|
+
overlay.style.cssText = `
|
|
991
|
+
position: absolute;
|
|
992
|
+
inset: 0;
|
|
993
|
+
display: flex;
|
|
994
|
+
align-items: center;
|
|
995
|
+
justify-content: center;
|
|
996
|
+
background: rgba(255, 255, 255, 0.8);
|
|
997
|
+
z-index: 100;
|
|
998
|
+
`;
|
|
999
|
+
el.appendChild(overlay);
|
|
1000
|
+
overlays.set(el, overlay);
|
|
1001
|
+
}
|
|
1002
|
+
overlay.style.display = "flex";
|
|
1003
|
+
} else if (overlay) {
|
|
1004
|
+
overlay.style.display = "none";
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
430
1007
|
var DJVPlugin = {
|
|
431
1008
|
install(app, options = {}) {
|
|
1009
|
+
const prefix = options.componentPrefix || "";
|
|
432
1010
|
if (options.registerComponents !== false) {
|
|
433
|
-
app.component(
|
|
434
|
-
app.component(
|
|
1011
|
+
app.component(`${prefix}DJVRenderer`, DJVRenderer);
|
|
1012
|
+
app.component(`${prefix}DJVProvider`, DJVProvider);
|
|
435
1013
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
1014
|
+
if (options.registerDirectives !== false) {
|
|
1015
|
+
app.directive("djv-track", createTrackDirective());
|
|
1016
|
+
app.directive("djv-visible", createVisibleDirective());
|
|
1017
|
+
app.directive("djv-loading", createLoadingDirective());
|
|
1018
|
+
}
|
|
1019
|
+
const globalConfig = {
|
|
1020
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
1021
|
+
cdnBaseUrl: options.cdnBaseUrl,
|
|
1022
|
+
channel: options.channel,
|
|
1023
|
+
debug: options.debug,
|
|
1024
|
+
enableSRI: options.enableSRI,
|
|
1025
|
+
enableMetrics: options.enableMetrics,
|
|
1026
|
+
retryCount: options.retryCount,
|
|
1027
|
+
retryDelay: options.retryDelay,
|
|
1028
|
+
timeout: options.timeout
|
|
1029
|
+
};
|
|
1030
|
+
app.provide(DJVLC_CONFIG_KEY, globalConfig);
|
|
1031
|
+
app.config.globalProperties.$djvlc = {
|
|
1032
|
+
config: globalConfig,
|
|
1033
|
+
track: dispatchTrackEvent
|
|
1034
|
+
};
|
|
440
1035
|
}
|
|
441
1036
|
};
|
|
442
1037
|
export {
|
|
1038
|
+
DJVLC_CONFIG_KEY,
|
|
443
1039
|
DJVPlugin,
|
|
444
1040
|
DJVProvider,
|
|
445
1041
|
DJVRenderer,
|
|
@@ -448,11 +1044,17 @@ export {
|
|
|
448
1044
|
injectRuntime,
|
|
449
1045
|
provideRuntime,
|
|
450
1046
|
useAction,
|
|
1047
|
+
useComponentState,
|
|
451
1048
|
useDJVRuntime,
|
|
452
1049
|
useData,
|
|
1050
|
+
useDebouncedAction,
|
|
1051
|
+
useGlobalConfig,
|
|
453
1052
|
useHostApi,
|
|
1053
|
+
useLifecycle,
|
|
1054
|
+
usePageInfo,
|
|
454
1055
|
useQuery,
|
|
455
1056
|
useRuntimeEvent,
|
|
456
1057
|
useRuntimeState,
|
|
457
|
-
useRuntimeStateWritable
|
|
1058
|
+
useRuntimeStateWritable,
|
|
1059
|
+
useWhen
|
|
458
1060
|
};
|