@almadar/ui 5.158.0 → 5.159.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/{EntityBindingContext-Bn3ePJQC.d.cts → EntityBindingContext-0Evn_LcT.d.cts} +1 -1
- package/dist/{EntityBindingContext-Bn3ePJQC.d.ts → EntityBindingContext-0Evn_LcT.d.ts} +1 -1
- package/dist/avl/index.cjs +144 -34
- package/dist/avl/index.js +145 -35
- package/dist/components/index.cjs +192 -7
- package/dist/components/index.d.cts +8 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +193 -8
- package/dist/context/index.cjs +134 -39
- package/dist/context/index.js +92 -1
- package/dist/hooks/index.cjs +328 -233
- package/dist/hooks/index.js +93 -2
- package/dist/lib/index.cjs +92 -0
- package/dist/lib/index.d.cts +58 -1
- package/dist/lib/index.d.ts +58 -1
- package/dist/lib/index.js +62 -1
- package/dist/locales/index.cjs +3 -0
- package/dist/locales/index.js +3 -0
- package/dist/perf-DaVdsbU0.d.cts +21 -0
- package/dist/perf-DaVdsbU0.d.ts +21 -0
- package/dist/providers/index.cjs +256 -96
- package/dist/providers/index.d.cts +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +257 -97
- package/dist/runtime/index.cjs +152 -39
- package/dist/runtime/index.d.cts +5 -22
- package/dist/runtime/index.d.ts +5 -22
- package/dist/runtime/index.js +154 -40
- package/locales/ar.json +1 -0
- package/locales/en.json +1 -0
- package/locales/sl.json +1 -0
- package/package.json +5 -5
package/dist/hooks/index.cjs
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var logger = require('@almadar/logger');
|
|
5
5
|
var providers = require('@almadar/ui/providers');
|
|
6
6
|
var core = require('@almadar/core');
|
|
7
7
|
var reactQuery = require('@tanstack/react-query');
|
|
8
8
|
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
12
|
+
|
|
9
13
|
var log = logger.createLogger("almadar:ui:orbital-history");
|
|
10
14
|
function useOrbitalHistory(options) {
|
|
11
15
|
const { appId, authToken, userId, onHistoryChange, onRevertSuccess } = options;
|
|
12
|
-
const getHeaders =
|
|
16
|
+
const getHeaders = React.useCallback(() => {
|
|
13
17
|
const headers = {
|
|
14
18
|
"Content-Type": "application/json"
|
|
15
19
|
};
|
|
@@ -21,11 +25,11 @@ function useOrbitalHistory(options) {
|
|
|
21
25
|
}
|
|
22
26
|
return headers;
|
|
23
27
|
}, [authToken, userId]);
|
|
24
|
-
const [timeline, setTimeline] =
|
|
25
|
-
const [currentVersion, setCurrentVersion] =
|
|
26
|
-
const [isLoading, setIsLoading] =
|
|
27
|
-
const [error, setError] =
|
|
28
|
-
const refresh =
|
|
28
|
+
const [timeline, setTimeline] = React.useState([]);
|
|
29
|
+
const [currentVersion, setCurrentVersion] = React.useState(1);
|
|
30
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
31
|
+
const [error, setError] = React.useState(null);
|
|
32
|
+
const refresh = React.useCallback(async () => {
|
|
29
33
|
if (!appId) return;
|
|
30
34
|
setIsLoading(true);
|
|
31
35
|
setError(null);
|
|
@@ -74,7 +78,7 @@ function useOrbitalHistory(options) {
|
|
|
74
78
|
setIsLoading(false);
|
|
75
79
|
}
|
|
76
80
|
}, [appId, getHeaders]);
|
|
77
|
-
const revertToSnapshot =
|
|
81
|
+
const revertToSnapshot = React.useCallback(async (snapshotId) => {
|
|
78
82
|
if (!appId) {
|
|
79
83
|
return { success: false, error: "No app ID provided" };
|
|
80
84
|
}
|
|
@@ -108,12 +112,12 @@ function useOrbitalHistory(options) {
|
|
|
108
112
|
};
|
|
109
113
|
}
|
|
110
114
|
}, [appId, getHeaders, refresh, onRevertSuccess]);
|
|
111
|
-
|
|
115
|
+
React.useEffect(() => {
|
|
112
116
|
if (appId && authToken && userId) {
|
|
113
117
|
refresh();
|
|
114
118
|
}
|
|
115
119
|
}, [appId, authToken, userId]);
|
|
116
|
-
|
|
120
|
+
React.useEffect(() => {
|
|
117
121
|
onHistoryChange?.(timeline);
|
|
118
122
|
}, [timeline]);
|
|
119
123
|
return {
|
|
@@ -127,15 +131,15 @@ function useOrbitalHistory(options) {
|
|
|
127
131
|
}
|
|
128
132
|
var log2 = logger.createLogger("almadar:ui:filesystem");
|
|
129
133
|
function useFileSystem() {
|
|
130
|
-
const [status, setStatus] =
|
|
131
|
-
const [error, setError] =
|
|
132
|
-
const [isLoading, setIsLoading] =
|
|
133
|
-
const [files, setFiles] =
|
|
134
|
-
const [selectedFile, setSelectedFile] =
|
|
135
|
-
const [selectedPath, setSelectedPath] =
|
|
136
|
-
const [previewUrl, setPreviewUrl] =
|
|
137
|
-
const [fileContents, setFileContents] =
|
|
138
|
-
const boot =
|
|
134
|
+
const [status, setStatus] = React.useState("idle");
|
|
135
|
+
const [error, setError] = React.useState(null);
|
|
136
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
137
|
+
const [files, setFiles] = React.useState([]);
|
|
138
|
+
const [selectedFile, setSelectedFile] = React.useState(null);
|
|
139
|
+
const [selectedPath, setSelectedPath] = React.useState(null);
|
|
140
|
+
const [previewUrl, setPreviewUrl] = React.useState(null);
|
|
141
|
+
const [fileContents, setFileContents] = React.useState(/* @__PURE__ */ new Map());
|
|
142
|
+
const boot = React.useCallback(async () => {
|
|
139
143
|
setStatus("booting");
|
|
140
144
|
setError(null);
|
|
141
145
|
setIsLoading(true);
|
|
@@ -150,7 +154,7 @@ function useFileSystem() {
|
|
|
150
154
|
setIsLoading(false);
|
|
151
155
|
}
|
|
152
156
|
}, []);
|
|
153
|
-
const mountFiles =
|
|
157
|
+
const mountFiles = React.useCallback(async (filesToMount) => {
|
|
154
158
|
setIsLoading(true);
|
|
155
159
|
try {
|
|
156
160
|
let filesArray;
|
|
@@ -206,17 +210,17 @@ function useFileSystem() {
|
|
|
206
210
|
setIsLoading(false);
|
|
207
211
|
}
|
|
208
212
|
}, []);
|
|
209
|
-
const readFile =
|
|
213
|
+
const readFile = React.useCallback(async (path) => {
|
|
210
214
|
return fileContents.get(path) || "";
|
|
211
215
|
}, [fileContents]);
|
|
212
|
-
const writeFile =
|
|
216
|
+
const writeFile = React.useCallback(async (path, content) => {
|
|
213
217
|
setFileContents((prev) => {
|
|
214
218
|
const next = new Map(prev);
|
|
215
219
|
next.set(path, content);
|
|
216
220
|
return next;
|
|
217
221
|
});
|
|
218
222
|
}, []);
|
|
219
|
-
const selectFile =
|
|
223
|
+
const selectFile = React.useCallback(async (path) => {
|
|
220
224
|
const content = fileContents.get(path) || "";
|
|
221
225
|
const ext = path.split(".").pop()?.toLowerCase() || "";
|
|
222
226
|
const languageMap = {
|
|
@@ -238,7 +242,7 @@ function useFileSystem() {
|
|
|
238
242
|
isDirty: false
|
|
239
243
|
});
|
|
240
244
|
}, [fileContents]);
|
|
241
|
-
const updateContent =
|
|
245
|
+
const updateContent = React.useCallback((pathOrContent, contentArg) => {
|
|
242
246
|
const path = contentArg !== void 0 ? pathOrContent : selectedPath;
|
|
243
247
|
const content = contentArg !== void 0 ? contentArg : pathOrContent;
|
|
244
248
|
if (!path) {
|
|
@@ -254,17 +258,17 @@ function useFileSystem() {
|
|
|
254
258
|
setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
|
|
255
259
|
}
|
|
256
260
|
}, [selectedPath]);
|
|
257
|
-
const updateSelectedContent =
|
|
261
|
+
const updateSelectedContent = React.useCallback((content) => {
|
|
258
262
|
setSelectedFile((prev) => prev ? { ...prev, content, isDirty: true } : null);
|
|
259
263
|
}, []);
|
|
260
|
-
const refreshTree =
|
|
264
|
+
const refreshTree = React.useCallback(async () => {
|
|
261
265
|
log2.debug("Refreshing tree");
|
|
262
266
|
}, []);
|
|
263
|
-
const runCommand =
|
|
267
|
+
const runCommand = React.useCallback(async (command) => {
|
|
264
268
|
log2.debug("Running command", { command });
|
|
265
269
|
return { exitCode: 0, output: "" };
|
|
266
270
|
}, []);
|
|
267
|
-
const startDevServer =
|
|
271
|
+
const startDevServer = React.useCallback(async () => {
|
|
268
272
|
log2.debug("Starting dev server");
|
|
269
273
|
setPreviewUrl("http://localhost:5173");
|
|
270
274
|
}, []);
|
|
@@ -302,14 +306,14 @@ var defaultManifest = {
|
|
|
302
306
|
};
|
|
303
307
|
function useExtensions(options) {
|
|
304
308
|
const { appId, loadOnMount = true } = options;
|
|
305
|
-
const [extensions, setExtensions] =
|
|
306
|
-
const [manifest] =
|
|
307
|
-
const [isLoading, setIsLoading] =
|
|
308
|
-
const [error, setError] =
|
|
309
|
-
const loadExtension =
|
|
309
|
+
const [extensions, setExtensions] = React.useState([]);
|
|
310
|
+
const [manifest] = React.useState(defaultManifest);
|
|
311
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
312
|
+
const [error, setError] = React.useState(null);
|
|
313
|
+
const loadExtension = React.useCallback(async (extensionId) => {
|
|
310
314
|
log3.debug("Loading extension", { extensionId });
|
|
311
315
|
}, []);
|
|
312
|
-
const loadExtensions =
|
|
316
|
+
const loadExtensions = React.useCallback(async () => {
|
|
313
317
|
setIsLoading(true);
|
|
314
318
|
setError(null);
|
|
315
319
|
try {
|
|
@@ -328,7 +332,7 @@ function useExtensions(options) {
|
|
|
328
332
|
setIsLoading(false);
|
|
329
333
|
}
|
|
330
334
|
}, []);
|
|
331
|
-
const getExtensionForFile =
|
|
335
|
+
const getExtensionForFile = React.useCallback((filename) => {
|
|
332
336
|
const ext = filename.split(".").pop()?.toLowerCase();
|
|
333
337
|
if (!ext) return null;
|
|
334
338
|
const languageMap = {
|
|
@@ -346,7 +350,7 @@ function useExtensions(options) {
|
|
|
346
350
|
if (!language) return null;
|
|
347
351
|
return extensions.find((e) => e.language === language) || null;
|
|
348
352
|
}, [extensions]);
|
|
349
|
-
|
|
353
|
+
React.useEffect(() => {
|
|
350
354
|
if (!appId || !loadOnMount) return;
|
|
351
355
|
const loadExtensions2 = async () => {
|
|
352
356
|
setIsLoading(true);
|
|
@@ -382,11 +386,11 @@ function useExtensions(options) {
|
|
|
382
386
|
var log4 = logger.createLogger("almadar:ui:file-editor");
|
|
383
387
|
function useFileEditor(options) {
|
|
384
388
|
const { extensions, fileSystem, onSchemaUpdate } = options;
|
|
385
|
-
const [openFiles, setOpenFiles] =
|
|
386
|
-
const [activeFilePath, setActiveFilePath] =
|
|
387
|
-
const [isSaving, setIsSaving] =
|
|
389
|
+
const [openFiles, setOpenFiles] = React.useState([]);
|
|
390
|
+
const [activeFilePath, setActiveFilePath] = React.useState(null);
|
|
391
|
+
const [isSaving, setIsSaving] = React.useState(false);
|
|
388
392
|
const activeFile = openFiles.find((f) => f.path === activeFilePath) || null;
|
|
389
|
-
const openFile =
|
|
393
|
+
const openFile = React.useCallback(async (path) => {
|
|
390
394
|
const existing = openFiles.find((f) => f.path === path);
|
|
391
395
|
if (existing) {
|
|
392
396
|
setActiveFilePath(path);
|
|
@@ -407,24 +411,24 @@ function useFileEditor(options) {
|
|
|
407
411
|
log4.error("Failed to open file", { error: err instanceof Error ? err : String(err) });
|
|
408
412
|
}
|
|
409
413
|
}, [openFiles, fileSystem, extensions]);
|
|
410
|
-
const closeFile =
|
|
414
|
+
const closeFile = React.useCallback((path) => {
|
|
411
415
|
setOpenFiles((prev) => prev.filter((f) => f.path !== path));
|
|
412
416
|
if (activeFilePath === path) {
|
|
413
417
|
const remaining = openFiles.filter((f) => f.path !== path);
|
|
414
418
|
setActiveFilePath(remaining.length > 0 ? remaining[0].path : null);
|
|
415
419
|
}
|
|
416
420
|
}, [activeFilePath, openFiles]);
|
|
417
|
-
const setActiveFile =
|
|
421
|
+
const setActiveFile = React.useCallback((path) => {
|
|
418
422
|
setActiveFilePath(path);
|
|
419
423
|
}, []);
|
|
420
|
-
const updateFileContent =
|
|
424
|
+
const updateFileContent = React.useCallback((path, content) => {
|
|
421
425
|
setOpenFiles(
|
|
422
426
|
(prev) => prev.map(
|
|
423
427
|
(f) => f.path === path ? { ...f, content, isDirty: true } : f
|
|
424
428
|
)
|
|
425
429
|
);
|
|
426
430
|
}, []);
|
|
427
|
-
const handleFileEdit =
|
|
431
|
+
const handleFileEdit = React.useCallback(async (path, content) => {
|
|
428
432
|
try {
|
|
429
433
|
await fileSystem.writeFile(path, content);
|
|
430
434
|
let action = "saved";
|
|
@@ -446,7 +450,7 @@ function useFileEditor(options) {
|
|
|
446
450
|
};
|
|
447
451
|
}
|
|
448
452
|
}, [fileSystem, onSchemaUpdate]);
|
|
449
|
-
const saveFile =
|
|
453
|
+
const saveFile = React.useCallback(async (path) => {
|
|
450
454
|
const file = openFiles.find((f) => f.path === path);
|
|
451
455
|
if (!file) return;
|
|
452
456
|
setIsSaving(true);
|
|
@@ -470,7 +474,7 @@ function useFileEditor(options) {
|
|
|
470
474
|
setIsSaving(false);
|
|
471
475
|
}
|
|
472
476
|
}, [openFiles, fileSystem, onSchemaUpdate]);
|
|
473
|
-
const saveAllFiles =
|
|
477
|
+
const saveAllFiles = React.useCallback(async () => {
|
|
474
478
|
setIsSaving(true);
|
|
475
479
|
try {
|
|
476
480
|
const dirtyFiles = openFiles.filter((f) => f.isDirty);
|
|
@@ -496,11 +500,11 @@ function useFileEditor(options) {
|
|
|
496
500
|
}
|
|
497
501
|
var log5 = logger.createLogger("almadar:ui:compile");
|
|
498
502
|
function useCompile() {
|
|
499
|
-
const [isCompiling, setIsCompiling] =
|
|
500
|
-
const [stage, setStage] =
|
|
501
|
-
const [lastResult, setLastResult] =
|
|
502
|
-
const [error, setError] =
|
|
503
|
-
const compileSchema =
|
|
503
|
+
const [isCompiling, setIsCompiling] = React.useState(false);
|
|
504
|
+
const [stage, setStage] = React.useState("idle");
|
|
505
|
+
const [lastResult, setLastResult] = React.useState(null);
|
|
506
|
+
const [error, setError] = React.useState(null);
|
|
507
|
+
const compileSchema = React.useCallback(async (schema) => {
|
|
504
508
|
setIsCompiling(true);
|
|
505
509
|
setStage("compiling");
|
|
506
510
|
setError(null);
|
|
@@ -533,18 +537,18 @@ function useCompile() {
|
|
|
533
537
|
}
|
|
534
538
|
var log6 = logger.createLogger("almadar:ui:preview");
|
|
535
539
|
function usePreview(options) {
|
|
536
|
-
const [previewUrl, setPreviewUrl] =
|
|
537
|
-
const [isLoading, setIsLoading] =
|
|
538
|
-
const [error, setError] =
|
|
539
|
-
const [loadError, setLoadError] =
|
|
540
|
-
const [app, setApp] =
|
|
541
|
-
const [isFullscreen, setIsFullscreen] =
|
|
542
|
-
const [isExecutingEvent, setIsExecutingEvent] =
|
|
543
|
-
const [errorToast, setErrorToast] =
|
|
544
|
-
const [currentStateName, setCurrentStateName] =
|
|
545
|
-
const [notificationsList, setNotificationsList] =
|
|
546
|
-
const [isPanelOpen, setIsPanelOpen] =
|
|
547
|
-
const notifications =
|
|
540
|
+
const [previewUrl, setPreviewUrl] = React.useState(null);
|
|
541
|
+
const [isLoading, setIsLoading] = React.useState(!!options?.appId);
|
|
542
|
+
const [error, setError] = React.useState(null);
|
|
543
|
+
const [loadError, setLoadError] = React.useState(null);
|
|
544
|
+
const [app, setApp] = React.useState(null);
|
|
545
|
+
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
|
546
|
+
const [isExecutingEvent, setIsExecutingEvent] = React.useState(false);
|
|
547
|
+
const [errorToast, setErrorToast] = React.useState(null);
|
|
548
|
+
const [currentStateName, setCurrentStateName] = React.useState(null);
|
|
549
|
+
const [notificationsList, setNotificationsList] = React.useState([]);
|
|
550
|
+
const [isPanelOpen, setIsPanelOpen] = React.useState(false);
|
|
551
|
+
const notifications = React.useMemo(() => ({
|
|
548
552
|
notifications: notificationsList,
|
|
549
553
|
isPanelOpen,
|
|
550
554
|
closePanel: () => setIsPanelOpen(false),
|
|
@@ -558,7 +562,7 @@ function usePreview(options) {
|
|
|
558
562
|
},
|
|
559
563
|
clearAll: () => setNotificationsList([])
|
|
560
564
|
}), [notificationsList, isPanelOpen]);
|
|
561
|
-
|
|
565
|
+
React.useEffect(() => {
|
|
562
566
|
const appId = options?.appId;
|
|
563
567
|
if (!appId) {
|
|
564
568
|
setApp(null);
|
|
@@ -569,10 +573,10 @@ function usePreview(options) {
|
|
|
569
573
|
setPreviewUrl(`/api/orbitals/${appId}`);
|
|
570
574
|
setIsLoading(false);
|
|
571
575
|
}, [options?.appId]);
|
|
572
|
-
const startPreview =
|
|
576
|
+
const startPreview = React.useCallback(async () => {
|
|
573
577
|
log6.debug("startPreview called");
|
|
574
578
|
}, []);
|
|
575
|
-
const stopPreview =
|
|
579
|
+
const stopPreview = React.useCallback(async () => {
|
|
576
580
|
setIsLoading(true);
|
|
577
581
|
try {
|
|
578
582
|
log6.debug("Stopping preview server");
|
|
@@ -582,16 +586,16 @@ function usePreview(options) {
|
|
|
582
586
|
setIsLoading(false);
|
|
583
587
|
}
|
|
584
588
|
}, []);
|
|
585
|
-
const refresh =
|
|
589
|
+
const refresh = React.useCallback(async () => {
|
|
586
590
|
if (!previewUrl) return;
|
|
587
591
|
log6.debug("Refreshing preview");
|
|
588
592
|
setPreviewUrl(`${previewUrl.split("?")[0]}?t=${Date.now()}`);
|
|
589
593
|
}, [previewUrl]);
|
|
590
|
-
const handleRefresh =
|
|
594
|
+
const handleRefresh = React.useCallback(async () => {
|
|
591
595
|
log6.debug("Handle refresh");
|
|
592
596
|
await refresh();
|
|
593
597
|
}, [refresh]);
|
|
594
|
-
const handleReset =
|
|
598
|
+
const handleReset = React.useCallback(async () => {
|
|
595
599
|
log6.debug("Resetting preview");
|
|
596
600
|
setError(null);
|
|
597
601
|
setLoadError(null);
|
|
@@ -599,10 +603,10 @@ function usePreview(options) {
|
|
|
599
603
|
setIsExecutingEvent(false);
|
|
600
604
|
setCurrentStateName(null);
|
|
601
605
|
}, []);
|
|
602
|
-
const toggleFullscreen =
|
|
606
|
+
const toggleFullscreen = React.useCallback(() => {
|
|
603
607
|
setIsFullscreen((prev) => !prev);
|
|
604
608
|
}, []);
|
|
605
|
-
const dismissErrorToast =
|
|
609
|
+
const dismissErrorToast = React.useCallback(() => {
|
|
606
610
|
setErrorToast(null);
|
|
607
611
|
}, []);
|
|
608
612
|
return {
|
|
@@ -628,16 +632,16 @@ function usePreview(options) {
|
|
|
628
632
|
}
|
|
629
633
|
var log7 = logger.createLogger("almadar:ui:agent-chat");
|
|
630
634
|
function useAgentChat(options) {
|
|
631
|
-
const [messages, setMessages] =
|
|
632
|
-
const [status, setStatus] =
|
|
633
|
-
const [activities, setActivities] =
|
|
634
|
-
const [todos, setTodos] =
|
|
635
|
-
const [schemaDiffs, setSchemaDiffs] =
|
|
636
|
-
const [isLoading, setIsLoading] =
|
|
637
|
-
const [error, setError] =
|
|
638
|
-
const [threadId] =
|
|
639
|
-
const [interrupt, setInterrupt] =
|
|
640
|
-
const sendMessage =
|
|
635
|
+
const [messages, setMessages] = React.useState([]);
|
|
636
|
+
const [status, setStatus] = React.useState("idle");
|
|
637
|
+
const [activities, setActivities] = React.useState([]);
|
|
638
|
+
const [todos, setTodos] = React.useState([]);
|
|
639
|
+
const [schemaDiffs, setSchemaDiffs] = React.useState([]);
|
|
640
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
641
|
+
const [error, setError] = React.useState(null);
|
|
642
|
+
const [threadId] = React.useState(null);
|
|
643
|
+
const [interrupt, setInterrupt] = React.useState(null);
|
|
644
|
+
const sendMessage = React.useCallback(async (content) => {
|
|
641
645
|
setIsLoading(true);
|
|
642
646
|
setStatus("running");
|
|
643
647
|
setError(null);
|
|
@@ -666,7 +670,7 @@ function useAgentChat(options) {
|
|
|
666
670
|
setIsLoading(false);
|
|
667
671
|
}
|
|
668
672
|
}, [options]);
|
|
669
|
-
const startGeneration =
|
|
673
|
+
const startGeneration = React.useCallback(async (skill, prompt, genOptions) => {
|
|
670
674
|
setStatus("running");
|
|
671
675
|
setIsLoading(true);
|
|
672
676
|
setError(null);
|
|
@@ -683,22 +687,22 @@ function useAgentChat(options) {
|
|
|
683
687
|
setIsLoading(false);
|
|
684
688
|
}
|
|
685
689
|
}, [options]);
|
|
686
|
-
const continueConversation =
|
|
690
|
+
const continueConversation = React.useCallback(async (message) => {
|
|
687
691
|
log7.debug("Continue conversation", { message: Array.isArray(message) ? message : [message] });
|
|
688
692
|
}, []);
|
|
689
|
-
const resumeWithDecision =
|
|
693
|
+
const resumeWithDecision = React.useCallback(async (decisions) => {
|
|
690
694
|
log7.debug("Resume with decision", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
|
|
691
695
|
setInterrupt(null);
|
|
692
696
|
}, []);
|
|
693
|
-
const cancel =
|
|
697
|
+
const cancel = React.useCallback(() => {
|
|
694
698
|
setStatus("idle");
|
|
695
699
|
setIsLoading(false);
|
|
696
700
|
setInterrupt(null);
|
|
697
701
|
}, []);
|
|
698
|
-
const clearMessages =
|
|
702
|
+
const clearMessages = React.useCallback(() => {
|
|
699
703
|
setMessages([]);
|
|
700
704
|
}, []);
|
|
701
|
-
const clearHistory =
|
|
705
|
+
const clearHistory = React.useCallback(() => {
|
|
702
706
|
setMessages([]);
|
|
703
707
|
setActivities([]);
|
|
704
708
|
setTodos([]);
|
|
@@ -726,13 +730,13 @@ function useAgentChat(options) {
|
|
|
726
730
|
}
|
|
727
731
|
var log8 = logger.createLogger("almadar:ui:validation");
|
|
728
732
|
function useValidation() {
|
|
729
|
-
const [result, setResult] =
|
|
730
|
-
const [isValidating, setIsValidating] =
|
|
731
|
-
const [error, setError] =
|
|
732
|
-
const [stage, setStage] =
|
|
733
|
-
const [isFixing, setIsFixing] =
|
|
734
|
-
const [progressMessage, setProgressMessage] =
|
|
735
|
-
const validate =
|
|
733
|
+
const [result, setResult] = React.useState(null);
|
|
734
|
+
const [isValidating, setIsValidating] = React.useState(false);
|
|
735
|
+
const [error, setError] = React.useState(null);
|
|
736
|
+
const [stage, setStage] = React.useState("idle");
|
|
737
|
+
const [isFixing, setIsFixing] = React.useState(false);
|
|
738
|
+
const [progressMessage, setProgressMessage] = React.useState(null);
|
|
739
|
+
const validate = React.useCallback(async (appId) => {
|
|
736
740
|
setIsValidating(true);
|
|
737
741
|
setError(null);
|
|
738
742
|
setStage("validating");
|
|
@@ -764,11 +768,11 @@ function useValidation() {
|
|
|
764
768
|
setIsValidating(false);
|
|
765
769
|
}
|
|
766
770
|
}, []);
|
|
767
|
-
const clearResult =
|
|
771
|
+
const clearResult = React.useCallback(() => {
|
|
768
772
|
setResult(null);
|
|
769
773
|
setError(null);
|
|
770
774
|
}, []);
|
|
771
|
-
const reset =
|
|
775
|
+
const reset = React.useCallback(() => {
|
|
772
776
|
setResult(null);
|
|
773
777
|
setError(null);
|
|
774
778
|
setStage("idle");
|
|
@@ -793,15 +797,15 @@ function useValidation() {
|
|
|
793
797
|
}
|
|
794
798
|
var log9 = logger.createLogger("almadar:ui:deep-agent");
|
|
795
799
|
function useDeepAgentGeneration() {
|
|
796
|
-
const [requests, setRequests] =
|
|
797
|
-
const [currentRequest, setCurrentRequest] =
|
|
798
|
-
const [isGenerating, setIsGenerating] =
|
|
799
|
-
const [isLoading, setIsLoading] =
|
|
800
|
-
const [isComplete, setIsComplete] =
|
|
801
|
-
const [progress, setProgress] =
|
|
802
|
-
const [error, setError] =
|
|
803
|
-
const [interrupt, setInterrupt] =
|
|
804
|
-
const generate =
|
|
800
|
+
const [requests, setRequests] = React.useState([]);
|
|
801
|
+
const [currentRequest, setCurrentRequest] = React.useState(null);
|
|
802
|
+
const [isGenerating, setIsGenerating] = React.useState(false);
|
|
803
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
804
|
+
const [isComplete, setIsComplete] = React.useState(false);
|
|
805
|
+
const [progress, setProgress] = React.useState({ stage: "idle", percent: 0, message: "" });
|
|
806
|
+
const [error, setError] = React.useState(null);
|
|
807
|
+
const [interrupt, setInterrupt] = React.useState(null);
|
|
808
|
+
const generate = React.useCallback(async (prompt) => {
|
|
805
809
|
setIsGenerating(true);
|
|
806
810
|
setIsLoading(true);
|
|
807
811
|
setIsComplete(false);
|
|
@@ -834,11 +838,11 @@ function useDeepAgentGeneration() {
|
|
|
834
838
|
setIsLoading(false);
|
|
835
839
|
}
|
|
836
840
|
}, []);
|
|
837
|
-
const startGeneration =
|
|
841
|
+
const startGeneration = React.useCallback(async (skill, prompt, _options) => {
|
|
838
842
|
log9.debug("Starting generation with skill", { skill });
|
|
839
843
|
await generate(prompt);
|
|
840
844
|
}, [generate]);
|
|
841
|
-
const cancelGeneration =
|
|
845
|
+
const cancelGeneration = React.useCallback(() => {
|
|
842
846
|
if (currentRequest) {
|
|
843
847
|
currentRequest.status = "failed";
|
|
844
848
|
currentRequest.error = "Cancelled by user";
|
|
@@ -849,14 +853,14 @@ function useDeepAgentGeneration() {
|
|
|
849
853
|
setIsComplete(false);
|
|
850
854
|
setProgress({ stage: "idle", percent: 0, message: "" });
|
|
851
855
|
}, [currentRequest]);
|
|
852
|
-
const clearRequests =
|
|
856
|
+
const clearRequests = React.useCallback(() => {
|
|
853
857
|
setRequests([]);
|
|
854
858
|
setCurrentRequest(null);
|
|
855
859
|
setError(null);
|
|
856
860
|
setProgress({ stage: "idle", percent: 0, message: "" });
|
|
857
861
|
setIsComplete(false);
|
|
858
862
|
}, []);
|
|
859
|
-
const submitInterruptDecisions =
|
|
863
|
+
const submitInterruptDecisions = React.useCallback((decisions) => {
|
|
860
864
|
log9.debug("Submitting interrupt decisions", () => ({ decisions: JSON.stringify(decisions), count: decisions.length }));
|
|
861
865
|
setInterrupt(null);
|
|
862
866
|
}, []);
|
|
@@ -950,10 +954,10 @@ var fallbackEventBus = {
|
|
|
950
954
|
}
|
|
951
955
|
};
|
|
952
956
|
function useEventBus() {
|
|
953
|
-
const context =
|
|
957
|
+
const context = React.useContext(providers.EventBusContext);
|
|
954
958
|
const baseBus = context ?? getGlobalEventBus() ?? fallbackEventBus;
|
|
955
959
|
const chain = providers.useTraitScopeChain();
|
|
956
|
-
return
|
|
960
|
+
return React.useMemo(() => {
|
|
957
961
|
if (chain.length === 0) {
|
|
958
962
|
return {
|
|
959
963
|
...baseBus,
|
|
@@ -998,9 +1002,9 @@ function useEventBus() {
|
|
|
998
1002
|
}
|
|
999
1003
|
function useEventListener(event, handler) {
|
|
1000
1004
|
const eventBus = useEventBus();
|
|
1001
|
-
const handlerRef =
|
|
1005
|
+
const handlerRef = React.useRef(handler);
|
|
1002
1006
|
handlerRef.current = handler;
|
|
1003
|
-
|
|
1007
|
+
React.useEffect(() => {
|
|
1004
1008
|
const wrappedHandler = (evt) => {
|
|
1005
1009
|
handlerRef.current(evt);
|
|
1006
1010
|
};
|
|
@@ -1012,13 +1016,95 @@ function useEventListener(event, handler) {
|
|
|
1012
1016
|
}
|
|
1013
1017
|
function useEmitEvent() {
|
|
1014
1018
|
const eventBus = useEventBus();
|
|
1015
|
-
return
|
|
1019
|
+
return React.useCallback(
|
|
1016
1020
|
(type, payload, source) => {
|
|
1017
1021
|
eventBus.emit(type, payload, source);
|
|
1018
1022
|
},
|
|
1019
1023
|
[eventBus]
|
|
1020
1024
|
);
|
|
1021
1025
|
}
|
|
1026
|
+
function expressionEqual(a, b) {
|
|
1027
|
+
if (Object.is(a, b)) return true;
|
|
1028
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1029
|
+
if (a.length !== b.length) return false;
|
|
1030
|
+
for (let i = 0; i < a.length; i++) {
|
|
1031
|
+
if (!expressionEqual(a[i], b[i])) return false;
|
|
1032
|
+
}
|
|
1033
|
+
return true;
|
|
1034
|
+
}
|
|
1035
|
+
if (a !== null && b !== null && typeof a === "object" && typeof b === "object" && !Array.isArray(a) && !Array.isArray(b) && !(a instanceof Date) && !(b instanceof Date)) {
|
|
1036
|
+
const aKeys = Object.keys(a);
|
|
1037
|
+
const bKeys = Object.keys(b);
|
|
1038
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
1039
|
+
for (const key of aKeys) {
|
|
1040
|
+
if (!Object.prototype.hasOwnProperty.call(b, key)) return false;
|
|
1041
|
+
if (!expressionEqual(
|
|
1042
|
+
a[key],
|
|
1043
|
+
b[key]
|
|
1044
|
+
)) return false;
|
|
1045
|
+
}
|
|
1046
|
+
return true;
|
|
1047
|
+
}
|
|
1048
|
+
return false;
|
|
1049
|
+
}
|
|
1050
|
+
function isPlainSlotObject(value) {
|
|
1051
|
+
if (value === null || value === void 0 || typeof value !== "object") return false;
|
|
1052
|
+
if (Array.isArray(value)) return false;
|
|
1053
|
+
if (React__default.default.isValidElement(value)) return false;
|
|
1054
|
+
if (value instanceof Date) return false;
|
|
1055
|
+
if (core.isRenderBindingMarker(value)) return false;
|
|
1056
|
+
return true;
|
|
1057
|
+
}
|
|
1058
|
+
function shareValue(prev, next) {
|
|
1059
|
+
if (Object.is(prev, next)) return { value: prev, equal: true };
|
|
1060
|
+
const prevMarker = core.isRenderBindingMarker(prev) ? prev : void 0;
|
|
1061
|
+
const nextMarker = core.isRenderBindingMarker(next) ? next : void 0;
|
|
1062
|
+
if (prevMarker !== void 0 || nextMarker !== void 0) {
|
|
1063
|
+
if (prevMarker !== void 0 && nextMarker !== void 0 && expressionEqual(prevMarker.expression, nextMarker.expression)) {
|
|
1064
|
+
return { value: prev, equal: true };
|
|
1065
|
+
}
|
|
1066
|
+
return { value: next, equal: false };
|
|
1067
|
+
}
|
|
1068
|
+
if (prev instanceof Date || next instanceof Date) {
|
|
1069
|
+
return prev instanceof Date && next instanceof Date && prev.getTime() === next.getTime() ? { value: prev, equal: true } : { value: next, equal: false };
|
|
1070
|
+
}
|
|
1071
|
+
if (typeof prev === "function" || typeof next === "function") return { value: next, equal: false };
|
|
1072
|
+
if (React__default.default.isValidElement(prev) || React__default.default.isValidElement(next)) return { value: next, equal: false };
|
|
1073
|
+
if (Array.isArray(prev) && Array.isArray(next)) {
|
|
1074
|
+
let equal = prev.length === next.length;
|
|
1075
|
+
const out = new Array(next.length);
|
|
1076
|
+
for (let i = 0; i < next.length; i++) {
|
|
1077
|
+
const child = shareValue(prev[i], next[i]);
|
|
1078
|
+
out[i] = child.value;
|
|
1079
|
+
if (!child.equal) equal = false;
|
|
1080
|
+
}
|
|
1081
|
+
return equal ? { value: prev, equal: true } : { value: out, equal: false };
|
|
1082
|
+
}
|
|
1083
|
+
if (isPlainSlotObject(prev) && isPlainSlotObject(next)) {
|
|
1084
|
+
const prevKeys = Object.keys(prev);
|
|
1085
|
+
const nextKeys = Object.keys(next);
|
|
1086
|
+
let equal = prevKeys.length === nextKeys.length;
|
|
1087
|
+
const out = {};
|
|
1088
|
+
for (const key of nextKeys) {
|
|
1089
|
+
if (!Object.prototype.hasOwnProperty.call(prev, key)) {
|
|
1090
|
+
equal = false;
|
|
1091
|
+
out[key] = next[key];
|
|
1092
|
+
continue;
|
|
1093
|
+
}
|
|
1094
|
+
const child = shareValue(prev[key], next[key]);
|
|
1095
|
+
out[key] = child.value;
|
|
1096
|
+
if (!child.equal) equal = false;
|
|
1097
|
+
}
|
|
1098
|
+
return equal ? { value: prev, equal: true } : { value: out, equal: false };
|
|
1099
|
+
}
|
|
1100
|
+
return { value: next, equal: false };
|
|
1101
|
+
}
|
|
1102
|
+
function reconcileSlotProps(prev, next) {
|
|
1103
|
+
const result = shareValue(prev, next);
|
|
1104
|
+
return { value: result.value, equal: result.equal };
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
// hooks/useUISlots.ts
|
|
1022
1108
|
var log11 = logger.createLogger("almadar:ui:ui-slots");
|
|
1023
1109
|
var DEFAULT_SOURCE_KEY = "__default__";
|
|
1024
1110
|
var MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
|
|
@@ -1073,25 +1159,25 @@ function aggregateSlot(sources) {
|
|
|
1073
1159
|
};
|
|
1074
1160
|
}
|
|
1075
1161
|
function useUISlotManager() {
|
|
1076
|
-
const [sources, setSources] =
|
|
1077
|
-
const subscribersRef =
|
|
1078
|
-
const timersRef =
|
|
1079
|
-
const traitIndexRef =
|
|
1080
|
-
const traitSubscribersRef =
|
|
1081
|
-
const slots =
|
|
1162
|
+
const [sources, setSources] = React.useState(DEFAULT_SOURCES);
|
|
1163
|
+
const subscribersRef = React.useRef(/* @__PURE__ */ new Set());
|
|
1164
|
+
const timersRef = React.useRef(/* @__PURE__ */ new Map());
|
|
1165
|
+
const traitIndexRef = React.useRef(/* @__PURE__ */ new Map());
|
|
1166
|
+
const traitSubscribersRef = React.useRef(/* @__PURE__ */ new Map());
|
|
1167
|
+
const slots = React.useMemo(() => {
|
|
1082
1168
|
const out = { ...DEFAULT_SLOTS };
|
|
1083
1169
|
for (const slot of ALL_SLOTS) {
|
|
1084
1170
|
out[slot] = aggregateSlot(sources[slot]);
|
|
1085
1171
|
}
|
|
1086
1172
|
return out;
|
|
1087
1173
|
}, [sources]);
|
|
1088
|
-
|
|
1174
|
+
React.useEffect(() => {
|
|
1089
1175
|
return () => {
|
|
1090
1176
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
1091
1177
|
timersRef.current.clear();
|
|
1092
1178
|
};
|
|
1093
1179
|
}, []);
|
|
1094
|
-
const notifySubscribers =
|
|
1180
|
+
const notifySubscribers = React.useCallback((slot, content) => {
|
|
1095
1181
|
subscribersRef.current.forEach((callback) => {
|
|
1096
1182
|
try {
|
|
1097
1183
|
callback(slot, content);
|
|
@@ -1100,7 +1186,7 @@ function useUISlotManager() {
|
|
|
1100
1186
|
}
|
|
1101
1187
|
});
|
|
1102
1188
|
}, []);
|
|
1103
|
-
const notifyTraitSubscribers =
|
|
1189
|
+
const notifyTraitSubscribers = React.useCallback(
|
|
1104
1190
|
(traitName, content) => {
|
|
1105
1191
|
const subs = traitSubscribersRef.current.get(traitName);
|
|
1106
1192
|
if (!subs) return;
|
|
@@ -1114,16 +1200,16 @@ function useUISlotManager() {
|
|
|
1114
1200
|
},
|
|
1115
1201
|
[]
|
|
1116
1202
|
);
|
|
1117
|
-
const indexTraitRender =
|
|
1203
|
+
const indexTraitRender = React.useCallback(
|
|
1118
1204
|
(traitName, content) => {
|
|
1119
1205
|
traitIndexRef.current.set(traitName, content);
|
|
1120
1206
|
},
|
|
1121
1207
|
[]
|
|
1122
1208
|
);
|
|
1123
|
-
const unindexTrait =
|
|
1209
|
+
const unindexTrait = React.useCallback((traitName) => {
|
|
1124
1210
|
traitIndexRef.current.delete(traitName);
|
|
1125
1211
|
}, []);
|
|
1126
|
-
const render =
|
|
1212
|
+
const render = React.useCallback(
|
|
1127
1213
|
(config) => {
|
|
1128
1214
|
const sourceKey = config.sourceTrait ?? DEFAULT_SOURCE_KEY;
|
|
1129
1215
|
const id = `slot-content-${config.target}-${sourceKey}`;
|
|
@@ -1173,6 +1259,14 @@ function useUISlotManager() {
|
|
|
1173
1259
|
});
|
|
1174
1260
|
return prev;
|
|
1175
1261
|
}
|
|
1262
|
+
if (existing && existing.priority === content.priority && existing.pattern === content.pattern && existing.animation === content.animation && existing.transitionEvent === content.transitionEvent && existing.fromState === content.fromState && existing.entity === content.entity && existing.nodeId === content.nodeId && existing.autoDismissAt === void 0 && content.autoDismissAt === void 0 && existing.onDismiss === void 0 === (content.onDismiss === void 0)) {
|
|
1263
|
+
const reconciled = reconcileSlotProps(existing.props, content.props);
|
|
1264
|
+
if (reconciled.equal) {
|
|
1265
|
+
log11.debug("slot:flush-bail", { slot: config.target, sourceKey, pattern: content.pattern });
|
|
1266
|
+
return prev;
|
|
1267
|
+
}
|
|
1268
|
+
content.props = reconciled.value;
|
|
1269
|
+
}
|
|
1176
1270
|
const nextSources = {
|
|
1177
1271
|
...slotSources,
|
|
1178
1272
|
[sourceKey]: content
|
|
@@ -1204,7 +1298,7 @@ function useUISlotManager() {
|
|
|
1204
1298
|
},
|
|
1205
1299
|
[notifySubscribers, notifyTraitSubscribers, indexTraitRender]
|
|
1206
1300
|
);
|
|
1207
|
-
const clear =
|
|
1301
|
+
const clear = React.useCallback(
|
|
1208
1302
|
(slot) => {
|
|
1209
1303
|
setSources((prev) => {
|
|
1210
1304
|
const slotSources = prev[slot];
|
|
@@ -1229,7 +1323,7 @@ function useUISlotManager() {
|
|
|
1229
1323
|
},
|
|
1230
1324
|
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
1231
1325
|
);
|
|
1232
|
-
const clearBySource =
|
|
1326
|
+
const clearBySource = React.useCallback(
|
|
1233
1327
|
(slot, sourceTrait) => {
|
|
1234
1328
|
const sourceKey = sourceTrait;
|
|
1235
1329
|
setSources((prev) => {
|
|
@@ -1258,7 +1352,7 @@ function useUISlotManager() {
|
|
|
1258
1352
|
},
|
|
1259
1353
|
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
1260
1354
|
);
|
|
1261
|
-
const clearById =
|
|
1355
|
+
const clearById = React.useCallback(
|
|
1262
1356
|
(id) => {
|
|
1263
1357
|
setSources((prev) => {
|
|
1264
1358
|
for (const slot of ALL_SLOTS) {
|
|
@@ -1289,7 +1383,7 @@ function useUISlotManager() {
|
|
|
1289
1383
|
},
|
|
1290
1384
|
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
1291
1385
|
);
|
|
1292
|
-
const clearAll =
|
|
1386
|
+
const clearAll = React.useCallback(() => {
|
|
1293
1387
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
1294
1388
|
timersRef.current.clear();
|
|
1295
1389
|
setSources((prev) => {
|
|
@@ -1308,25 +1402,25 @@ function useUISlotManager() {
|
|
|
1308
1402
|
});
|
|
1309
1403
|
traitIndexRef.current.clear();
|
|
1310
1404
|
}, [notifySubscribers, notifyTraitSubscribers]);
|
|
1311
|
-
const subscribe =
|
|
1405
|
+
const subscribe = React.useCallback((callback) => {
|
|
1312
1406
|
subscribersRef.current.add(callback);
|
|
1313
1407
|
return () => {
|
|
1314
1408
|
subscribersRef.current.delete(callback);
|
|
1315
1409
|
};
|
|
1316
1410
|
}, []);
|
|
1317
|
-
const hasContent =
|
|
1411
|
+
const hasContent = React.useCallback(
|
|
1318
1412
|
(slot) => slots[slot] !== null,
|
|
1319
1413
|
[slots]
|
|
1320
1414
|
);
|
|
1321
|
-
const getContent =
|
|
1415
|
+
const getContent = React.useCallback(
|
|
1322
1416
|
(slot) => slots[slot] ?? null,
|
|
1323
1417
|
[slots]
|
|
1324
1418
|
);
|
|
1325
|
-
const getTraitContent =
|
|
1419
|
+
const getTraitContent = React.useCallback(
|
|
1326
1420
|
(traitName) => traitIndexRef.current.get(traitName) ?? null,
|
|
1327
1421
|
[]
|
|
1328
1422
|
);
|
|
1329
|
-
const subscribeTrait =
|
|
1423
|
+
const subscribeTrait = React.useCallback(
|
|
1330
1424
|
(traitName, callback) => {
|
|
1331
1425
|
let set = traitSubscribersRef.current.get(traitName);
|
|
1332
1426
|
if (!set) {
|
|
@@ -1345,7 +1439,7 @@ function useUISlotManager() {
|
|
|
1345
1439
|
},
|
|
1346
1440
|
[]
|
|
1347
1441
|
);
|
|
1348
|
-
const updateTraitContent =
|
|
1442
|
+
const updateTraitContent = React.useCallback(
|
|
1349
1443
|
(traitName, content) => {
|
|
1350
1444
|
const id = `slot-content-trait-${traitName}`;
|
|
1351
1445
|
const fullContent = { ...content, id, sourceTrait: traitName };
|
|
@@ -1375,12 +1469,12 @@ function useUIEvents(dispatch, traitName, validEvents, eventBusInstance) {
|
|
|
1375
1469
|
const defaultEventBus = useEventBus();
|
|
1376
1470
|
const eventBus = eventBusInstance ?? defaultEventBus;
|
|
1377
1471
|
const validEventsKey = validEvents.slice().sort().join(",");
|
|
1378
|
-
const stableValidEvents =
|
|
1472
|
+
const stableValidEvents = React.useMemo(
|
|
1379
1473
|
() => validEvents,
|
|
1380
1474
|
[validEventsKey]
|
|
1381
1475
|
// intentional — validEventsKey is the stable dep
|
|
1382
1476
|
);
|
|
1383
|
-
|
|
1477
|
+
React.useEffect(() => {
|
|
1384
1478
|
const unsubscribes = [];
|
|
1385
1479
|
for (const smEvent of stableValidEvents) {
|
|
1386
1480
|
const handler = (event) => {
|
|
@@ -1404,12 +1498,12 @@ function useTraitListens(dispatch, listens, eventBusInstance) {
|
|
|
1404
1498
|
const defaultEventBus = useEventBus();
|
|
1405
1499
|
const eventBus = eventBusInstance ?? defaultEventBus;
|
|
1406
1500
|
const stableKey = listens.map((l) => `${l.sourceKey}->${l.trigger}`).sort().join("|");
|
|
1407
|
-
const stableListens =
|
|
1501
|
+
const stableListens = React.useMemo(
|
|
1408
1502
|
() => listens,
|
|
1409
1503
|
[stableKey]
|
|
1410
1504
|
// intentional
|
|
1411
1505
|
);
|
|
1412
|
-
|
|
1506
|
+
React.useEffect(() => {
|
|
1413
1507
|
const unsubscribes = [];
|
|
1414
1508
|
for (const spec of stableListens) {
|
|
1415
1509
|
const handler = (event) => {
|
|
@@ -1469,15 +1563,15 @@ function createSharedEntityStore() {
|
|
|
1469
1563
|
return { getSnapshot, subscribe, commit, seed };
|
|
1470
1564
|
}
|
|
1471
1565
|
function useSharedEntityStore() {
|
|
1472
|
-
const storeRef =
|
|
1566
|
+
const storeRef = React.useRef(null);
|
|
1473
1567
|
if (storeRef.current === null) {
|
|
1474
1568
|
storeRef.current = createSharedEntityStore();
|
|
1475
1569
|
}
|
|
1476
1570
|
return storeRef.current;
|
|
1477
1571
|
}
|
|
1478
|
-
var SharedEntityStoreContext =
|
|
1572
|
+
var SharedEntityStoreContext = React.createContext(null);
|
|
1479
1573
|
function useSharedEntityStoreContext() {
|
|
1480
|
-
const store =
|
|
1574
|
+
const store = React.useContext(SharedEntityStoreContext);
|
|
1481
1575
|
if (!store) {
|
|
1482
1576
|
throw new Error(
|
|
1483
1577
|
"useSharedEntityStoreContext: no SharedEntityStoreContext.Provider found in the component tree"
|
|
@@ -1486,7 +1580,7 @@ function useSharedEntityStoreContext() {
|
|
|
1486
1580
|
return store;
|
|
1487
1581
|
}
|
|
1488
1582
|
function useSharedEntitySnapshot(store, entityId) {
|
|
1489
|
-
return
|
|
1583
|
+
return React.useSyncExternalStore(
|
|
1490
1584
|
(onStoreChange) => store.subscribe(entityId, onStoreChange),
|
|
1491
1585
|
() => store.getSnapshot(entityId)
|
|
1492
1586
|
);
|
|
@@ -1514,35 +1608,35 @@ function getOrCreateStore(query) {
|
|
|
1514
1608
|
return queryStores.get(query);
|
|
1515
1609
|
}
|
|
1516
1610
|
function useQuerySingleton(query) {
|
|
1517
|
-
const [, forceUpdate] =
|
|
1611
|
+
const [, forceUpdate] = React.useState({});
|
|
1518
1612
|
if (!query) {
|
|
1519
1613
|
return null;
|
|
1520
1614
|
}
|
|
1521
|
-
const store =
|
|
1522
|
-
|
|
1615
|
+
const store = React.useMemo(() => getOrCreateStore(query), [query]);
|
|
1616
|
+
React.useMemo(() => {
|
|
1523
1617
|
const listener = () => forceUpdate({});
|
|
1524
1618
|
store.listeners.add(listener);
|
|
1525
1619
|
return () => {
|
|
1526
1620
|
store.listeners.delete(listener);
|
|
1527
1621
|
};
|
|
1528
1622
|
}, [store]);
|
|
1529
|
-
const notifyListeners =
|
|
1623
|
+
const notifyListeners = React.useCallback(() => {
|
|
1530
1624
|
store.listeners.forEach((listener) => listener());
|
|
1531
1625
|
}, [store]);
|
|
1532
|
-
const setSearch =
|
|
1626
|
+
const setSearch = React.useCallback((value) => {
|
|
1533
1627
|
store.search = value;
|
|
1534
1628
|
notifyListeners();
|
|
1535
1629
|
}, [store, notifyListeners]);
|
|
1536
|
-
const setFilter =
|
|
1630
|
+
const setFilter = React.useCallback((key, value) => {
|
|
1537
1631
|
store.filters = { ...store.filters, [key]: value };
|
|
1538
1632
|
notifyListeners();
|
|
1539
1633
|
}, [store, notifyListeners]);
|
|
1540
|
-
const clearFilters =
|
|
1634
|
+
const clearFilters = React.useCallback(() => {
|
|
1541
1635
|
store.filters = {};
|
|
1542
1636
|
store.search = "";
|
|
1543
1637
|
notifyListeners();
|
|
1544
1638
|
}, [store, notifyListeners]);
|
|
1545
|
-
const setSort =
|
|
1639
|
+
const setSort = React.useCallback((field, direction) => {
|
|
1546
1640
|
store.sortField = field;
|
|
1547
1641
|
store.sortDirection = direction;
|
|
1548
1642
|
notifyListeners();
|
|
@@ -1580,6 +1674,7 @@ var en_default = {
|
|
|
1580
1674
|
"common.confirm": "Are you sure?",
|
|
1581
1675
|
"common.create": "Create",
|
|
1582
1676
|
"common.edit": "Edit",
|
|
1677
|
+
"common.title": "Title",
|
|
1583
1678
|
"common.view": "View",
|
|
1584
1679
|
"common.add": "Add",
|
|
1585
1680
|
"common.remove": "Remove",
|
|
@@ -2147,7 +2242,7 @@ var en_default = {
|
|
|
2147
2242
|
// hooks/useTranslate.ts
|
|
2148
2243
|
var { $meta: _meta, ...coreMessages } = en_default;
|
|
2149
2244
|
var coreLocale = coreMessages;
|
|
2150
|
-
var I18nContext =
|
|
2245
|
+
var I18nContext = React.createContext({
|
|
2151
2246
|
locale: "en",
|
|
2152
2247
|
direction: "ltr",
|
|
2153
2248
|
t: (key, params) => {
|
|
@@ -2163,7 +2258,7 @@ var I18nContext = react.createContext({
|
|
|
2163
2258
|
I18nContext.displayName = "I18nContext";
|
|
2164
2259
|
var I18nProvider = I18nContext.Provider;
|
|
2165
2260
|
function useTranslate() {
|
|
2166
|
-
return
|
|
2261
|
+
return React.useContext(I18nContext);
|
|
2167
2262
|
}
|
|
2168
2263
|
function createTranslate(messages) {
|
|
2169
2264
|
return (key, params) => {
|
|
@@ -2188,14 +2283,14 @@ function useAuthContext() {
|
|
|
2188
2283
|
}
|
|
2189
2284
|
function useSwipeGesture(callbacks, options = {}) {
|
|
2190
2285
|
const { threshold = 50, velocityThreshold = 0.3, preventDefault = false } = options;
|
|
2191
|
-
const startX =
|
|
2192
|
-
const startY =
|
|
2193
|
-
const startTime =
|
|
2194
|
-
const currentX =
|
|
2195
|
-
const tracking =
|
|
2196
|
-
const offsetXRef =
|
|
2197
|
-
const isSwipingRef =
|
|
2198
|
-
const onPointerDown =
|
|
2286
|
+
const startX = React.useRef(0);
|
|
2287
|
+
const startY = React.useRef(0);
|
|
2288
|
+
const startTime = React.useRef(0);
|
|
2289
|
+
const currentX = React.useRef(0);
|
|
2290
|
+
const tracking = React.useRef(false);
|
|
2291
|
+
const offsetXRef = React.useRef(0);
|
|
2292
|
+
const isSwipingRef = React.useRef(false);
|
|
2293
|
+
const onPointerDown = React.useCallback((e) => {
|
|
2199
2294
|
startX.current = e.clientX;
|
|
2200
2295
|
startY.current = e.clientY;
|
|
2201
2296
|
currentX.current = e.clientX;
|
|
@@ -2205,7 +2300,7 @@ function useSwipeGesture(callbacks, options = {}) {
|
|
|
2205
2300
|
offsetXRef.current = 0;
|
|
2206
2301
|
e.target.setPointerCapture?.(e.pointerId);
|
|
2207
2302
|
}, []);
|
|
2208
|
-
const onPointerMove =
|
|
2303
|
+
const onPointerMove = React.useCallback((e) => {
|
|
2209
2304
|
if (!tracking.current) return;
|
|
2210
2305
|
if (preventDefault) e.preventDefault();
|
|
2211
2306
|
currentX.current = e.clientX;
|
|
@@ -2216,7 +2311,7 @@ function useSwipeGesture(callbacks, options = {}) {
|
|
|
2216
2311
|
offsetXRef.current = dx;
|
|
2217
2312
|
}
|
|
2218
2313
|
}, [preventDefault]);
|
|
2219
|
-
const onPointerUp =
|
|
2314
|
+
const onPointerUp = React.useCallback((e) => {
|
|
2220
2315
|
if (!tracking.current) return;
|
|
2221
2316
|
tracking.current = false;
|
|
2222
2317
|
const dx = e.clientX - startX.current;
|
|
@@ -2234,7 +2329,7 @@ function useSwipeGesture(callbacks, options = {}) {
|
|
|
2234
2329
|
else if (dy > threshold) callbacks.onSwipeDown?.();
|
|
2235
2330
|
}
|
|
2236
2331
|
}, [threshold, velocityThreshold, callbacks]);
|
|
2237
|
-
const onPointerCancel =
|
|
2332
|
+
const onPointerCancel = React.useCallback(() => {
|
|
2238
2333
|
tracking.current = false;
|
|
2239
2334
|
offsetXRef.current = 0;
|
|
2240
2335
|
isSwipingRef.current = false;
|
|
@@ -2250,18 +2345,18 @@ function useSwipeGesture(callbacks, options = {}) {
|
|
|
2250
2345
|
}
|
|
2251
2346
|
function useLongPress(onLongPress, options = {}) {
|
|
2252
2347
|
const { duration = 500, moveThreshold = 10 } = options;
|
|
2253
|
-
const timerRef =
|
|
2254
|
-
const startPos =
|
|
2255
|
-
const isPressedRef =
|
|
2256
|
-
const firedRef =
|
|
2257
|
-
const cancel =
|
|
2348
|
+
const timerRef = React.useRef(null);
|
|
2349
|
+
const startPos = React.useRef({ x: 0, y: 0 });
|
|
2350
|
+
const isPressedRef = React.useRef(false);
|
|
2351
|
+
const firedRef = React.useRef(false);
|
|
2352
|
+
const cancel = React.useCallback(() => {
|
|
2258
2353
|
if (timerRef.current) {
|
|
2259
2354
|
clearTimeout(timerRef.current);
|
|
2260
2355
|
timerRef.current = null;
|
|
2261
2356
|
}
|
|
2262
2357
|
isPressedRef.current = false;
|
|
2263
2358
|
}, []);
|
|
2264
|
-
const onPointerDown =
|
|
2359
|
+
const onPointerDown = React.useCallback((e) => {
|
|
2265
2360
|
firedRef.current = false;
|
|
2266
2361
|
startPos.current = { x: e.clientX, y: e.clientY };
|
|
2267
2362
|
isPressedRef.current = true;
|
|
@@ -2271,7 +2366,7 @@ function useLongPress(onLongPress, options = {}) {
|
|
|
2271
2366
|
onLongPress();
|
|
2272
2367
|
}, duration);
|
|
2273
2368
|
}, [duration, onLongPress]);
|
|
2274
|
-
const onPointerMove =
|
|
2369
|
+
const onPointerMove = React.useCallback((e) => {
|
|
2275
2370
|
if (!isPressedRef.current) return;
|
|
2276
2371
|
const dx = e.clientX - startPos.current.x;
|
|
2277
2372
|
const dy = e.clientY - startPos.current.y;
|
|
@@ -2279,10 +2374,10 @@ function useLongPress(onLongPress, options = {}) {
|
|
|
2279
2374
|
cancel();
|
|
2280
2375
|
}
|
|
2281
2376
|
}, [moveThreshold, cancel]);
|
|
2282
|
-
const onPointerUp =
|
|
2377
|
+
const onPointerUp = React.useCallback(() => {
|
|
2283
2378
|
cancel();
|
|
2284
2379
|
}, [cancel]);
|
|
2285
|
-
const onPointerCancel =
|
|
2380
|
+
const onPointerCancel = React.useCallback(() => {
|
|
2286
2381
|
cancel();
|
|
2287
2382
|
}, [cancel]);
|
|
2288
2383
|
return {
|
|
@@ -2294,22 +2389,22 @@ function useLongPress(onLongPress, options = {}) {
|
|
|
2294
2389
|
};
|
|
2295
2390
|
}
|
|
2296
2391
|
function useDragReorder(initialItems, onReorder) {
|
|
2297
|
-
const [items, setItems] =
|
|
2298
|
-
const [dragIndex, setDragIndex] =
|
|
2299
|
-
const [dragOverIndex, setDragOverIndex] =
|
|
2300
|
-
const itemsRef =
|
|
2392
|
+
const [items, setItems] = React.useState(initialItems);
|
|
2393
|
+
const [dragIndex, setDragIndex] = React.useState(-1);
|
|
2394
|
+
const [dragOverIndex, setDragOverIndex] = React.useState(-1);
|
|
2395
|
+
const itemsRef = React.useRef(initialItems);
|
|
2301
2396
|
if (initialItems !== itemsRef.current) {
|
|
2302
2397
|
itemsRef.current = initialItems;
|
|
2303
2398
|
setItems(initialItems);
|
|
2304
2399
|
}
|
|
2305
2400
|
const isDragging = dragIndex >= 0;
|
|
2306
|
-
const handleDragStart =
|
|
2401
|
+
const handleDragStart = React.useCallback((index) => (e) => {
|
|
2307
2402
|
e.preventDefault();
|
|
2308
2403
|
setDragIndex(index);
|
|
2309
2404
|
setDragOverIndex(index);
|
|
2310
2405
|
e.target.setPointerCapture?.(e.pointerId);
|
|
2311
2406
|
}, []);
|
|
2312
|
-
const handleDragMove =
|
|
2407
|
+
const handleDragMove = React.useCallback((index) => (e) => {
|
|
2313
2408
|
if (dragIndex < 0) return;
|
|
2314
2409
|
const target = document.elementFromPoint(e.clientX, e.clientY);
|
|
2315
2410
|
if (!target) return;
|
|
@@ -2324,7 +2419,7 @@ function useDragReorder(initialItems, onReorder) {
|
|
|
2324
2419
|
}
|
|
2325
2420
|
}
|
|
2326
2421
|
}, [dragIndex, dragOverIndex]);
|
|
2327
|
-
const handleDragEnd =
|
|
2422
|
+
const handleDragEnd = React.useCallback(() => {
|
|
2328
2423
|
if (dragIndex >= 0 && dragOverIndex >= 0 && dragIndex !== dragOverIndex) {
|
|
2329
2424
|
const newItems = [...items];
|
|
2330
2425
|
const [movedItem] = newItems.splice(dragIndex, 1);
|
|
@@ -2335,13 +2430,13 @@ function useDragReorder(initialItems, onReorder) {
|
|
|
2335
2430
|
setDragIndex(-1);
|
|
2336
2431
|
setDragOverIndex(-1);
|
|
2337
2432
|
}, [dragIndex, dragOverIndex, items, onReorder]);
|
|
2338
|
-
const getDragHandleProps =
|
|
2433
|
+
const getDragHandleProps = React.useCallback((index) => ({
|
|
2339
2434
|
onPointerDown: handleDragStart(index),
|
|
2340
2435
|
style: { cursor: "grab", touchAction: "none" },
|
|
2341
2436
|
"aria-grabbed": dragIndex === index,
|
|
2342
2437
|
role: "button"
|
|
2343
2438
|
}), [handleDragStart, dragIndex]);
|
|
2344
|
-
const getItemProps =
|
|
2439
|
+
const getItemProps = React.useCallback((index) => ({
|
|
2345
2440
|
onPointerMove: handleDragMove(index),
|
|
2346
2441
|
onPointerUp: handleDragEnd,
|
|
2347
2442
|
"aria-dropeffect": "move",
|
|
@@ -2362,7 +2457,7 @@ function useDragReorder(initialItems, onReorder) {
|
|
|
2362
2457
|
};
|
|
2363
2458
|
}
|
|
2364
2459
|
function useMediaQuery(query) {
|
|
2365
|
-
const subscribe =
|
|
2460
|
+
const subscribe = React.useCallback(
|
|
2366
2461
|
(onChange) => {
|
|
2367
2462
|
const mql = window.matchMedia(query);
|
|
2368
2463
|
mql.addEventListener("change", onChange);
|
|
@@ -2370,7 +2465,7 @@ function useMediaQuery(query) {
|
|
|
2370
2465
|
},
|
|
2371
2466
|
[query]
|
|
2372
2467
|
);
|
|
2373
|
-
return
|
|
2468
|
+
return React.useSyncExternalStore(
|
|
2374
2469
|
subscribe,
|
|
2375
2470
|
() => window.matchMedia(query).matches,
|
|
2376
2471
|
() => false
|
|
@@ -2378,19 +2473,19 @@ function useMediaQuery(query) {
|
|
|
2378
2473
|
}
|
|
2379
2474
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
2380
2475
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
2381
|
-
const observerRef =
|
|
2382
|
-
const callbackRef =
|
|
2476
|
+
const observerRef = React.useRef(null);
|
|
2477
|
+
const callbackRef = React.useRef(onLoadMore);
|
|
2383
2478
|
callbackRef.current = onLoadMore;
|
|
2384
|
-
const hasMoreRef =
|
|
2479
|
+
const hasMoreRef = React.useRef(hasMore);
|
|
2385
2480
|
hasMoreRef.current = hasMore;
|
|
2386
|
-
const isLoadingRef =
|
|
2481
|
+
const isLoadingRef = React.useRef(isLoading);
|
|
2387
2482
|
isLoadingRef.current = isLoading;
|
|
2388
|
-
|
|
2483
|
+
React.useEffect(() => {
|
|
2389
2484
|
return () => {
|
|
2390
2485
|
observerRef.current?.disconnect();
|
|
2391
2486
|
};
|
|
2392
2487
|
}, []);
|
|
2393
|
-
const sentinelRef =
|
|
2488
|
+
const sentinelRef = React.useCallback((node) => {
|
|
2394
2489
|
observerRef.current?.disconnect();
|
|
2395
2490
|
if (!node) return;
|
|
2396
2491
|
observerRef.current = new IntersectionObserver(
|
|
@@ -2408,12 +2503,12 @@ function useInfiniteScroll(onLoadMore, options = {}) {
|
|
|
2408
2503
|
}
|
|
2409
2504
|
function usePullToRefresh(onRefresh, options = {}) {
|
|
2410
2505
|
const { threshold = 60, maxPull = 120 } = options;
|
|
2411
|
-
const [pullDistance, setPullDistance] =
|
|
2412
|
-
const [isPulling, setIsPulling] =
|
|
2413
|
-
const [isRefreshing, setIsRefreshing] =
|
|
2414
|
-
const startY =
|
|
2415
|
-
const scrollTopRef =
|
|
2416
|
-
const onTouchStart =
|
|
2506
|
+
const [pullDistance, setPullDistance] = React.useState(0);
|
|
2507
|
+
const [isPulling, setIsPulling] = React.useState(false);
|
|
2508
|
+
const [isRefreshing, setIsRefreshing] = React.useState(false);
|
|
2509
|
+
const startY = React.useRef(0);
|
|
2510
|
+
const scrollTopRef = React.useRef(0);
|
|
2511
|
+
const onTouchStart = React.useCallback((e) => {
|
|
2417
2512
|
const container = e.currentTarget;
|
|
2418
2513
|
scrollTopRef.current = container.scrollTop;
|
|
2419
2514
|
if (scrollTopRef.current <= 0) {
|
|
@@ -2421,7 +2516,7 @@ function usePullToRefresh(onRefresh, options = {}) {
|
|
|
2421
2516
|
setIsPulling(true);
|
|
2422
2517
|
}
|
|
2423
2518
|
}, []);
|
|
2424
|
-
const onTouchMove =
|
|
2519
|
+
const onTouchMove = React.useCallback((e) => {
|
|
2425
2520
|
if (!isPulling || isRefreshing) return;
|
|
2426
2521
|
const container = e.currentTarget;
|
|
2427
2522
|
if (container.scrollTop > 0) {
|
|
@@ -2434,7 +2529,7 @@ function usePullToRefresh(onRefresh, options = {}) {
|
|
|
2434
2529
|
setPullDistance(distance);
|
|
2435
2530
|
}
|
|
2436
2531
|
}, [isPulling, isRefreshing, maxPull]);
|
|
2437
|
-
const onTouchEnd =
|
|
2532
|
+
const onTouchEnd = React.useCallback(() => {
|
|
2438
2533
|
if (!isPulling) return;
|
|
2439
2534
|
setIsPulling(false);
|
|
2440
2535
|
if (pullDistance >= threshold && !isRefreshing) {
|
|
@@ -2445,7 +2540,7 @@ function usePullToRefresh(onRefresh, options = {}) {
|
|
|
2445
2540
|
setPullDistance(0);
|
|
2446
2541
|
}
|
|
2447
2542
|
}, [isPulling, pullDistance, threshold, isRefreshing, onRefresh]);
|
|
2448
|
-
const endRefresh =
|
|
2543
|
+
const endRefresh = React.useCallback(() => {
|
|
2449
2544
|
setIsRefreshing(false);
|
|
2450
2545
|
setPullDistance(0);
|
|
2451
2546
|
}, []);
|
|
@@ -2483,9 +2578,9 @@ function useCanvasGestures(options) {
|
|
|
2483
2578
|
onPanDelta,
|
|
2484
2579
|
onMultiTouchStart
|
|
2485
2580
|
} = options;
|
|
2486
|
-
const pointers =
|
|
2487
|
-
const pinch =
|
|
2488
|
-
const computePinch =
|
|
2581
|
+
const pointers = React.useRef(/* @__PURE__ */ new Map());
|
|
2582
|
+
const pinch = React.useRef(null);
|
|
2583
|
+
const computePinch = React.useCallback(() => {
|
|
2489
2584
|
const pts = [...pointers.current.values()];
|
|
2490
2585
|
const dx = pts[1].x - pts[0].x;
|
|
2491
2586
|
const dy = pts[1].y - pts[0].y;
|
|
@@ -2494,7 +2589,7 @@ function useCanvasGestures(options) {
|
|
|
2494
2589
|
centroid: { x: (pts[0].x + pts[1].x) / 2, y: (pts[0].y + pts[1].y) / 2 }
|
|
2495
2590
|
};
|
|
2496
2591
|
}, []);
|
|
2497
|
-
const handlePointerDown =
|
|
2592
|
+
const handlePointerDown = React.useCallback(
|
|
2498
2593
|
(e) => {
|
|
2499
2594
|
if (!enabled) return;
|
|
2500
2595
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
@@ -2508,7 +2603,7 @@ function useCanvasGestures(options) {
|
|
|
2508
2603
|
},
|
|
2509
2604
|
[enabled, canvasRef, onMultiTouchStart, computePinch, onPointerDown]
|
|
2510
2605
|
);
|
|
2511
|
-
const handlePointerMove =
|
|
2606
|
+
const handlePointerMove = React.useCallback(
|
|
2512
2607
|
(e) => {
|
|
2513
2608
|
if (!enabled) return;
|
|
2514
2609
|
if (pointers.current.has(e.pointerId)) {
|
|
@@ -2528,7 +2623,7 @@ function useCanvasGestures(options) {
|
|
|
2528
2623
|
},
|
|
2529
2624
|
[enabled, canvasRef, computePinch, onZoom, onPanDelta, onPointerMove]
|
|
2530
2625
|
);
|
|
2531
|
-
const endPointer =
|
|
2626
|
+
const endPointer = React.useCallback(
|
|
2532
2627
|
(e, fireUp) => {
|
|
2533
2628
|
const wasMulti = pointers.current.size >= 2;
|
|
2534
2629
|
pointers.current.delete(e.pointerId);
|
|
@@ -2538,21 +2633,21 @@ function useCanvasGestures(options) {
|
|
|
2538
2633
|
},
|
|
2539
2634
|
[onPointerUp]
|
|
2540
2635
|
);
|
|
2541
|
-
const handlePointerUp =
|
|
2636
|
+
const handlePointerUp = React.useCallback(
|
|
2542
2637
|
(e) => {
|
|
2543
2638
|
if (!enabled) return;
|
|
2544
2639
|
endPointer(e, true);
|
|
2545
2640
|
},
|
|
2546
2641
|
[enabled, endPointer]
|
|
2547
2642
|
);
|
|
2548
|
-
const handlePointerCancel =
|
|
2643
|
+
const handlePointerCancel = React.useCallback(
|
|
2549
2644
|
(e) => {
|
|
2550
2645
|
if (!enabled) return;
|
|
2551
2646
|
endPointer(e, false);
|
|
2552
2647
|
},
|
|
2553
2648
|
[enabled, endPointer]
|
|
2554
2649
|
);
|
|
2555
|
-
const handleWheel =
|
|
2650
|
+
const handleWheel = React.useCallback(
|
|
2556
2651
|
(e) => {
|
|
2557
2652
|
if (!enabled) return;
|
|
2558
2653
|
e.preventDefault();
|
|
@@ -2571,24 +2666,24 @@ function useCanvasGestures(options) {
|
|
|
2571
2666
|
}
|
|
2572
2667
|
function useTapReveal(options = {}) {
|
|
2573
2668
|
const { onReveal, onDismiss, refs, enabled = true } = options;
|
|
2574
|
-
const [revealed, setRevealed] =
|
|
2575
|
-
const onRevealRef =
|
|
2576
|
-
const onDismissRef =
|
|
2669
|
+
const [revealed, setRevealed] = React.useState(false);
|
|
2670
|
+
const onRevealRef = React.useRef(onReveal);
|
|
2671
|
+
const onDismissRef = React.useRef(onDismiss);
|
|
2577
2672
|
onRevealRef.current = onReveal;
|
|
2578
2673
|
onDismissRef.current = onDismiss;
|
|
2579
|
-
const reveal =
|
|
2674
|
+
const reveal = React.useCallback(() => {
|
|
2580
2675
|
setRevealed((wasRevealed) => {
|
|
2581
2676
|
if (!wasRevealed) onRevealRef.current?.();
|
|
2582
2677
|
return true;
|
|
2583
2678
|
});
|
|
2584
2679
|
}, []);
|
|
2585
|
-
const dismiss =
|
|
2680
|
+
const dismiss = React.useCallback(() => {
|
|
2586
2681
|
setRevealed((wasRevealed) => {
|
|
2587
2682
|
if (wasRevealed) onDismissRef.current?.();
|
|
2588
2683
|
return false;
|
|
2589
2684
|
});
|
|
2590
2685
|
}, []);
|
|
2591
|
-
const onPointerDown =
|
|
2686
|
+
const onPointerDown = React.useCallback(
|
|
2592
2687
|
(e) => {
|
|
2593
2688
|
if (!enabled || e.pointerType === "mouse") return;
|
|
2594
2689
|
if (revealed) dismiss();
|
|
@@ -2596,7 +2691,7 @@ function useTapReveal(options = {}) {
|
|
|
2596
2691
|
},
|
|
2597
2692
|
[enabled, revealed, reveal, dismiss]
|
|
2598
2693
|
);
|
|
2599
|
-
|
|
2694
|
+
React.useEffect(() => {
|
|
2600
2695
|
if (!revealed || typeof document === "undefined") return;
|
|
2601
2696
|
const onDocDown = (ev) => {
|
|
2602
2697
|
const target = ev.target;
|
|
@@ -2614,9 +2709,9 @@ function useTapReveal(options = {}) {
|
|
|
2614
2709
|
}
|
|
2615
2710
|
var ALMADAR_DND_MIME = "application/x-almadar-dnd";
|
|
2616
2711
|
function useDraggable({ payload, disabled = false }) {
|
|
2617
|
-
const [isDragging, setIsDragging] =
|
|
2712
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
2618
2713
|
const eventBus = useEventBus();
|
|
2619
|
-
const handleDragStart =
|
|
2714
|
+
const handleDragStart = React.useCallback(
|
|
2620
2715
|
(e) => {
|
|
2621
2716
|
if (disabled) {
|
|
2622
2717
|
e.preventDefault();
|
|
@@ -2629,14 +2724,14 @@ function useDraggable({ payload, disabled = false }) {
|
|
|
2629
2724
|
},
|
|
2630
2725
|
[disabled, payload, eventBus]
|
|
2631
2726
|
);
|
|
2632
|
-
const handleDragEnd =
|
|
2727
|
+
const handleDragEnd = React.useCallback(
|
|
2633
2728
|
(e) => {
|
|
2634
2729
|
setIsDragging(false);
|
|
2635
2730
|
eventBus.emit("UI:DRAG_END", { kind: payload.kind, data: payload.data });
|
|
2636
2731
|
},
|
|
2637
2732
|
[payload, eventBus]
|
|
2638
2733
|
);
|
|
2639
|
-
const dragProps =
|
|
2734
|
+
const dragProps = React.useMemo(
|
|
2640
2735
|
() => ({
|
|
2641
2736
|
draggable: !disabled,
|
|
2642
2737
|
onDragStart: handleDragStart,
|
|
@@ -2662,9 +2757,9 @@ function hasAlmadarPayload(e) {
|
|
|
2662
2757
|
return e.dataTransfer.types.includes(ALMADAR_DND_MIME);
|
|
2663
2758
|
}
|
|
2664
2759
|
function useDropZone({ accepts, onDrop, disabled = false }) {
|
|
2665
|
-
const [isOver, setIsOver] =
|
|
2760
|
+
const [isOver, setIsOver] = React.useState(false);
|
|
2666
2761
|
const eventBus = useEventBus();
|
|
2667
|
-
const handleDragOver =
|
|
2762
|
+
const handleDragOver = React.useCallback(
|
|
2668
2763
|
(e) => {
|
|
2669
2764
|
if (disabled) return;
|
|
2670
2765
|
if (!hasAlmadarPayload(e)) return;
|
|
@@ -2674,13 +2769,13 @@ function useDropZone({ accepts, onDrop, disabled = false }) {
|
|
|
2674
2769
|
},
|
|
2675
2770
|
[disabled]
|
|
2676
2771
|
);
|
|
2677
|
-
const handleDragLeave =
|
|
2772
|
+
const handleDragLeave = React.useCallback(
|
|
2678
2773
|
(e) => {
|
|
2679
2774
|
setIsOver(false);
|
|
2680
2775
|
},
|
|
2681
2776
|
[]
|
|
2682
2777
|
);
|
|
2683
|
-
const handleDrop =
|
|
2778
|
+
const handleDrop = React.useCallback(
|
|
2684
2779
|
(e) => {
|
|
2685
2780
|
e.preventDefault();
|
|
2686
2781
|
setIsOver(false);
|
|
@@ -2694,7 +2789,7 @@ function useDropZone({ accepts, onDrop, disabled = false }) {
|
|
|
2694
2789
|
},
|
|
2695
2790
|
[disabled, accepts, onDrop, eventBus]
|
|
2696
2791
|
);
|
|
2697
|
-
const dropProps =
|
|
2792
|
+
const dropProps = React.useMemo(
|
|
2698
2793
|
() => ({
|
|
2699
2794
|
onDragOver: handleDragOver,
|
|
2700
2795
|
onDragLeave: handleDragLeave,
|
|
@@ -2706,14 +2801,14 @@ function useDropZone({ accepts, onDrop, disabled = false }) {
|
|
|
2706
2801
|
}
|
|
2707
2802
|
function useRenderInterpolation(options = {}) {
|
|
2708
2803
|
const tickIntervalMs = options.tickIntervalMs ?? 1e3 / 30;
|
|
2709
|
-
const prevRef =
|
|
2710
|
-
const currRef =
|
|
2711
|
-
const rafRef =
|
|
2712
|
-
const onSnapshot =
|
|
2804
|
+
const prevRef = React.useRef(null);
|
|
2805
|
+
const currRef = React.useRef(null);
|
|
2806
|
+
const rafRef = React.useRef(null);
|
|
2807
|
+
const onSnapshot = React.useCallback((entities) => {
|
|
2713
2808
|
prevRef.current = currRef.current;
|
|
2714
2809
|
currRef.current = { entities, arrivedAt: performance.now() };
|
|
2715
2810
|
}, []);
|
|
2716
|
-
const getInterpolated =
|
|
2811
|
+
const getInterpolated = React.useCallback((now) => {
|
|
2717
2812
|
const out = /* @__PURE__ */ new Map();
|
|
2718
2813
|
const curr = currRef.current;
|
|
2719
2814
|
if (!curr) return out;
|
|
@@ -2739,7 +2834,7 @@ function useRenderInterpolation(options = {}) {
|
|
|
2739
2834
|
}
|
|
2740
2835
|
return out;
|
|
2741
2836
|
}, [tickIntervalMs]);
|
|
2742
|
-
const startLoop =
|
|
2837
|
+
const startLoop = React.useCallback(
|
|
2743
2838
|
(draw) => {
|
|
2744
2839
|
let active = true;
|
|
2745
2840
|
const loop = () => {
|
|
@@ -2761,7 +2856,7 @@ function useRenderInterpolation(options = {}) {
|
|
|
2761
2856
|
},
|
|
2762
2857
|
[getInterpolated]
|
|
2763
2858
|
);
|
|
2764
|
-
|
|
2859
|
+
React.useEffect(() => {
|
|
2765
2860
|
return () => {
|
|
2766
2861
|
if (rafRef.current !== null) {
|
|
2767
2862
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -2801,7 +2896,7 @@ function useGitHubStatus() {
|
|
|
2801
2896
|
});
|
|
2802
2897
|
}
|
|
2803
2898
|
function useConnectGitHub() {
|
|
2804
|
-
const connectGitHub =
|
|
2899
|
+
const connectGitHub = React.useCallback(() => {
|
|
2805
2900
|
const userId = getUserId();
|
|
2806
2901
|
const state = btoa(JSON.stringify({ userId, returnUrl: window.location.href }));
|
|
2807
2902
|
window.location.href = `${API_BASE}/api/github/oauth/authorize?state=${state}`;
|