@flytedan/flytebot-design-system 0.60.0 → 0.61.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/index.cjs +202 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -14
- package/dist/index.d.ts +97 -14
- package/dist/index.js +198 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14203,6 +14203,75 @@ function BreadcrumbCrumb({
|
|
|
14203
14203
|
|
|
14204
14204
|
// src/kits/query.ts
|
|
14205
14205
|
import * as React74 from "react";
|
|
14206
|
+
|
|
14207
|
+
// src/kits/queryUrl.ts
|
|
14208
|
+
var historyUrlAdapter = {
|
|
14209
|
+
read: () => new URLSearchParams(window.location.search),
|
|
14210
|
+
write(next) {
|
|
14211
|
+
const search = next.toString();
|
|
14212
|
+
const url = window.location.pathname + (search ? `?${search}` : "") + window.location.hash;
|
|
14213
|
+
window.history.replaceState(window.history.state, "", url);
|
|
14214
|
+
},
|
|
14215
|
+
subscribe(onChange) {
|
|
14216
|
+
const onPopState = () => onChange(new URLSearchParams(window.location.search));
|
|
14217
|
+
window.addEventListener("popstate", onPopState);
|
|
14218
|
+
return () => window.removeEventListener("popstate", onPopState);
|
|
14219
|
+
}
|
|
14220
|
+
};
|
|
14221
|
+
var names = (scope) => {
|
|
14222
|
+
const prefix = scope ? `${scope}-` : "";
|
|
14223
|
+
return {
|
|
14224
|
+
q: `${prefix}q`,
|
|
14225
|
+
sort: `${prefix}sort`,
|
|
14226
|
+
dir: `${prefix}dir`,
|
|
14227
|
+
page: `${prefix}page`,
|
|
14228
|
+
pageSize: `${prefix}pageSize`,
|
|
14229
|
+
filters: `${prefix}filters`
|
|
14230
|
+
};
|
|
14231
|
+
};
|
|
14232
|
+
var positiveInt = (text) => {
|
|
14233
|
+
const n = Number(text);
|
|
14234
|
+
return text !== null && Number.isInteger(n) && n >= 1 ? n : null;
|
|
14235
|
+
};
|
|
14236
|
+
function parseFilters(text) {
|
|
14237
|
+
if (text === null) return null;
|
|
14238
|
+
try {
|
|
14239
|
+
const parsed = JSON.parse(text);
|
|
14240
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
14241
|
+
} catch {
|
|
14242
|
+
return null;
|
|
14243
|
+
}
|
|
14244
|
+
}
|
|
14245
|
+
function readQueryFromUrl(params, scope, base, paging) {
|
|
14246
|
+
const n = names(scope);
|
|
14247
|
+
const dir = params.get(n.dir);
|
|
14248
|
+
return {
|
|
14249
|
+
page: paging === "page" ? positiveInt(params.get(n.page)) ?? base.page : base.page,
|
|
14250
|
+
pageSize: positiveInt(params.get(n.pageSize)) ?? base.pageSize,
|
|
14251
|
+
sort: params.get(n.sort) || base.sort,
|
|
14252
|
+
dir: dir === "asc" || dir === "desc" ? dir : base.dir,
|
|
14253
|
+
q: params.get(n.q) ?? base.q,
|
|
14254
|
+
filters: parseFilters(params.get(n.filters)) ?? base.filters
|
|
14255
|
+
};
|
|
14256
|
+
}
|
|
14257
|
+
function writeQueryToUrl(params, scope, query, base, paging) {
|
|
14258
|
+
const n = names(scope);
|
|
14259
|
+
const next = new URLSearchParams(params);
|
|
14260
|
+
const set = (name, value, isDefault) => {
|
|
14261
|
+
if (value === null || isDefault) next.delete(name);
|
|
14262
|
+
else next.set(name, value);
|
|
14263
|
+
};
|
|
14264
|
+
set(n.q, query.q, query.q === base.q);
|
|
14265
|
+
set(n.sort, query.sort, query.sort === base.sort);
|
|
14266
|
+
set(n.dir, query.dir, query.dir === base.dir);
|
|
14267
|
+
set(n.pageSize, String(query.pageSize), query.pageSize === base.pageSize);
|
|
14268
|
+
set(n.page, String(query.page), paging === "keyset" || query.page === base.page);
|
|
14269
|
+
const filters = JSON.stringify(query.filters);
|
|
14270
|
+
set(n.filters, filters, filters === JSON.stringify(base.filters));
|
|
14271
|
+
return next;
|
|
14272
|
+
}
|
|
14273
|
+
|
|
14274
|
+
// src/kits/query.ts
|
|
14206
14275
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
14207
14276
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
14208
14277
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -14256,50 +14325,129 @@ function compare(a, b, dir) {
|
|
|
14256
14325
|
}
|
|
14257
14326
|
var API = null;
|
|
14258
14327
|
var PREFS = null;
|
|
14259
|
-
function
|
|
14260
|
-
|
|
14328
|
+
function loadedFrom(paging, answer) {
|
|
14329
|
+
if (paging === "keyset") {
|
|
14330
|
+
const r2 = answer;
|
|
14331
|
+
return { rows: r2.rows, pager: null, next: r2.next, total: r2.total ?? null, facets: r2.filter?.facets ?? {}, aggregate: r2.aggregate ?? {} };
|
|
14332
|
+
}
|
|
14333
|
+
const r = answer;
|
|
14334
|
+
return { rows: r.rows, pager: r.pager ?? null, next: null, total: null, facets: r.filter?.facets ?? {}, aggregate: r.aggregate ?? {} };
|
|
14335
|
+
}
|
|
14336
|
+
function requestFor(params, query, paging, after) {
|
|
14337
|
+
if (paging === "page") return { ...params || {}, ...query };
|
|
14338
|
+
const { sort, dir, q, filters, pageSize } = query;
|
|
14339
|
+
return { ...params || {}, sort, dir, q, filters, limit: pageSize, ...after === void 0 ? {} : { after } };
|
|
14340
|
+
}
|
|
14341
|
+
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
14342
|
+
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
14343
|
+
const [base] = React74.useState(() => {
|
|
14261
14344
|
const store = PREFS || window.PlannerPrefs;
|
|
14262
14345
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14263
14346
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14264
14347
|
});
|
|
14348
|
+
const [mountParams] = React74.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
|
|
14349
|
+
const address = React74.useRef(mountParams);
|
|
14350
|
+
const [query, setQuery] = React74.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
|
|
14265
14351
|
const savePref = React74.useCallback((patch2) => {
|
|
14266
14352
|
const store = PREFS || window.PlannerPrefs;
|
|
14267
14353
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14268
14354
|
}, [prefsKey]);
|
|
14269
14355
|
const [res, setRes] = React74.useState(null);
|
|
14270
14356
|
const [loading, setLoading] = React74.useState(true);
|
|
14271
|
-
const
|
|
14357
|
+
const [loadingMore, setLoadingMore] = React74.useState(false);
|
|
14358
|
+
const [failure, setFailure] = React74.useState(null);
|
|
14359
|
+
const [reloadToken, setReloadToken] = React74.useState(0);
|
|
14360
|
+
const moreController = React74.useRef(null);
|
|
14272
14361
|
const depKey = (deps || []).join("|");
|
|
14273
14362
|
const paramKey = JSON.stringify(params || {});
|
|
14274
14363
|
const queryKey = JSON.stringify(query);
|
|
14364
|
+
const lifetime = React74.useRef(null);
|
|
14365
|
+
React74.useEffect(() => {
|
|
14366
|
+
const controller = new AbortController();
|
|
14367
|
+
lifetime.current = controller;
|
|
14368
|
+
return () => controller.abort();
|
|
14369
|
+
}, []);
|
|
14370
|
+
const latest = React74.useRef({ res, loading, query, params, endpoint, url, base });
|
|
14371
|
+
React74.useEffect(() => {
|
|
14372
|
+
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
14373
|
+
});
|
|
14275
14374
|
React74.useEffect(() => {
|
|
14276
|
-
const
|
|
14375
|
+
const controller = new AbortController();
|
|
14376
|
+
const { signal } = controller;
|
|
14277
14377
|
setLoading(true);
|
|
14378
|
+
setLoadingMore(false);
|
|
14379
|
+
setFailure(null);
|
|
14278
14380
|
const t = setTimeout(() => {
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14381
|
+
const { url: u, base: b } = latest.current;
|
|
14382
|
+
if (u && address.current) {
|
|
14383
|
+
const next = writeQueryToUrl(address.current, u.scope, query, b, paging);
|
|
14384
|
+
if (next.toString() !== address.current.toString()) {
|
|
14385
|
+
address.current = next;
|
|
14386
|
+
(u.adapter ?? historyUrlAdapter).write(next);
|
|
14387
|
+
}
|
|
14388
|
+
}
|
|
14389
|
+
QueryKit.getApi().request(endpoint, requestFor(params, query, paging), { signal }).then(
|
|
14390
|
+
(r) => {
|
|
14391
|
+
if (signal.aborted) return;
|
|
14392
|
+
setRes(loadedFrom(paging, r));
|
|
14393
|
+
setLoading(false);
|
|
14394
|
+
},
|
|
14395
|
+
(e) => {
|
|
14396
|
+
if (signal.aborted) return;
|
|
14397
|
+
setFailure({ error: toError(e), during: "query" });
|
|
14398
|
+
setLoading(false);
|
|
14399
|
+
}
|
|
14400
|
+
);
|
|
14284
14401
|
}, query.q ? 220 : 60);
|
|
14285
|
-
return () =>
|
|
14286
|
-
|
|
14402
|
+
return () => {
|
|
14403
|
+
clearTimeout(t);
|
|
14404
|
+
controller.abort();
|
|
14405
|
+
moreController.current?.abort();
|
|
14406
|
+
moreController.current = null;
|
|
14407
|
+
};
|
|
14408
|
+
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
14409
|
+
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
14410
|
+
React74.useEffect(() => {
|
|
14411
|
+
if (!adapter) return;
|
|
14412
|
+
return adapter.subscribe((params2) => {
|
|
14413
|
+
const { url: u, base: b } = latest.current;
|
|
14414
|
+
if (!u) return;
|
|
14415
|
+
address.current = params2;
|
|
14416
|
+
const fromAddress = readQueryFromUrl(params2, u.scope, b, paging);
|
|
14417
|
+
setQuery((s) => JSON.stringify(s) === JSON.stringify(fromAddress) ? s : fromAddress);
|
|
14418
|
+
});
|
|
14419
|
+
}, [adapter, paging]);
|
|
14287
14420
|
const patch = (p, resetPage = true) => setQuery((s) => ({ ...s, ...p, page: resetPage ? 1 : p.page != null ? p.page : s.page }));
|
|
14288
|
-
const
|
|
14289
|
-
|
|
14290
|
-
|
|
14421
|
+
const loadMore = () => {
|
|
14422
|
+
const { res: loaded, loading: querying, query: q, params: p, endpoint: e } = latest.current;
|
|
14423
|
+
if (!loaded || loaded.next === null || querying || moreController.current !== null) return;
|
|
14424
|
+
const controller = new AbortController();
|
|
14425
|
+
const { signal } = controller;
|
|
14426
|
+
moreController.current = controller;
|
|
14427
|
+
setLoadingMore(true);
|
|
14428
|
+
setFailure(null);
|
|
14429
|
+
QueryKit.getApi().request(e, requestFor(p, q, "keyset", loaded.next), { signal }).then(
|
|
14430
|
+
(r) => {
|
|
14431
|
+
if (signal.aborted) return;
|
|
14432
|
+
moreController.current = null;
|
|
14433
|
+
const more = loadedFrom("keyset", r);
|
|
14434
|
+
setRes((now) => now && { ...more, rows: [...now.rows, ...more.rows], total: more.total ?? now.total });
|
|
14435
|
+
setLoadingMore(false);
|
|
14436
|
+
},
|
|
14437
|
+
(err) => {
|
|
14438
|
+
if (signal.aborted) return;
|
|
14439
|
+
moreController.current = null;
|
|
14440
|
+
setFailure({ error: toError(err), during: "more" });
|
|
14441
|
+
setLoadingMore(false);
|
|
14442
|
+
}
|
|
14443
|
+
);
|
|
14444
|
+
};
|
|
14445
|
+
const shared = {
|
|
14291
14446
|
rows: res ? res.rows : [],
|
|
14292
|
-
/** The response's pager block, verbatim. */
|
|
14293
|
-
pager,
|
|
14294
|
-
total: pager.total || 0,
|
|
14295
|
-
page: pager.page || query.page,
|
|
14296
14447
|
pageSize: query.pageSize,
|
|
14297
|
-
|
|
14298
|
-
from: pager.from || 0,
|
|
14299
|
-
to: pager.to || 0,
|
|
14300
|
-
facets: res && res.filter && res.filter.facets || {},
|
|
14448
|
+
facets: res ? res.facets : {},
|
|
14301
14449
|
/** Server-computed totals over the whole match, never the current page. */
|
|
14302
|
-
aggregate: res
|
|
14450
|
+
aggregate: res ? res.aggregate : {},
|
|
14303
14451
|
/** The live query object — pass to fetchAll-style calls that need the full match. */
|
|
14304
14452
|
query,
|
|
14305
14453
|
sort: query.sort ? { key: query.sort, dir: query.dir } : void 0,
|
|
@@ -14308,8 +14456,12 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14308
14456
|
loading,
|
|
14309
14457
|
/** True only on the very first load — later loads keep showing stale rows. */
|
|
14310
14458
|
initialLoading: loading && !res,
|
|
14459
|
+
error: failure ? failure.error : null,
|
|
14460
|
+
retry: () => {
|
|
14461
|
+
if (failure?.during === "more") loadMore();
|
|
14462
|
+
else setReloadToken((t) => t + 1);
|
|
14463
|
+
},
|
|
14311
14464
|
activeFilterCount: Object.values(query.filters).filter(isActiveFilterValue).length,
|
|
14312
|
-
setPage: (page) => patch({ page }, false),
|
|
14313
14465
|
setPageSize: (pageSize) => {
|
|
14314
14466
|
savePref({ pageSize });
|
|
14315
14467
|
patch({ pageSize });
|
|
@@ -14324,8 +14476,6 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14324
14476
|
savePref({ sort: key, dir: dir || "desc" });
|
|
14325
14477
|
setQuery((s) => ({ ...s, page: 1, sort: key, dir: dir || "desc" }));
|
|
14326
14478
|
},
|
|
14327
|
-
/** Same query, unpaged — for CSV export and select-all-matching. */
|
|
14328
|
-
fetchAll: () => QueryKit.getApi().request(endpoint, { ...params || {}, ...query, page: 1, pageSize: 1e5 }).then((r) => r.rows),
|
|
14329
14479
|
/** value may be an updater fn — required for toggles, or two fast clicks
|
|
14330
14480
|
both read the same stale array and the first one is lost. */
|
|
14331
14481
|
setFilter: (id, value) => setQuery((s) => ({ ...s, page: 1, filters: { ...s.filters, [id]: typeof value === "function" ? value(s.filters[id]) : value } })),
|
|
@@ -14336,14 +14486,30 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14336
14486
|
}),
|
|
14337
14487
|
setFilters: (filters) => patch({ filters }),
|
|
14338
14488
|
clearFilters: () => patch({ filters: {}, q: "" }),
|
|
14339
|
-
refresh: () =>
|
|
14489
|
+
refresh: () => setReloadToken((t) => t + 1),
|
|
14490
|
+
patchRows: (change) => setRes((now) => now && { ...now, rows: change(now.rows) }),
|
|
14340
14491
|
/* True on a re-query while the PREVIOUS rows are still rendered — sort, filter, page.
|
|
14341
14492
|
Distinct from `loading` (first load, nothing on screen) because the two need different
|
|
14342
14493
|
treatments: skeletons versus a stale overlay on real content. */
|
|
14343
14494
|
refreshing: loading && !!res,
|
|
14344
14495
|
queryString: QueryKit.toQueryString(query)
|
|
14345
14496
|
};
|
|
14346
|
-
|
|
14497
|
+
if (paging === "keyset") {
|
|
14498
|
+
return { ...shared, total: res ? res.total : null, hasMore: !!res && res.next !== null, loadingMore, loadMore };
|
|
14499
|
+
}
|
|
14500
|
+
const pager = res && res.pager || { page: query.page, pageSize: query.pageSize, total: 0, totalPages: 1, from: 0, to: 0, hasPrev: false, hasNext: false };
|
|
14501
|
+
return {
|
|
14502
|
+
...shared,
|
|
14503
|
+
pager,
|
|
14504
|
+
total: pager.total || 0,
|
|
14505
|
+
page: pager.page || query.page,
|
|
14506
|
+
totalPages: pager.totalPages || 1,
|
|
14507
|
+
from: pager.from || 0,
|
|
14508
|
+
to: pager.to || 0,
|
|
14509
|
+
setPage: (page) => patch({ page }, false),
|
|
14510
|
+
/** Same query, unpaged — for CSV export and select-all-matching. */
|
|
14511
|
+
fetchAll: () => QueryKit.getApi().request(endpoint, { ...params || {}, ...query, page: 1, pageSize: 1e5 }, { signal: lifetime.current.signal }).then((r) => r.rows)
|
|
14512
|
+
};
|
|
14347
14513
|
}
|
|
14348
14514
|
var QueryKit = {
|
|
14349
14515
|
DEFAULTS,
|
|
@@ -14788,6 +14954,7 @@ export {
|
|
|
14788
14954
|
formatRelative,
|
|
14789
14955
|
groupMessages,
|
|
14790
14956
|
hasModifier,
|
|
14957
|
+
historyUrlAdapter,
|
|
14791
14958
|
iconForMime,
|
|
14792
14959
|
importanceLevel,
|
|
14793
14960
|
importanceTokens,
|
|
@@ -14807,6 +14974,7 @@ export {
|
|
|
14807
14974
|
preferenceScore,
|
|
14808
14975
|
preferenceSegments,
|
|
14809
14976
|
rangeFilter,
|
|
14977
|
+
readQueryFromUrl,
|
|
14810
14978
|
resolveTheme,
|
|
14811
14979
|
revokeAttachment,
|
|
14812
14980
|
savePrefs,
|
|
@@ -14830,6 +14998,7 @@ export {
|
|
|
14830
14998
|
useToast,
|
|
14831
14999
|
validateFilterValue,
|
|
14832
15000
|
visibleMessages,
|
|
14833
|
-
watchAppearance
|
|
15001
|
+
watchAppearance,
|
|
15002
|
+
writeQueryToUrl
|
|
14834
15003
|
};
|
|
14835
15004
|
//# sourceMappingURL=index.js.map
|