@columenlabs/lumen-ui 0.1.202 → 0.1.204
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/assistant/lumen-assistant.js +2 -1
- package/dist/lazy-part.d.ts +10 -1
- package/dist/lazy-part.js +51 -2
- package/dist/route-error.d.ts +1 -3
- package/dist/route-error.js +2 -10
- package/package.json +2 -2
|
@@ -24,7 +24,8 @@ import { chatMarkdown, chatTurns, copyMarkdown, turnMarkdown } from './copy.js';
|
|
|
24
24
|
import { composeAssistant, selectionRef, useComposeRequest, usePageSelection, useShownAssistantSources, } from './sources.js';
|
|
25
25
|
import { useAssistantChat } from './use-assistant-chat.js';
|
|
26
26
|
// The Markdown renderer (tables included) loads with the first answer (lazy-part.tsx).
|
|
27
|
-
|
|
27
|
+
// A tab whose build a deploy replaced shows the answer as plain text instead of reloading mid chat.
|
|
28
|
+
const ChatMarkdown = lazyPart(() => import('./chat-markdown.js').then((m) => m.default), null, ({ children }) => _jsx("p", { className: "whitespace-pre-wrap", children: children }));
|
|
28
29
|
/** The main model's context drawn full (tokens); the mark sits where the assistant compacts. */
|
|
29
30
|
const CONTEXT_MAX = 200_000;
|
|
30
31
|
const COMPACT_AT = 150_000;
|
package/dist/lazy-part.d.ts
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
* first page never downloads what it doesn't draw. The import must be a dynamic `import()` with the
|
|
4
4
|
* part's module, and every other import of that module elsewhere in the kit's static graph must be
|
|
5
5
|
* type-only, or the bundler keeps it in the first file.
|
|
6
|
+
*
|
|
7
|
+
* Every lazy part also loads on its own once the tab is idle (8 s after load). A deploy replaces
|
|
8
|
+
* the hashed files, so a tab that first drew a part after one asked for a file that was gone and
|
|
9
|
+
* reloaded: the assistant's first answer reloaded the page mid chat (2026-11-04,
|
|
10
|
+
* `chat-markdown-*.js`). Loaded early, the part is in the tab's module map before any deploy.
|
|
6
11
|
*/
|
|
7
12
|
import { type ComponentType, type ReactNode } from 'react';
|
|
8
|
-
|
|
13
|
+
/** A dynamic import that failed to load (Chrome, Firefox, Safari wording), not a page's own bug. */
|
|
14
|
+
export declare function isStaleBuildError(error: unknown): boolean;
|
|
15
|
+
export declare function lazyPart<P extends object>(load: () => Promise<ComponentType<P>>, fallback?: ReactNode,
|
|
16
|
+
/** Drawn instead when a deploy removed the part's file, so the tab keeps working (no reload). */
|
|
17
|
+
stale?: ComponentType<P>): ComponentType<P>;
|
package/dist/lazy-part.js
CHANGED
|
@@ -4,10 +4,59 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* first page never downloads what it doesn't draw. The import must be a dynamic `import()` with the
|
|
5
5
|
* part's module, and every other import of that module elsewhere in the kit's static graph must be
|
|
6
6
|
* type-only, or the bundler keeps it in the first file.
|
|
7
|
+
*
|
|
8
|
+
* Every lazy part also loads on its own once the tab is idle (8 s after load). A deploy replaces
|
|
9
|
+
* the hashed files, so a tab that first drew a part after one asked for a file that was gone and
|
|
10
|
+
* reloaded: the assistant's first answer reloaded the page mid chat (2026-11-04,
|
|
11
|
+
* `chat-markdown-*.js`). Loaded early, the part is in the tab's module map before any deploy.
|
|
7
12
|
*/
|
|
8
13
|
import { Suspense, lazy } from 'react';
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
/** A dynamic import that failed to load (Chrome, Firefox, Safari wording), not a page's own bug. */
|
|
15
|
+
export function isStaleBuildError(error) {
|
|
16
|
+
const message = error instanceof Error ? error.message : '';
|
|
17
|
+
return (message.startsWith('Failed to fetch dynamically imported module') ||
|
|
18
|
+
message.startsWith('error loading dynamically imported module') ||
|
|
19
|
+
message.startsWith('Importing a module script failed') ||
|
|
20
|
+
message.includes('Unable to preload CSS') ||
|
|
21
|
+
// Safari, when a missing file comes back as a page instead of a script.
|
|
22
|
+
message.includes('is not a valid JavaScript MIME type'));
|
|
23
|
+
}
|
|
24
|
+
/** How long after load the lazy parts start loading: the first page's own work comes first. */
|
|
25
|
+
const PRELOAD_AFTER_MS = 8_000;
|
|
26
|
+
const loaders = new Set();
|
|
27
|
+
let scheduled = false;
|
|
28
|
+
function schedulePreload() {
|
|
29
|
+
if (scheduled || typeof window === 'undefined')
|
|
30
|
+
return;
|
|
31
|
+
scheduled = true;
|
|
32
|
+
const run = () => {
|
|
33
|
+
for (const load of loaders)
|
|
34
|
+
load().catch(() => { });
|
|
35
|
+
};
|
|
36
|
+
const idle = () => setTimeout(() => 'requestIdleCallback' in window ? window.requestIdleCallback(run) : setTimeout(run, 1000), PRELOAD_AFTER_MS);
|
|
37
|
+
if (document.readyState === 'complete')
|
|
38
|
+
idle();
|
|
39
|
+
else
|
|
40
|
+
window.addEventListener('load', idle, { once: true });
|
|
41
|
+
}
|
|
42
|
+
export function lazyPart(load, fallback = null,
|
|
43
|
+
/** Drawn instead when a deploy removed the part's file, so the tab keeps working (no reload). */
|
|
44
|
+
stale) {
|
|
45
|
+
let pending = null;
|
|
46
|
+
const once = () => {
|
|
47
|
+
pending ??= load().catch((error) => {
|
|
48
|
+
pending = null;
|
|
49
|
+
throw error;
|
|
50
|
+
});
|
|
51
|
+
return pending;
|
|
52
|
+
};
|
|
53
|
+
loaders.add(once);
|
|
54
|
+
schedulePreload();
|
|
55
|
+
const Part = lazy(() => once().then((c) => ({ default: c }), (error) => {
|
|
56
|
+
if (stale && isStaleBuildError(error))
|
|
57
|
+
return { default: stale };
|
|
58
|
+
throw error;
|
|
59
|
+
}));
|
|
11
60
|
function LazyPart(props) {
|
|
12
61
|
return (_jsx(Suspense, { fallback: fallback, children: _jsx(Part, { ...props }) }));
|
|
13
62
|
}
|
package/dist/route-error.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ErrorComponentProps } from '@tanstack/react-router';
|
|
2
|
-
|
|
3
|
-
export declare function isStaleBuildError(error: unknown): boolean;
|
|
2
|
+
export { isStaleBuildError } from './lazy-part.js';
|
|
4
3
|
/**
|
|
5
4
|
* Reloads onto the new build unless it already did in the last 10 s (a file that is truly missing
|
|
6
5
|
* then shows its error instead of reloading forever); says whether a reload is under way.
|
|
@@ -39,4 +38,3 @@ export declare function ErrorPage({ error, onRetry, what, }: {
|
|
|
39
38
|
* tried once more on its own, then shown with Try again and Reload. Each one is logged.
|
|
40
39
|
*/
|
|
41
40
|
export declare function RouteError({ error, reset }: ErrorComponentProps): import("react").JSX.Element;
|
|
42
|
-
export {};
|
package/dist/route-error.js
CHANGED
|
@@ -17,6 +17,7 @@ import { ChevronRight, RefreshCw, RotateCcw, TriangleAlert } from 'lucide-react'
|
|
|
17
17
|
import { useEffect, useState } from 'react';
|
|
18
18
|
import { toast } from 'sonner';
|
|
19
19
|
import { fetchWithin } from './fetch-within.js';
|
|
20
|
+
import { isStaleBuildError } from './lazy-part.js';
|
|
20
21
|
import { reportClientError } from './telemetry.js';
|
|
21
22
|
import { Button } from './ui/button.js';
|
|
22
23
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible.js';
|
|
@@ -24,16 +25,7 @@ import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTi
|
|
|
24
25
|
import { Spinner } from './ui/spinner.js';
|
|
25
26
|
const KEY = 'lumen_new_build_reload';
|
|
26
27
|
const GAP_MS = 10_000;
|
|
27
|
-
|
|
28
|
-
export function isStaleBuildError(error) {
|
|
29
|
-
const message = error instanceof Error ? error.message : '';
|
|
30
|
-
return (message.startsWith('Failed to fetch dynamically imported module') ||
|
|
31
|
-
message.startsWith('error loading dynamically imported module') ||
|
|
32
|
-
message.startsWith('Importing a module script failed') ||
|
|
33
|
-
message.includes('Unable to preload CSS') ||
|
|
34
|
-
// Safari, when a missing file comes back as a page instead of a script.
|
|
35
|
-
message.includes('is not a valid JavaScript MIME type'));
|
|
36
|
-
}
|
|
28
|
+
export { isStaleBuildError } from './lazy-part.js';
|
|
37
29
|
/** A reload this tab has already started; anything failing meanwhile waits for it. */
|
|
38
30
|
let reloadStarted = false;
|
|
39
31
|
/** Whether this tab has not reloaded for a new build in the last 10 s. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.204",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@codemirror/lang-javascript": "6.2.5",
|
|
50
50
|
"@codemirror/lang-json": "6.0.2",
|
|
51
51
|
"@codemirror/lang-sql": "6.10.0",
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.204",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|