@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.cjs
CHANGED
|
@@ -216,6 +216,7 @@ __export(index_exports, {
|
|
|
216
216
|
formatRelative: () => formatRelative,
|
|
217
217
|
groupMessages: () => groupMessages,
|
|
218
218
|
hasModifier: () => hasModifier,
|
|
219
|
+
historyUrlAdapter: () => historyUrlAdapter,
|
|
219
220
|
iconForMime: () => iconForMime,
|
|
220
221
|
importanceLevel: () => importanceLevel,
|
|
221
222
|
importanceTokens: () => importanceTokens,
|
|
@@ -235,6 +236,7 @@ __export(index_exports, {
|
|
|
235
236
|
preferenceScore: () => preferenceScore,
|
|
236
237
|
preferenceSegments: () => preferenceSegments,
|
|
237
238
|
rangeFilter: () => rangeFilter,
|
|
239
|
+
readQueryFromUrl: () => readQueryFromUrl,
|
|
238
240
|
resolveTheme: () => resolveTheme,
|
|
239
241
|
revokeAttachment: () => revokeAttachment,
|
|
240
242
|
savePrefs: () => savePrefs,
|
|
@@ -258,7 +260,8 @@ __export(index_exports, {
|
|
|
258
260
|
useToast: () => useToast,
|
|
259
261
|
validateFilterValue: () => validateFilterValue,
|
|
260
262
|
visibleMessages: () => visibleMessages,
|
|
261
|
-
watchAppearance: () => watchAppearance
|
|
263
|
+
watchAppearance: () => watchAppearance,
|
|
264
|
+
writeQueryToUrl: () => writeQueryToUrl
|
|
262
265
|
});
|
|
263
266
|
module.exports = __toCommonJS(index_exports);
|
|
264
267
|
|
|
@@ -14467,6 +14470,75 @@ function BreadcrumbCrumb({
|
|
|
14467
14470
|
|
|
14468
14471
|
// src/kits/query.ts
|
|
14469
14472
|
var React74 = __toESM(require("react"), 1);
|
|
14473
|
+
|
|
14474
|
+
// src/kits/queryUrl.ts
|
|
14475
|
+
var historyUrlAdapter = {
|
|
14476
|
+
read: () => new URLSearchParams(window.location.search),
|
|
14477
|
+
write(next) {
|
|
14478
|
+
const search = next.toString();
|
|
14479
|
+
const url = window.location.pathname + (search ? `?${search}` : "") + window.location.hash;
|
|
14480
|
+
window.history.replaceState(window.history.state, "", url);
|
|
14481
|
+
},
|
|
14482
|
+
subscribe(onChange) {
|
|
14483
|
+
const onPopState = () => onChange(new URLSearchParams(window.location.search));
|
|
14484
|
+
window.addEventListener("popstate", onPopState);
|
|
14485
|
+
return () => window.removeEventListener("popstate", onPopState);
|
|
14486
|
+
}
|
|
14487
|
+
};
|
|
14488
|
+
var names = (scope) => {
|
|
14489
|
+
const prefix = scope ? `${scope}-` : "";
|
|
14490
|
+
return {
|
|
14491
|
+
q: `${prefix}q`,
|
|
14492
|
+
sort: `${prefix}sort`,
|
|
14493
|
+
dir: `${prefix}dir`,
|
|
14494
|
+
page: `${prefix}page`,
|
|
14495
|
+
pageSize: `${prefix}pageSize`,
|
|
14496
|
+
filters: `${prefix}filters`
|
|
14497
|
+
};
|
|
14498
|
+
};
|
|
14499
|
+
var positiveInt = (text) => {
|
|
14500
|
+
const n = Number(text);
|
|
14501
|
+
return text !== null && Number.isInteger(n) && n >= 1 ? n : null;
|
|
14502
|
+
};
|
|
14503
|
+
function parseFilters(text) {
|
|
14504
|
+
if (text === null) return null;
|
|
14505
|
+
try {
|
|
14506
|
+
const parsed = JSON.parse(text);
|
|
14507
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
14508
|
+
} catch {
|
|
14509
|
+
return null;
|
|
14510
|
+
}
|
|
14511
|
+
}
|
|
14512
|
+
function readQueryFromUrl(params, scope, base, paging) {
|
|
14513
|
+
const n = names(scope);
|
|
14514
|
+
const dir = params.get(n.dir);
|
|
14515
|
+
return {
|
|
14516
|
+
page: paging === "page" ? positiveInt(params.get(n.page)) ?? base.page : base.page,
|
|
14517
|
+
pageSize: positiveInt(params.get(n.pageSize)) ?? base.pageSize,
|
|
14518
|
+
sort: params.get(n.sort) || base.sort,
|
|
14519
|
+
dir: dir === "asc" || dir === "desc" ? dir : base.dir,
|
|
14520
|
+
q: params.get(n.q) ?? base.q,
|
|
14521
|
+
filters: parseFilters(params.get(n.filters)) ?? base.filters
|
|
14522
|
+
};
|
|
14523
|
+
}
|
|
14524
|
+
function writeQueryToUrl(params, scope, query, base, paging) {
|
|
14525
|
+
const n = names(scope);
|
|
14526
|
+
const next = new URLSearchParams(params);
|
|
14527
|
+
const set = (name, value, isDefault) => {
|
|
14528
|
+
if (value === null || isDefault) next.delete(name);
|
|
14529
|
+
else next.set(name, value);
|
|
14530
|
+
};
|
|
14531
|
+
set(n.q, query.q, query.q === base.q);
|
|
14532
|
+
set(n.sort, query.sort, query.sort === base.sort);
|
|
14533
|
+
set(n.dir, query.dir, query.dir === base.dir);
|
|
14534
|
+
set(n.pageSize, String(query.pageSize), query.pageSize === base.pageSize);
|
|
14535
|
+
set(n.page, String(query.page), paging === "keyset" || query.page === base.page);
|
|
14536
|
+
const filters = JSON.stringify(query.filters);
|
|
14537
|
+
set(n.filters, filters, filters === JSON.stringify(base.filters));
|
|
14538
|
+
return next;
|
|
14539
|
+
}
|
|
14540
|
+
|
|
14541
|
+
// src/kits/query.ts
|
|
14470
14542
|
var isMultiSelectShaped = (v) => !!v && typeof v === "object" && Array.isArray(v.values);
|
|
14471
14543
|
var isRangeShaped = (v) => !!v && typeof v === "object" && ("min" in v || "max" in v);
|
|
14472
14544
|
var isDateShaped = (v) => !!v && typeof v === "object" && "kind" in v;
|
|
@@ -14520,50 +14592,129 @@ function compare(a, b, dir) {
|
|
|
14520
14592
|
}
|
|
14521
14593
|
var API = null;
|
|
14522
14594
|
var PREFS = null;
|
|
14523
|
-
function
|
|
14524
|
-
|
|
14595
|
+
function loadedFrom(paging, answer) {
|
|
14596
|
+
if (paging === "keyset") {
|
|
14597
|
+
const r2 = answer;
|
|
14598
|
+
return { rows: r2.rows, pager: null, next: r2.next, total: r2.total ?? null, facets: r2.filter?.facets ?? {}, aggregate: r2.aggregate ?? {} };
|
|
14599
|
+
}
|
|
14600
|
+
const r = answer;
|
|
14601
|
+
return { rows: r.rows, pager: r.pager ?? null, next: null, total: null, facets: r.filter?.facets ?? {}, aggregate: r.aggregate ?? {} };
|
|
14602
|
+
}
|
|
14603
|
+
function requestFor(params, query, paging, after) {
|
|
14604
|
+
if (paging === "page") return { ...params || {}, ...query };
|
|
14605
|
+
const { sort, dir, q, filters, pageSize } = query;
|
|
14606
|
+
return { ...params || {}, sort, dir, q, filters, limit: pageSize, ...after === void 0 ? {} : { after } };
|
|
14607
|
+
}
|
|
14608
|
+
var toError = (e) => e instanceof Error ? e : new Error(String(e));
|
|
14609
|
+
function useServerTable({ endpoint, params, defaults, deps, prefsKey, paging = "page", url }) {
|
|
14610
|
+
const [base] = React74.useState(() => {
|
|
14525
14611
|
const store = PREFS || window.PlannerPrefs;
|
|
14526
14612
|
const saved = prefsKey && store ? store.getTable(prefsKey) : {};
|
|
14527
14613
|
return { ...DEFAULTS, ...defaults || {}, ...saved.pageSize ? { pageSize: saved.pageSize } : {}, ...saved.sort ? { sort: saved.sort, dir: saved.dir || "desc" } : {} };
|
|
14528
14614
|
});
|
|
14615
|
+
const [mountParams] = React74.useState(() => url ? (url.adapter ?? historyUrlAdapter).read() : null);
|
|
14616
|
+
const address = React74.useRef(mountParams);
|
|
14617
|
+
const [query, setQuery] = React74.useState(() => url && mountParams ? readQueryFromUrl(mountParams, url.scope, base, paging) : base);
|
|
14529
14618
|
const savePref = React74.useCallback((patch2) => {
|
|
14530
14619
|
const store = PREFS || window.PlannerPrefs;
|
|
14531
14620
|
if (prefsKey && store) store.setTable(prefsKey, patch2);
|
|
14532
14621
|
}, [prefsKey]);
|
|
14533
14622
|
const [res, setRes] = React74.useState(null);
|
|
14534
14623
|
const [loading, setLoading] = React74.useState(true);
|
|
14535
|
-
const
|
|
14624
|
+
const [loadingMore, setLoadingMore] = React74.useState(false);
|
|
14625
|
+
const [failure, setFailure] = React74.useState(null);
|
|
14626
|
+
const [reloadToken, setReloadToken] = React74.useState(0);
|
|
14627
|
+
const moreController = React74.useRef(null);
|
|
14536
14628
|
const depKey = (deps || []).join("|");
|
|
14537
14629
|
const paramKey = JSON.stringify(params || {});
|
|
14538
14630
|
const queryKey = JSON.stringify(query);
|
|
14631
|
+
const lifetime = React74.useRef(null);
|
|
14632
|
+
React74.useEffect(() => {
|
|
14633
|
+
const controller = new AbortController();
|
|
14634
|
+
lifetime.current = controller;
|
|
14635
|
+
return () => controller.abort();
|
|
14636
|
+
}, []);
|
|
14637
|
+
const latest = React74.useRef({ res, loading, query, params, endpoint, url, base });
|
|
14638
|
+
React74.useEffect(() => {
|
|
14639
|
+
latest.current = { res, loading, query, params, endpoint, url, base };
|
|
14640
|
+
});
|
|
14539
14641
|
React74.useEffect(() => {
|
|
14540
|
-
const
|
|
14642
|
+
const controller = new AbortController();
|
|
14643
|
+
const { signal } = controller;
|
|
14541
14644
|
setLoading(true);
|
|
14645
|
+
setLoadingMore(false);
|
|
14646
|
+
setFailure(null);
|
|
14542
14647
|
const t = setTimeout(() => {
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14648
|
+
const { url: u, base: b } = latest.current;
|
|
14649
|
+
if (u && address.current) {
|
|
14650
|
+
const next = writeQueryToUrl(address.current, u.scope, query, b, paging);
|
|
14651
|
+
if (next.toString() !== address.current.toString()) {
|
|
14652
|
+
address.current = next;
|
|
14653
|
+
(u.adapter ?? historyUrlAdapter).write(next);
|
|
14654
|
+
}
|
|
14655
|
+
}
|
|
14656
|
+
QueryKit.getApi().request(endpoint, requestFor(params, query, paging), { signal }).then(
|
|
14657
|
+
(r) => {
|
|
14658
|
+
if (signal.aborted) return;
|
|
14659
|
+
setRes(loadedFrom(paging, r));
|
|
14660
|
+
setLoading(false);
|
|
14661
|
+
},
|
|
14662
|
+
(e) => {
|
|
14663
|
+
if (signal.aborted) return;
|
|
14664
|
+
setFailure({ error: toError(e), during: "query" });
|
|
14665
|
+
setLoading(false);
|
|
14666
|
+
}
|
|
14667
|
+
);
|
|
14548
14668
|
}, query.q ? 220 : 60);
|
|
14549
|
-
return () =>
|
|
14550
|
-
|
|
14669
|
+
return () => {
|
|
14670
|
+
clearTimeout(t);
|
|
14671
|
+
controller.abort();
|
|
14672
|
+
moreController.current?.abort();
|
|
14673
|
+
moreController.current = null;
|
|
14674
|
+
};
|
|
14675
|
+
}, [endpoint, queryKey, paramKey, depKey, paging, reloadToken]);
|
|
14676
|
+
const adapter = url ? url.adapter ?? historyUrlAdapter : null;
|
|
14677
|
+
React74.useEffect(() => {
|
|
14678
|
+
if (!adapter) return;
|
|
14679
|
+
return adapter.subscribe((params2) => {
|
|
14680
|
+
const { url: u, base: b } = latest.current;
|
|
14681
|
+
if (!u) return;
|
|
14682
|
+
address.current = params2;
|
|
14683
|
+
const fromAddress = readQueryFromUrl(params2, u.scope, b, paging);
|
|
14684
|
+
setQuery((s) => JSON.stringify(s) === JSON.stringify(fromAddress) ? s : fromAddress);
|
|
14685
|
+
});
|
|
14686
|
+
}, [adapter, paging]);
|
|
14551
14687
|
const patch = (p, resetPage = true) => setQuery((s) => ({ ...s, ...p, page: resetPage ? 1 : p.page != null ? p.page : s.page }));
|
|
14552
|
-
const
|
|
14553
|
-
|
|
14554
|
-
|
|
14688
|
+
const loadMore = () => {
|
|
14689
|
+
const { res: loaded, loading: querying, query: q, params: p, endpoint: e } = latest.current;
|
|
14690
|
+
if (!loaded || loaded.next === null || querying || moreController.current !== null) return;
|
|
14691
|
+
const controller = new AbortController();
|
|
14692
|
+
const { signal } = controller;
|
|
14693
|
+
moreController.current = controller;
|
|
14694
|
+
setLoadingMore(true);
|
|
14695
|
+
setFailure(null);
|
|
14696
|
+
QueryKit.getApi().request(e, requestFor(p, q, "keyset", loaded.next), { signal }).then(
|
|
14697
|
+
(r) => {
|
|
14698
|
+
if (signal.aborted) return;
|
|
14699
|
+
moreController.current = null;
|
|
14700
|
+
const more = loadedFrom("keyset", r);
|
|
14701
|
+
setRes((now) => now && { ...more, rows: [...now.rows, ...more.rows], total: more.total ?? now.total });
|
|
14702
|
+
setLoadingMore(false);
|
|
14703
|
+
},
|
|
14704
|
+
(err) => {
|
|
14705
|
+
if (signal.aborted) return;
|
|
14706
|
+
moreController.current = null;
|
|
14707
|
+
setFailure({ error: toError(err), during: "more" });
|
|
14708
|
+
setLoadingMore(false);
|
|
14709
|
+
}
|
|
14710
|
+
);
|
|
14711
|
+
};
|
|
14712
|
+
const shared = {
|
|
14555
14713
|
rows: res ? res.rows : [],
|
|
14556
|
-
/** The response's pager block, verbatim. */
|
|
14557
|
-
pager,
|
|
14558
|
-
total: pager.total || 0,
|
|
14559
|
-
page: pager.page || query.page,
|
|
14560
14714
|
pageSize: query.pageSize,
|
|
14561
|
-
|
|
14562
|
-
from: pager.from || 0,
|
|
14563
|
-
to: pager.to || 0,
|
|
14564
|
-
facets: res && res.filter && res.filter.facets || {},
|
|
14715
|
+
facets: res ? res.facets : {},
|
|
14565
14716
|
/** Server-computed totals over the whole match, never the current page. */
|
|
14566
|
-
aggregate: res
|
|
14717
|
+
aggregate: res ? res.aggregate : {},
|
|
14567
14718
|
/** The live query object — pass to fetchAll-style calls that need the full match. */
|
|
14568
14719
|
query,
|
|
14569
14720
|
sort: query.sort ? { key: query.sort, dir: query.dir } : void 0,
|
|
@@ -14572,8 +14723,12 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14572
14723
|
loading,
|
|
14573
14724
|
/** True only on the very first load — later loads keep showing stale rows. */
|
|
14574
14725
|
initialLoading: loading && !res,
|
|
14726
|
+
error: failure ? failure.error : null,
|
|
14727
|
+
retry: () => {
|
|
14728
|
+
if (failure?.during === "more") loadMore();
|
|
14729
|
+
else setReloadToken((t) => t + 1);
|
|
14730
|
+
},
|
|
14575
14731
|
activeFilterCount: Object.values(query.filters).filter(isActiveFilterValue).length,
|
|
14576
|
-
setPage: (page) => patch({ page }, false),
|
|
14577
14732
|
setPageSize: (pageSize) => {
|
|
14578
14733
|
savePref({ pageSize });
|
|
14579
14734
|
patch({ pageSize });
|
|
@@ -14588,8 +14743,6 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14588
14743
|
savePref({ sort: key, dir: dir || "desc" });
|
|
14589
14744
|
setQuery((s) => ({ ...s, page: 1, sort: key, dir: dir || "desc" }));
|
|
14590
14745
|
},
|
|
14591
|
-
/** Same query, unpaged — for CSV export and select-all-matching. */
|
|
14592
|
-
fetchAll: () => QueryKit.getApi().request(endpoint, { ...params || {}, ...query, page: 1, pageSize: 1e5 }).then((r) => r.rows),
|
|
14593
14746
|
/** value may be an updater fn — required for toggles, or two fast clicks
|
|
14594
14747
|
both read the same stale array and the first one is lost. */
|
|
14595
14748
|
setFilter: (id, value) => setQuery((s) => ({ ...s, page: 1, filters: { ...s.filters, [id]: typeof value === "function" ? value(s.filters[id]) : value } })),
|
|
@@ -14600,14 +14753,30 @@ function useServerTable({ endpoint, params, defaults, deps, prefsKey }) {
|
|
|
14600
14753
|
}),
|
|
14601
14754
|
setFilters: (filters) => patch({ filters }),
|
|
14602
14755
|
clearFilters: () => patch({ filters: {}, q: "" }),
|
|
14603
|
-
refresh: () =>
|
|
14756
|
+
refresh: () => setReloadToken((t) => t + 1),
|
|
14757
|
+
patchRows: (change) => setRes((now) => now && { ...now, rows: change(now.rows) }),
|
|
14604
14758
|
/* True on a re-query while the PREVIOUS rows are still rendered — sort, filter, page.
|
|
14605
14759
|
Distinct from `loading` (first load, nothing on screen) because the two need different
|
|
14606
14760
|
treatments: skeletons versus a stale overlay on real content. */
|
|
14607
14761
|
refreshing: loading && !!res,
|
|
14608
14762
|
queryString: QueryKit.toQueryString(query)
|
|
14609
14763
|
};
|
|
14610
|
-
|
|
14764
|
+
if (paging === "keyset") {
|
|
14765
|
+
return { ...shared, total: res ? res.total : null, hasMore: !!res && res.next !== null, loadingMore, loadMore };
|
|
14766
|
+
}
|
|
14767
|
+
const pager = res && res.pager || { page: query.page, pageSize: query.pageSize, total: 0, totalPages: 1, from: 0, to: 0, hasPrev: false, hasNext: false };
|
|
14768
|
+
return {
|
|
14769
|
+
...shared,
|
|
14770
|
+
pager,
|
|
14771
|
+
total: pager.total || 0,
|
|
14772
|
+
page: pager.page || query.page,
|
|
14773
|
+
totalPages: pager.totalPages || 1,
|
|
14774
|
+
from: pager.from || 0,
|
|
14775
|
+
to: pager.to || 0,
|
|
14776
|
+
setPage: (page) => patch({ page }, false),
|
|
14777
|
+
/** Same query, unpaged — for CSV export and select-all-matching. */
|
|
14778
|
+
fetchAll: () => QueryKit.getApi().request(endpoint, { ...params || {}, ...query, page: 1, pageSize: 1e5 }, { signal: lifetime.current.signal }).then((r) => r.rows)
|
|
14779
|
+
};
|
|
14611
14780
|
}
|
|
14612
14781
|
var QueryKit = {
|
|
14613
14782
|
DEFAULTS,
|
|
@@ -15053,6 +15222,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
15053
15222
|
formatRelative,
|
|
15054
15223
|
groupMessages,
|
|
15055
15224
|
hasModifier,
|
|
15225
|
+
historyUrlAdapter,
|
|
15056
15226
|
iconForMime,
|
|
15057
15227
|
importanceLevel,
|
|
15058
15228
|
importanceTokens,
|
|
@@ -15072,6 +15242,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
15072
15242
|
preferenceScore,
|
|
15073
15243
|
preferenceSegments,
|
|
15074
15244
|
rangeFilter,
|
|
15245
|
+
readQueryFromUrl,
|
|
15075
15246
|
resolveTheme,
|
|
15076
15247
|
revokeAttachment,
|
|
15077
15248
|
savePrefs,
|
|
@@ -15095,6 +15266,7 @@ function useDocumentTitle(routeTitle, appName) {
|
|
|
15095
15266
|
useToast,
|
|
15096
15267
|
validateFilterValue,
|
|
15097
15268
|
visibleMessages,
|
|
15098
|
-
watchAppearance
|
|
15269
|
+
watchAppearance,
|
|
15270
|
+
writeQueryToUrl
|
|
15099
15271
|
});
|
|
15100
15272
|
//# sourceMappingURL=index.cjs.map
|