@flamingo-stack/openframe-frontend-core 0.0.718 → 0.0.719
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/{chunk-N2PF5CFX.js → chunk-2JLP2X2M.js} +1 -1
- package/dist/{chunk-YEMCCYIF.js → chunk-4D6NMPOO.js} +1 -1
- package/dist/{chunk-MIQLUUVF.cjs → chunk-4JIGEK7C.cjs} +6 -6
- package/dist/{chunk-JIWMBIVZ.js → chunk-5U3KWQXP.js} +3 -3
- package/dist/{chunk-67QBMN4R.js → chunk-5YAGX5DY.js} +1 -1
- package/dist/{chunk-GEDY7HQI.cjs → chunk-6X3O67OL.cjs} +4 -0
- package/dist/{chunk-DEZDMTBM.js → chunk-7BCY77W6.js} +5 -5
- package/dist/{chunk-BWIN42ZA.cjs → chunk-7BREFV7G.cjs} +19 -19
- package/dist/{chunk-45F7PXUI.js → chunk-AJHSQ5XK.js} +2 -2
- package/dist/{chunk-TBCZCRQ5.js → chunk-CU6NWO2M.js} +5 -5
- package/dist/{chunk-DCD5WZUF.js → chunk-D6PMVWDI.js} +2 -2
- package/dist/{chunk-2RKFMUNW.cjs → chunk-DFEPUYTF.cjs} +24 -21
- package/dist/{chunk-BOTM373R.cjs → chunk-E2V2EH2G.cjs} +2 -2
- package/dist/{chunk-PQ6HBLZ7.js → chunk-EAHOB64X.js} +3 -3
- package/dist/{chunk-SGFTTJKO.js → chunk-FVQJBII6.js} +1 -1
- package/dist/{chunk-APJZBDQN.js → chunk-H5V7GRN5.js} +24 -21
- package/dist/{chunk-6A43ZDWV.cjs → chunk-H5VIMBRN.cjs} +2 -2
- package/dist/{chunk-DXCBOZVT.cjs → chunk-HCFNEKO3.cjs} +13 -13
- package/dist/{chunk-Z5UWW3Z2.cjs → chunk-LCLDFMDF.cjs} +66 -50
- package/dist/{chunk-NDZ5ZXOQ.cjs → chunk-LOZLHG2U.cjs} +6 -6
- package/dist/{chunk-Z3CVSPO3.cjs → chunk-NQVS4G7G.cjs} +134 -134
- package/dist/{chunk-EZC2F5OT.cjs → chunk-NYWESHOQ.cjs} +15 -15
- package/dist/{chunk-YBQQNDC7.js → chunk-RR6PY34K.js} +4 -0
- package/dist/{chunk-GN4A7PMB.cjs → chunk-SWAVO7BB.cjs} +23 -23
- package/dist/{chunk-S2FUFMLW.cjs → chunk-TDZ76NCB.cjs} +16 -16
- package/dist/{chunk-QXZCLQNV.js → chunk-TELAANY6.js} +1 -1
- package/dist/{chunk-MM7MCIXL.js → chunk-TTEFN6VO.js} +4 -4
- package/dist/{chunk-YC5COB5V.cjs → chunk-WS7WRR5Z.cjs} +32 -32
- package/dist/{chunk-LOYPRJWA.js → chunk-Y4MB25KW.js} +66 -50
- package/dist/{chunk-WALCXC7J.cjs → chunk-ZKNZ2CXW.cjs} +3 -3
- package/dist/{cloud-tenants-TAKOWXLD.js → cloud-tenants-DNBPNQNP.js} +2 -2
- package/dist/{cloud-tenants-PFDF7O5U.cjs → cloud-tenants-FBUO66GW.cjs} +3 -3
- package/dist/components/case-studies/index.cjs +11 -11
- package/dist/components/case-studies/index.js +3 -3
- package/dist/components/contact/index.cjs +4 -4
- package/dist/components/contact/index.js +3 -3
- package/dist/components/docs/index.cjs +6 -6
- package/dist/components/docs/index.js +5 -5
- package/dist/components/embeds/index.cjs +4 -4
- package/dist/components/embeds/index.js +3 -3
- package/dist/components/faq/index.cjs +5 -5
- package/dist/components/faq/index.js +4 -4
- package/dist/components/features/index.cjs +3 -3
- package/dist/components/features/index.js +2 -2
- package/dist/components/features/remote-session/remote-desktop-view.d.ts +6 -2
- package/dist/components/features/remote-session/remote-desktop-view.d.ts.map +1 -1
- package/dist/components/help-center-pages/index.cjs +48 -48
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +23 -23
- package/dist/components/index.js +12 -12
- package/dist/components/meeting-scheduler/index.cjs +18 -18
- package/dist/components/meeting-scheduler/index.js +2 -2
- package/dist/components/navigation/index.cjs +4 -4
- package/dist/components/navigation/index.js +3 -3
- package/dist/components/onboarding-guides/index.cjs +7 -7
- package/dist/components/onboarding-guides/index.js +6 -6
- package/dist/components/product-demo/index.cjs +7 -7
- package/dist/components/product-demo/index.js +7 -7
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/related-content/related-content-section.d.ts +6 -6
- package/dist/components/related-content/related-content-section.d.ts.map +1 -1
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +3 -3
- package/dist/components/ui/index.js +2 -2
- package/dist/{devices-KRCGZMGA.cjs → devices-5A5TY4JD.cjs} +4 -4
- package/dist/{devices-LHEX7O5T.js → devices-PLDAEUSL.js} +2 -2
- package/dist/hooks/use-self-fetch.d.ts +3 -0
- package/dist/hooks/use-self-fetch.d.ts.map +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.js +3 -3
- package/dist/{knowledge-KLVPVEYZ.cjs → knowledge-FKTJ723Z.cjs} +3 -3
- package/dist/{knowledge-RZSFNR33.js → knowledge-G6Q5KRWV.js} +2 -2
- package/dist/{logs-OX3XTVL2.cjs → logs-CJCXUBU6.cjs} +11 -11
- package/dist/{logs-E5DOV5JO.js → logs-QMV6XIC4.js} +2 -2
- package/dist/{policies-MC2S4S5G.js → policies-G6D7AX6F.js} +2 -2
- package/dist/{policies-FOSCIZGK.cjs → policies-QMRTK3CY.cjs} +7 -7
- package/dist/{remote-session-DRFE5XZE.cjs → remote-session-2JVI7RVA.cjs} +3 -3
- package/dist/{remote-session-JQ2BPIE3.js → remote-session-DBD6OSTX.js} +1 -1
- package/dist/{software-update-D4OEIH65.js → software-update-6BQM6BKH.js} +2 -2
- package/dist/{software-update-HOBSTWVO.cjs → software-update-PNZMRDBT.cjs} +7 -7
- package/package.json +1 -1
- package/src/components/features/remote-session/remote-desktop-view.tsx +86 -63
- package/src/components/related-content/related-content-section.tsx +46 -47
- package/src/hooks/use-self-fetch.ts +7 -0
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
* `renderSkeletonForType` so the placeholder height matches the loaded card
|
|
29
29
|
* exactly (zero layout shift on resolve).
|
|
30
30
|
*
|
|
31
|
-
* One API call per content type
|
|
32
|
-
* (`buildListUrl` — injectable; defaults to the
|
|
33
|
-
* builder prefixed with `apiBaseUrl`). Fetching uses
|
|
34
|
-
* fetch, NO react-query) so third-party embedders need
|
|
35
|
-
* cards are imported via DEEP module paths (not the
|
|
36
|
-
* chunk never reaches `@tanstack/react-query`.
|
|
31
|
+
* One API call per page of a content type, carrying only that page's ids, via
|
|
32
|
+
* the shared list-URL builder (`buildListUrl` — injectable; defaults to the
|
|
33
|
+
* lib's byte-parity-tested builder prefixed with `apiBaseUrl`). Fetching uses
|
|
34
|
+
* `useSelfFetch` (plain fetch, NO react-query) so third-party embedders need
|
|
35
|
+
* no QueryClientProvider; cards are imported via DEEP module paths (not the
|
|
36
|
+
* chat barrel) so this chunk never reaches `@tanstack/react-query`.
|
|
37
37
|
*
|
|
38
38
|
* The per-type card + skeleton dispatch lives in `./card-registry`
|
|
39
39
|
* (`RELATED_CARD_REGISTRY`): ONE entry per content type, each carrying that
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
*/
|
|
50
50
|
|
|
51
51
|
import type React from 'react';
|
|
52
|
-
import {
|
|
52
|
+
import { useMemo, useState } from 'react';
|
|
53
53
|
import { useSelfFetch } from '../../hooks/use-self-fetch';
|
|
54
54
|
import type { ContentRef, ContentRefWithReason } from '../../types/content-ref';
|
|
55
55
|
import {
|
|
@@ -246,23 +246,29 @@ function CardForType({
|
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
// =============================================================================
|
|
249
|
-
// Fetch
|
|
250
|
-
//
|
|
251
|
-
// react-query usage: `enabled`
|
|
252
|
-
// `
|
|
253
|
-
// react-query: no retry/backoff, no focus
|
|
249
|
+
// Fetch ONE page of a group — only the ids on screen go into the list URL.
|
|
250
|
+
// Pages already fetched are kept by url, so paging back renders without a
|
|
251
|
+
// request. `useSelfFetch` replaces the hub's old react-query usage: `enabled`
|
|
252
|
+
// ≙ `url === null` (no list API → `items: null`), `!res.ok`/network error ≙
|
|
253
|
+
// an empty page. Accepted deltas vs react-query: no retry/backoff, no focus
|
|
254
|
+
// refetch, no cross-mount cache.
|
|
254
255
|
// =============================================================================
|
|
255
256
|
|
|
256
257
|
function useGroupItems(type: string, refs: ContentRef[], buildUrl: (type: string, ids: string[]) => string | null) {
|
|
257
258
|
const ids = refs.map(r => r.id);
|
|
258
259
|
const url = ids.length > 0 ? buildUrl(type, ids) : null;
|
|
259
|
-
const
|
|
260
|
-
const
|
|
261
|
-
|
|
260
|
+
const [pages, setPages] = useState<ReadonlyMap<string, unknown[]>>(() => new Map());
|
|
261
|
+
const cached = url !== null ? pages.get(url) : undefined;
|
|
262
|
+
const { data, dataUrl, error } = useSelfFetch<unknown>(cached ? null : url);
|
|
263
|
+
if (data != null && dataUrl !== null && !pages.has(dataUrl)) {
|
|
264
|
+
setPages(new Map(pages).set(dataUrl, extractItems(data)));
|
|
265
|
+
}
|
|
266
|
+
if (url === null) return { items: null, isLoading: false };
|
|
267
|
+
return { items: cached ?? (error ? [] : null), isLoading: !cached && !error };
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
// =============================================================================
|
|
265
|
-
// Per-group renderer — one API call
|
|
271
|
+
// Per-group renderer — one API call per page, then render cards via the
|
|
266
272
|
// dispatcher with per-type skeletons + per-type layout from CONTENT_REF_GROUPS.
|
|
267
273
|
// =============================================================================
|
|
268
274
|
|
|
@@ -325,41 +331,33 @@ function ContentGroup({
|
|
|
325
331
|
* its heading too — no orphaned titles. */
|
|
326
332
|
heading: React.ReactNode;
|
|
327
333
|
}) {
|
|
328
|
-
const { items, isLoading } = useGroupItems(type, refs, buildUrl);
|
|
329
334
|
const config = resolveGroupConfig(type);
|
|
330
335
|
const isListLayout = config.layout === 'list';
|
|
331
336
|
const cardSize = config.gridSize;
|
|
332
337
|
|
|
333
338
|
// Per-group pagination for big groups (author pages): GROUP_PAGE_SIZE items
|
|
334
|
-
// per page with the standard Pagination control below the group
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
// refetch) can never strand the view past the last page, and RESET when the
|
|
339
|
-
// ref set actually changes (shrink→grow must not return to a stale page).
|
|
339
|
+
// per page with the standard Pagination control below the group, each page
|
|
340
|
+
// fetched on its own. Back to page 1 whenever the ref set changes (a
|
|
341
|
+
// suggestion refetch can shrink it) — reset while rendering, so the stale
|
|
342
|
+
// page is never requested.
|
|
340
343
|
const [page, setPage] = useState(1);
|
|
341
344
|
const refsKey = refs.map(r => r.id).join('|');
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
}, [refsKey]);
|
|
345
|
+
const [pagedRefsKey, setPagedRefsKey] = useState(refsKey);
|
|
346
|
+
if (pagedRefsKey !== refsKey) {
|
|
347
|
+
setPagedRefsKey(refsKey);
|
|
348
|
+
setPage(1);
|
|
349
|
+
}
|
|
349
350
|
const totalGroupPages = pageCount(refs.length, GROUP_PAGE_SIZE);
|
|
350
|
-
const
|
|
351
|
-
const
|
|
352
|
-
refs.length > GROUP_PAGE_SIZE ? refs.slice((safePage - 1) * GROUP_PAGE_SIZE, safePage * GROUP_PAGE_SIZE) : refs;
|
|
351
|
+
const pageRefs = refs.slice((page - 1) * GROUP_PAGE_SIZE, page * GROUP_PAGE_SIZE);
|
|
352
|
+
const { items, isLoading } = useGroupItems(type, pageRefs, buildUrl);
|
|
353
353
|
const groupPagination =
|
|
354
|
-
totalGroupPages > 1 ?
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (isLoading && !items) {
|
|
362
|
-
const skeletons = visibleGroupRefs.map(r => (
|
|
354
|
+
totalGroupPages > 1 ? <Pagination currentPage={page} totalPages={totalGroupPages} onPageChange={setPage} /> : null;
|
|
355
|
+
|
|
356
|
+
// Skeletons until this page's rows land — SSR HTML and the client's first
|
|
357
|
+
// paint render identical skeletons (useSelfFetch starts loading on both
|
|
358
|
+
// sides). The pager stays in place while an unfetched page loads.
|
|
359
|
+
if (isLoading) {
|
|
360
|
+
const skeletons = pageRefs.map(r => (
|
|
363
361
|
<div key={r.id}>{renderSkeletonForType(type, cardSize, adminCampaignCard)}</div>
|
|
364
362
|
));
|
|
365
363
|
return (
|
|
@@ -370,11 +368,12 @@ function ContentGroup({
|
|
|
370
368
|
) : (
|
|
371
369
|
<div className={gridClassFor(columns)}>{skeletons}</div>
|
|
372
370
|
)}
|
|
371
|
+
{groupPagination}
|
|
373
372
|
</div>
|
|
374
373
|
);
|
|
375
374
|
}
|
|
376
375
|
|
|
377
|
-
if (!items
|
|
376
|
+
if (!items) return null;
|
|
378
377
|
|
|
379
378
|
// Index fetched rows by id, then render in REF order — refs carry the
|
|
380
379
|
// intended sequence (suggestion mode: the engine's tier order, so
|
|
@@ -393,7 +392,7 @@ function ContentGroup({
|
|
|
393
392
|
};
|
|
394
393
|
const itemById = new Map(items.map(it => [rowKey(it), it]));
|
|
395
394
|
|
|
396
|
-
const cards =
|
|
395
|
+
const cards = pageRefs
|
|
397
396
|
.map(contentRef => {
|
|
398
397
|
const itemId = String(contentRef.id);
|
|
399
398
|
const item = itemById.get(itemId);
|
|
@@ -426,9 +425,9 @@ function ContentGroup({
|
|
|
426
425
|
.filter(Boolean);
|
|
427
426
|
|
|
428
427
|
if (cards.length === 0) {
|
|
429
|
-
// Current PAGE resolved zero cards (
|
|
430
|
-
// and the
|
|
431
|
-
// pager exists the user must keep the controls
|
|
428
|
+
// Current PAGE resolved zero cards (its fetch failed, rows were deleted
|
|
429
|
+
// between the ref fetch and the page fetch, or a stricter list-API gate
|
|
430
|
+
// dropped them). When a pager exists the user must keep the controls —
|
|
432
431
|
// dropping the whole group would strand them. A genuinely empty group
|
|
433
432
|
// (no pager) still vanishes with its heading.
|
|
434
433
|
if (groupPagination) {
|
|
@@ -5,6 +5,9 @@ import { contentFetch } from '../utils/embed-content-fetch';
|
|
|
5
5
|
|
|
6
6
|
export interface UseSelfFetchResult<T> {
|
|
7
7
|
data: T | null;
|
|
8
|
+
/** The url `data` came from (`null` until something lands). While a new url
|
|
9
|
+
* loads, `data` still holds the previous one — compare before trusting it. */
|
|
10
|
+
dataUrl: string | null;
|
|
8
11
|
/** Imperatively patch the fetched data (e.g. optimistic vote updates). */
|
|
9
12
|
setData: Dispatch<SetStateAction<T | null>>;
|
|
10
13
|
isLoading: boolean;
|
|
@@ -48,6 +51,7 @@ export function useSelfFetch<T>(
|
|
|
48
51
|
const initialData = options?.initialData;
|
|
49
52
|
const revalidateOnVisibleAfterMs = options?.revalidateOnVisibleAfterMs;
|
|
50
53
|
const [data, setData] = useState<T | null>(initialData ?? null);
|
|
54
|
+
const [dataUrl, setDataUrl] = useState<string | null>(initialData !== undefined ? url : null);
|
|
51
55
|
const [isLoading, setIsLoading] = useState(initialData === undefined && url !== null);
|
|
52
56
|
const [error, setError] = useState(false);
|
|
53
57
|
const [reloadKey, setReloadKey] = useState(0);
|
|
@@ -78,6 +82,7 @@ export function useSelfFetch<T>(
|
|
|
78
82
|
// `initialData` is `undefined`.
|
|
79
83
|
if (syncedProps.initialData !== initialData && initialData !== undefined) {
|
|
80
84
|
setData(initialData);
|
|
85
|
+
setDataUrl(url);
|
|
81
86
|
}
|
|
82
87
|
// Fetching just got disabled — nothing will land to clear the spinner.
|
|
83
88
|
if (syncedProps.url !== url && url === null) {
|
|
@@ -101,6 +106,7 @@ export function useSelfFetch<T>(
|
|
|
101
106
|
const json = (await res.json()) as T;
|
|
102
107
|
if (!cancelled) {
|
|
103
108
|
setData(json);
|
|
109
|
+
setDataUrl(url);
|
|
104
110
|
dataUrlRef.current = url; // remember the url we now hold data for
|
|
105
111
|
dataAtRef.current = Date.now();
|
|
106
112
|
}
|
|
@@ -149,6 +155,7 @@ export function useSelfFetch<T>(
|
|
|
149
155
|
|
|
150
156
|
return {
|
|
151
157
|
data,
|
|
158
|
+
dataUrl,
|
|
152
159
|
setData,
|
|
153
160
|
isLoading,
|
|
154
161
|
error,
|