@timeax/form-palette 0.0.30 → 0.0.32

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/extra.js CHANGED
@@ -253,19 +253,139 @@ function mapOptions(rawList, mapping, ctx) {
253
253
  }
254
254
 
255
255
  // src/presets/lister/engine/search.ts
256
- function optionText(o3) {
257
- var _a;
258
- const l2 = o3.label;
259
- if (typeof l2 === "string") return l2;
260
- if (typeof l2 === "number") return String(l2);
261
- const rl = (_a = o3.raw) == null ? void 0 : _a.label;
262
- if (typeof rl === "string") return rl;
263
- return String(o3.value);
264
- }
265
- function filterOptionsLocal(options, query) {
256
+ function getPath2(obj, path) {
257
+ if (!obj || !path) return void 0;
258
+ if (!path.includes(".")) return obj[path];
259
+ let cur = obj;
260
+ for (const part of path.split(".")) {
261
+ if (cur == null) return void 0;
262
+ cur = cur[part];
263
+ }
264
+ return cur;
265
+ }
266
+ function toText(v2) {
267
+ if (v2 == null) return "";
268
+ if (typeof v2 === "string") return v2;
269
+ if (typeof v2 === "number" || typeof v2 === "boolean") return String(v2);
270
+ return "";
271
+ }
272
+ function collectAllText(obj, out, depth = 2, budget = { n: 80 }) {
273
+ if (obj == null || budget.n <= 0) return;
274
+ const t4 = typeof obj;
275
+ if (t4 === "string" || t4 === "number" || t4 === "boolean") {
276
+ out.push(String(obj));
277
+ budget.n -= 1;
278
+ return;
279
+ }
280
+ if (depth <= 0) return;
281
+ if (Array.isArray(obj)) {
282
+ for (const x2 of obj) collectAllText(x2, out, depth - 1, budget);
283
+ return;
284
+ }
285
+ if (t4 === "object") {
286
+ for (const k2 of Object.keys(obj)) {
287
+ collectAllText(obj[k2], out, depth - 1, budget);
288
+ if (budget.n <= 0) break;
289
+ }
290
+ }
291
+ }
292
+ function matchQueryInText(q2, text) {
293
+ if (!q2) return true;
294
+ return text.toLowerCase().includes(q2);
295
+ }
296
+ function buildSearchTextForKeys(raw, keys) {
297
+ const parts = [];
298
+ for (const k2 of keys) {
299
+ const key = String(k2);
300
+ const v2 = getPath2(raw, key);
301
+ if (v2 == null) continue;
302
+ if (Array.isArray(v2)) {
303
+ for (const x2 of v2) {
304
+ const s4 = toText(x2);
305
+ if (s4) parts.push(s4);
306
+ }
307
+ continue;
308
+ }
309
+ const s3 = toText(v2);
310
+ if (s3) parts.push(s3);
311
+ }
312
+ return parts.join(" ");
313
+ }
314
+ function matchesSearch(raw, q2, search) {
315
+ if (!q2) return true;
316
+ if (search == null ? void 0 : search.searchAll) {
317
+ return matchQueryInText(q2, buildSearchTextAll(raw));
318
+ }
319
+ if (Array.isArray(search == null ? void 0 : search.searchOnly) && search.searchOnly.length) {
320
+ return matchQueryInText(
321
+ q2,
322
+ buildSearchTextForKeys(raw, search.searchOnly)
323
+ );
324
+ }
325
+ if (typeof (search == null ? void 0 : search.subject) === "string" && search.subject) {
326
+ return matchQueryInText(
327
+ q2,
328
+ buildSearchTextForKeys(raw, [search.subject])
329
+ );
330
+ }
331
+ return matchQueryInText(q2, buildSearchTextAll(raw));
332
+ }
333
+ function buildSearchTextAll(raw) {
334
+ const parts = [];
335
+ collectAllText(raw, parts, 2);
336
+ return parts.join(" ");
337
+ }
338
+ function isEmptyFilterValue(v2) {
339
+ if (v2 === void 0 || v2 === null) return true;
340
+ if (typeof v2 === "string" && v2.trim() === "") return true;
341
+ return Array.isArray(v2) && v2.length === 0;
342
+ }
343
+ function matchesFilters(raw, filters) {
344
+ if (!filters) return true;
345
+ for (const key of Object.keys(filters)) {
346
+ if (key === "search" || key === "subject" || key === "searchAll" || key === "searchOnly") {
347
+ continue;
348
+ }
349
+ const fv = filters[key];
350
+ if (isEmptyFilterValue(fv)) continue;
351
+ const rv = getPath2(raw, key);
352
+ if (Array.isArray(fv)) {
353
+ if (Array.isArray(rv)) {
354
+ const ok = rv.some((x2) => fv.includes(x2));
355
+ if (!ok) return false;
356
+ } else {
357
+ if (!fv.includes(rv)) return false;
358
+ }
359
+ continue;
360
+ }
361
+ if (Array.isArray(rv)) {
362
+ if (!rv.includes(fv)) return false;
363
+ continue;
364
+ }
365
+ if (String(rv) !== String(fv)) return false;
366
+ }
367
+ return true;
368
+ }
369
+ function filterRawListLocal(rawList, query, search, filters, opts) {
370
+ let list = Array.isArray(rawList) ? rawList : [];
371
+ const ctx = { query, search, filters };
372
+ const filtersLocal = (opts == null ? void 0 : opts.filtersSpec) && opts.filtersSpec.local;
373
+ if (typeof filtersLocal === "function") {
374
+ const out = filtersLocal(list, ctx);
375
+ if (Array.isArray(out)) list = out;
376
+ } else {
377
+ list = list.filter(
378
+ (r5) => matchesFilters(r5, filters)
379
+ );
380
+ }
266
381
  const q2 = (query != null ? query : "").trim().toLowerCase();
267
- if (!q2) return options;
268
- return options.filter((o3) => optionText(o3).toLowerCase().includes(q2));
382
+ if (!q2) return list;
383
+ const searchLocal = (opts == null ? void 0 : opts.searchSpec) && opts.searchSpec.local;
384
+ if (typeof searchLocal === "function") {
385
+ const out = searchLocal(list, ctx);
386
+ if (Array.isArray(out)) return out;
387
+ }
388
+ return list.filter((r5) => matchesSearch(r5, q2, search));
269
389
  }
270
390
 
271
391
  // src/presets/lister/engine/selection.ts
@@ -427,7 +547,8 @@ function initialSessionState(sessionId) {
427
547
  filtersPatch: {},
428
548
  effectiveFilters: void 0,
429
549
  // IMPORTANT: these are now OPTION IDS (not db values)
430
- selectedFilterValues: []
550
+ selectedFilterValues: [],
551
+ searchPayload: void 0
431
552
  };
432
553
  }
433
554
  function buildSearchPayloadFromTarget(target) {
@@ -439,7 +560,7 @@ function buildSearchPayloadFromTarget(target) {
439
560
  return subject ? { subject } : void 0;
440
561
  }
441
562
  if (target.mode === "only") {
442
- const only = Array.isArray(target.only) ? target.only.filter(Boolean) : void 0;
563
+ const only = Array.isArray(target.only) ? target.only.filter((v2) => v2 !== null && v2 !== void 0) : void 0;
443
564
  return only && only.length ? { searchOnly: only } : void 0;
444
565
  }
445
566
  return void 0;
@@ -696,16 +817,15 @@ function ListerProvider(props) {
696
817
  );
697
818
  const fetchAndHydrate = React__namespace.useCallback(
698
819
  async (id, reason, override) => {
699
- var _a2, _b2, _c2, _d, _e, _f, _g, _h;
820
+ var _a2, _b2, _c2, _d, _e, _f, _g;
700
821
  const s0 = getSession(id);
701
822
  if (!(s0 == null ? void 0 : s0.definition)) return;
702
823
  const myReq = ((_a2 = reqIdBySessionRef.current[id]) != null ? _a2 : 0) + 1;
703
824
  reqIdBySessionRef.current[id] = myReq;
704
825
  const query = (_b2 = override == null ? void 0 : override.query) != null ? _b2 : s0.query;
705
826
  const filters = (_d = (_c2 = override == null ? void 0 : override.filters) != null ? _c2 : s0.effectiveFilters) != null ? _d : s0.filters;
706
- const search = (_f = override == null ? void 0 : override.search) != null ? _f : buildSearchPayloadFromTarget(
707
- (_e = getSession(id)) == null ? void 0 : _e.searchTarget
708
- );
827
+ const hasSearchOverride = !!override && Object.prototype.hasOwnProperty.call(override, "search");
828
+ const search = hasSearchOverride ? override.search : (_e = s0.searchPayload) != null ? _e : buildSearchPayloadFromTarget(s0.searchTarget);
709
829
  patchSession(id, {
710
830
  errorCode: void 0,
711
831
  loading: reason !== "refresh",
@@ -738,7 +858,7 @@ function ListerProvider(props) {
738
858
  details: {
739
859
  sessionId: id,
740
860
  kind: s3 == null ? void 0 : s3.kind,
741
- endpoint: (_h = (_g = s3 == null ? void 0 : s3.definition) == null ? void 0 : _g.source) == null ? void 0 : _h.endpoint,
861
+ endpoint: (_g = (_f = s3 == null ? void 0 : s3.definition) == null ? void 0 : _f.source) == null ? void 0 : _g.endpoint,
742
862
  query,
743
863
  filters,
744
864
  search
@@ -792,7 +912,7 @@ function ListerProvider(props) {
792
912
  nextPatch,
793
913
  spec
794
914
  );
795
- shouldFetch = (spec == null ? void 0 : spec.autoFetch) !== false;
915
+ shouldFetch = (spec == null ? void 0 : spec.autoFetch) !== false && s4.searchMode !== "local";
796
916
  return {
797
917
  ...s4,
798
918
  filtersPatch: nextPatch,
@@ -881,7 +1001,7 @@ function ListerProvider(props) {
881
1001
  );
882
1002
  const apiOpenAny = React__namespace.useCallback(
883
1003
  async (kindOrDef, filters, opts) => {
884
- var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i;
1004
+ var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k, _l;
885
1005
  const mode = (_a2 = opts == null ? void 0 : opts.mode) != null ? _a2 : "single";
886
1006
  try {
887
1007
  const def = typeof kindOrDef === "string" ? getPreset(kindOrDef) : kindOrDef;
@@ -904,7 +1024,8 @@ function ListerProvider(props) {
904
1024
  const pos = anchorToPos(opts == null ? void 0 : opts.anchor);
905
1025
  const filtersSpec = (_d = opts == null ? void 0 : opts.filtersSpec) != null ? _d : prev == null ? void 0 : prev.filtersSpec;
906
1026
  const filtersPatch = (_e = prev == null ? void 0 : prev.filtersPatch) != null ? _e : {};
907
- const selectedFilterValues = (_f = prev == null ? void 0 : prev.selectedFilterValues) != null ? _f : [];
1027
+ const resolvedSearchMode = (_g = (_f = opts == null ? void 0 : opts.searchMode) != null ? _f : prev == null ? void 0 : prev.searchMode) != null ? _g : "remote";
1028
+ const selectedFilterValues = (_h = prev == null ? void 0 : prev.selectedFilterValues) != null ? _h : [];
908
1029
  const effectiveFilters = computeEffectiveFilters(
909
1030
  filters,
910
1031
  filtersPatch,
@@ -912,10 +1033,10 @@ function ListerProvider(props) {
912
1033
  );
913
1034
  const searchSpec = def == null ? void 0 : def.search;
914
1035
  const defaultCol = searchSpec == null ? void 0 : searchSpec.default;
915
- const defaultSearchTarget = defaultCol ? { mode: "subject", subject: defaultCol, only: null } : void 0;
916
- const searchTarget = (_g = prev == null ? void 0 : prev.searchTarget) != null ? _g : defaultSearchTarget;
917
- const initialQuery = (_i = (_h = opts == null ? void 0 : opts.initialQuery) != null ? _h : prev == null ? void 0 : prev.query) != null ? _i : "";
918
- const searchPayload = buildSearchPayloadFromTarget(searchTarget);
1036
+ const defaultSearchTarget2 = defaultCol ? { mode: "subject", subject: defaultCol, only: null } : void 0;
1037
+ const searchTarget = (_i = prev == null ? void 0 : prev.searchTarget) != null ? _i : defaultSearchTarget2;
1038
+ const initialQuery = (_k = (_j = opts == null ? void 0 : opts.initialQuery) != null ? _j : prev == null ? void 0 : prev.query) != null ? _k : "";
1039
+ const searchPayload = (_l = prev == null ? void 0 : prev.searchPayload) != null ? _l : buildSearchPayloadFromTarget(searchTarget);
919
1040
  const { rawList, optionsList } = await performFetch(
920
1041
  def,
921
1042
  effectiveFilters,
@@ -923,7 +1044,7 @@ function ListerProvider(props) {
923
1044
  );
924
1045
  return await new Promise(
925
1046
  (resolve) => {
926
- var _a3, _b3, _c3, _d2;
1047
+ var _a3, _b3, _c3;
927
1048
  const base = initialSessionState(sessionId);
928
1049
  const nextSession = {
929
1050
  ...prev ? { ...prev } : base,
@@ -939,12 +1060,12 @@ function ListerProvider(props) {
939
1060
  draggable: (_a3 = opts == null ? void 0 : opts.draggable) != null ? _a3 : true,
940
1061
  position: pos,
941
1062
  hasMoved: false,
942
- searchMode: (_b3 = opts == null ? void 0 : opts.searchMode) != null ? _b3 : "remote",
1063
+ searchMode: resolvedSearchMode,
943
1064
  query: initialQuery,
944
1065
  searchSpec,
945
1066
  searchTarget,
946
- showRefresh: (_c3 = opts == null ? void 0 : opts.showRefresh) != null ? _c3 : false,
947
- refreshMode: (_d2 = opts == null ? void 0 : opts.refreshMode) != null ? _d2 : "preserve-selection",
1067
+ showRefresh: (_b3 = opts == null ? void 0 : opts.showRefresh) != null ? _b3 : false,
1068
+ refreshMode: (_c3 = opts == null ? void 0 : opts.refreshMode) != null ? _c3 : "preserve-selection",
948
1069
  // filters
949
1070
  filtersSpec,
950
1071
  filtersPatch,
@@ -1162,17 +1283,32 @@ function ListerProvider(props) {
1162
1283
  );
1163
1284
  const setSearchMode = React__namespace.useCallback(
1164
1285
  (id, mode) => {
1286
+ var _a2;
1287
+ const s3 = getSession(id);
1288
+ if (!s3) return;
1289
+ const prevMode = s3.searchMode;
1165
1290
  patchSession(id, { searchMode: mode });
1291
+ if (prevMode === mode) return;
1292
+ if (mode === "local") {
1293
+ fetchAndHydrate(id, "refresh", {
1294
+ filters: (_a2 = s3.effectiveFilters) != null ? _a2 : s3.filters,
1295
+ query: "",
1296
+ // base fetch (unsearched)
1297
+ search: void 0
1298
+ // force NO search payload
1299
+ });
1300
+ }
1166
1301
  },
1167
- [patchSession]
1302
+ [fetchAndHydrate, getSession, patchSession]
1168
1303
  );
1169
1304
  const scheduleRemoteFetch = React__namespace.useCallback(
1170
1305
  (id, q2, payloadOverride) => {
1171
1306
  if (timerBySessionRef.current[id])
1172
1307
  clearTimeout(timerBySessionRef.current[id]);
1173
1308
  timerBySessionRef.current[id] = setTimeout(() => {
1309
+ var _a2;
1174
1310
  const s3 = getSession(id);
1175
- const search = payloadOverride != null ? payloadOverride : buildSearchPayloadFromTarget(s3 == null ? void 0 : s3.searchTarget);
1311
+ const search = (_a2 = payloadOverride != null ? payloadOverride : s3 == null ? void 0 : s3.searchPayload) != null ? _a2 : buildSearchPayloadFromTarget(s3 == null ? void 0 : s3.searchTarget);
1176
1312
  fetchAndHydrate(id, "search", { query: q2, search });
1177
1313
  }, debounceMs);
1178
1314
  },
@@ -1181,7 +1317,10 @@ function ListerProvider(props) {
1181
1317
  const setSearchTarget = React__namespace.useCallback(
1182
1318
  (id, target) => {
1183
1319
  var _a2, _b2;
1184
- patchSession(id, { searchTarget: target });
1320
+ patchSession(id, {
1321
+ searchTarget: target,
1322
+ searchPayload: void 0
1323
+ });
1185
1324
  const s3 = getSession(id);
1186
1325
  const mode = (_a2 = s3 == null ? void 0 : s3.searchMode) != null ? _a2 : "remote";
1187
1326
  const q2 = (_b2 = s3 == null ? void 0 : s3.query) != null ? _b2 : "";
@@ -1193,7 +1332,7 @@ function ListerProvider(props) {
1193
1332
  );
1194
1333
  const searchLocalImpl = React__namespace.useCallback(
1195
1334
  (id, q2, payload) => {
1196
- patchSession(id, { query: q2 });
1335
+ patchSession(id, { query: q2, searchPayload: payload });
1197
1336
  const s3 = getSession(id);
1198
1337
  if (!s3) return;
1199
1338
  if (s3.searchMode === "hybrid") {
@@ -1204,7 +1343,7 @@ function ListerProvider(props) {
1204
1343
  );
1205
1344
  const searchRemoteImpl = React__namespace.useCallback(
1206
1345
  (id, q2, payload) => {
1207
- patchSession(id, { query: q2 });
1346
+ patchSession(id, { query: q2, searchPayload: payload });
1208
1347
  scheduleRemoteFetch(id, q2, payload);
1209
1348
  },
1210
1349
  [patchSession, scheduleRemoteFetch]
@@ -1232,13 +1371,30 @@ function ListerProvider(props) {
1232
1371
  );
1233
1372
  const getVisibleOptions = React__namespace.useCallback(
1234
1373
  (id) => {
1374
+ var _a2, _b2, _c2, _d;
1235
1375
  const s3 = getSession(id);
1236
1376
  if (!s3) return [];
1237
- if (s3.searchMode === "local")
1238
- return filterOptionsLocal(s3.optionsList, s3.query);
1239
- if (s3.searchMode === "hybrid")
1240
- return filterOptionsLocal(s3.optionsList, s3.query);
1241
- return s3.optionsList;
1377
+ if (s3.searchMode === "remote") return s3.optionsList;
1378
+ const def = s3.definition;
1379
+ if (!def) return [];
1380
+ const filters = (_a2 = s3.effectiveFilters) != null ? _a2 : s3.filters;
1381
+ const payload = (_b2 = s3.searchPayload) != null ? _b2 : buildSearchPayloadFromTarget(s3 == null ? void 0 : s3.searchTarget);
1382
+ const visibleRaw = filterRawListLocal(
1383
+ (_c2 = s3.rawList) != null ? _c2 : [],
1384
+ s3.query,
1385
+ payload,
1386
+ filters,
1387
+ {
1388
+ searchSpec: (_d = s3.searchSpec) != null ? _d : def.search,
1389
+ filtersSpec: s3.filtersSpec
1390
+ }
1391
+ );
1392
+ const mapCtx = { query: s3.query, filters };
1393
+ return mapOptions(
1394
+ visibleRaw,
1395
+ def.mapping,
1396
+ mapCtx
1397
+ );
1242
1398
  },
1243
1399
  [getSession]
1244
1400
  );
@@ -1303,50 +1459,6 @@ function ListerProvider(props) {
1303
1459
  );
1304
1460
  return /* @__PURE__ */ jsxRuntime.jsx(Ctx.Provider, { value, children: props.children });
1305
1461
  }
1306
- function useLister() {
1307
- const ctx = React__namespace.useContext(Ctx);
1308
- if (!ctx)
1309
- throw new Error("useLister must be used within <ListerProvider />");
1310
- const api = React__namespace.useMemo(() => {
1311
- const fetch = ((kindOrDef, filters, opts) => ctx.apiFetchAny(kindOrDef, filters, opts));
1312
- const open = ((kindOrDef, filters, opts) => ctx.apiOpenAny(kindOrDef, filters, opts));
1313
- return {
1314
- fetch,
1315
- open,
1316
- registerPreset: (kind, def) => ctx.registerPreset(kind, def),
1317
- getPreset: (kind) => ctx.getPreset(kind)
1318
- };
1319
- }, [ctx]);
1320
- const active = ctx.store.activeId ? ctx.store.sessions[ctx.store.activeId] : void 0;
1321
- return {
1322
- api,
1323
- store: ctx.store,
1324
- state: active,
1325
- actions: {
1326
- focus: ctx.focus,
1327
- dispose: ctx.dispose,
1328
- apply: ctx.apply,
1329
- cancel: ctx.cancel,
1330
- close: ctx.close,
1331
- toggle: ctx.toggle,
1332
- select: ctx.select,
1333
- deselect: ctx.deselect,
1334
- clear: ctx.clear,
1335
- setQuery: ctx.setQuery,
1336
- setSearchMode: ctx.setSearchMode,
1337
- setSearchTarget: ctx.setSearchTarget,
1338
- searchLocal: ctx.searchLocal,
1339
- searchRemote: ctx.searchRemote,
1340
- refresh: ctx.refresh,
1341
- setPosition: ctx.setPosition,
1342
- getFilterCtx: ctx.getFilterCtx,
1343
- applyFilterOption: ctx.applyFilterOption,
1344
- registerPreset: ctx.registerPreset,
1345
- getPreset: ctx.getPreset,
1346
- getVisibleOptions: ctx.getVisibleOptions
1347
- }
1348
- };
1349
- }
1350
1462
 
1351
1463
  // ../../node_modules/clsx/dist/clsx.mjs
1352
1464
  function r(e4) {
@@ -26008,7 +26120,7 @@ function SearchBar(props) {
26008
26120
  {
26009
26121
  variant: "select",
26010
26122
  mode: "button",
26011
- value: searchMode,
26123
+ defaultValue: searchMode,
26012
26124
  triggerClassName: "border-none ring-0 shadow-none! px-1! cursor-pointer",
26013
26125
  options: [
26014
26126
  {
@@ -26285,6 +26397,429 @@ function FooterBar(props) {
26285
26397
  }
26286
26398
  );
26287
26399
  }
26400
+ function useLister() {
26401
+ const ctx = React__namespace.useContext(Ctx);
26402
+ if (!ctx)
26403
+ throw new Error("useLister must be used within <ListerProvider />");
26404
+ const api = React__namespace.useMemo(() => {
26405
+ const fetch = ((kindOrDef, filters, opts) => ctx.apiFetchAny(kindOrDef, filters, opts));
26406
+ const open = ((kindOrDef, filters, opts) => ctx.apiOpenAny(kindOrDef, filters, opts));
26407
+ return {
26408
+ fetch,
26409
+ open,
26410
+ registerPreset: (kind, def) => ctx.registerPreset(kind, def),
26411
+ getPreset: (kind) => ctx.getPreset(kind)
26412
+ };
26413
+ }, [ctx]);
26414
+ const active = ctx.store.activeId ? ctx.store.sessions[ctx.store.activeId] : void 0;
26415
+ return {
26416
+ api,
26417
+ store: ctx.store,
26418
+ state: active,
26419
+ actions: {
26420
+ focus: ctx.focus,
26421
+ dispose: ctx.dispose,
26422
+ apply: ctx.apply,
26423
+ cancel: ctx.cancel,
26424
+ close: ctx.close,
26425
+ toggle: ctx.toggle,
26426
+ select: ctx.select,
26427
+ deselect: ctx.deselect,
26428
+ clear: ctx.clear,
26429
+ setQuery: ctx.setQuery,
26430
+ setSearchMode: ctx.setSearchMode,
26431
+ setSearchTarget: ctx.setSearchTarget,
26432
+ searchLocal: ctx.searchLocal,
26433
+ searchRemote: ctx.searchRemote,
26434
+ refresh: ctx.refresh,
26435
+ setPosition: ctx.setPosition,
26436
+ getFilterCtx: ctx.getFilterCtx,
26437
+ applyFilterOption: ctx.applyFilterOption,
26438
+ registerPreset: ctx.registerPreset,
26439
+ getPreset: ctx.getPreset,
26440
+ getVisibleOptions: ctx.getVisibleOptions
26441
+ }
26442
+ };
26443
+ }
26444
+ function defaultSearchTarget(search) {
26445
+ const def = search == null ? void 0 : search.default;
26446
+ return def ? { mode: "subject", subject: def, only: null } : void 0;
26447
+ }
26448
+ function isKey(x2) {
26449
+ return typeof x2 === "string" || typeof x2 === "number";
26450
+ }
26451
+ function useData(opts) {
26452
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
26453
+ const ctx = React__namespace.useContext(Ctx);
26454
+ if (!ctx) throw new Error("useData must be used within <ListerProvider />");
26455
+ const enabled = (_a = opts.enabled) != null ? _a : true;
26456
+ const debounceMs = (_b = opts.debounceMs) != null ? _b : 300;
26457
+ const [data, setData] = React__namespace.useState(() => {
26458
+ var _a2;
26459
+ return (_a2 = opts.initial) != null ? _a2 : [];
26460
+ });
26461
+ const [loading, setLoading] = React__namespace.useState(false);
26462
+ const [error, setError] = React__namespace.useState(void 0);
26463
+ const [query, _setQuery] = React__namespace.useState("");
26464
+ const [searchMode, _setSearchMode] = React__namespace.useState(
26465
+ (_c = opts.searchMode) != null ? _c : "remote"
26466
+ );
26467
+ const [searchTarget, _setSearchTarget] = React__namespace.useState(() => defaultSearchTarget(opts.search));
26468
+ const [filters, _setFilters] = React__namespace.useState(
26469
+ opts.filters
26470
+ );
26471
+ const selectionMode = (_e = (_d = opts.selection) == null ? void 0 : _d.mode) != null ? _e : "none";
26472
+ const selectionPrune = (_g = (_f = opts.selection) == null ? void 0 : _f.prune) != null ? _g : "never";
26473
+ const getItemKey = React__namespace.useMemo(() => {
26474
+ var _a2;
26475
+ const key = (_a2 = opts.selection) == null ? void 0 : _a2.key;
26476
+ if (!key) {
26477
+ return (item) => {
26478
+ var _a3;
26479
+ const v2 = (_a3 = item == null ? void 0 : item.id) != null ? _a3 : item == null ? void 0 : item.value;
26480
+ return isKey(v2) ? v2 : null;
26481
+ };
26482
+ }
26483
+ if (typeof key === "function") {
26484
+ return (item) => {
26485
+ const v2 = key(item);
26486
+ return isKey(v2) ? v2 : null;
26487
+ };
26488
+ }
26489
+ return (item) => {
26490
+ const v2 = item == null ? void 0 : item[key];
26491
+ return isKey(v2) ? v2 : null;
26492
+ };
26493
+ }, [(_h = opts.selection) == null ? void 0 : _h.key]);
26494
+ const [selectedIdsArr, setSelectedIdsArr] = React__namespace.useState([]);
26495
+ const selectedCacheRef = React__namespace.useRef(/* @__PURE__ */ new Map());
26496
+ const reqIdRef = React__namespace.useRef(0);
26497
+ const timerRef = React__namespace.useRef(null);
26498
+ const didMountRef = React__namespace.useRef(false);
26499
+ const skipNextModeEffectRef = React__namespace.useRef(false);
26500
+ const inlineDef = React__namespace.useMemo(() => {
26501
+ var _a2;
26502
+ return makeInlineDef({
26503
+ id: opts.id,
26504
+ endpoint: opts.endpoint,
26505
+ method: (_a2 = opts.method) != null ? _a2 : "GET",
26506
+ selector: opts.selector,
26507
+ buildRequest: opts.buildRequest,
26508
+ search: opts.search
26509
+ });
26510
+ }, [
26511
+ opts.id,
26512
+ opts.endpoint,
26513
+ opts.method,
26514
+ opts.selector,
26515
+ opts.buildRequest,
26516
+ opts.search
26517
+ ]);
26518
+ const dataById = React__namespace.useMemo(() => {
26519
+ const map = /* @__PURE__ */ new Map();
26520
+ if (selectionMode === "none") return map;
26521
+ for (const item of data) {
26522
+ const k2 = getItemKey(item);
26523
+ if (k2 == null) continue;
26524
+ map.set(k2, item);
26525
+ }
26526
+ return map;
26527
+ }, [data, getItemKey, selectionMode]);
26528
+ const normalizeIds = React__namespace.useCallback((v2) => {
26529
+ return Array.isArray(v2) ? v2 : [v2];
26530
+ }, []);
26531
+ const commitSelectedCache = React__namespace.useCallback(
26532
+ (list) => {
26533
+ if (selectionMode === "none") return;
26534
+ for (const item of list) {
26535
+ const k2 = getItemKey(item);
26536
+ if (k2 == null) continue;
26537
+ selectedCacheRef.current.set(k2, item);
26538
+ }
26539
+ },
26540
+ [getItemKey, selectionMode]
26541
+ );
26542
+ const fetchImpl = React__namespace.useCallback(
26543
+ async (override) => {
26544
+ var _a2, _b2, _c2, _d2, _e2, _f2;
26545
+ if (!enabled) return data;
26546
+ const q2 = (_a2 = override == null ? void 0 : override.query) != null ? _a2 : query;
26547
+ const f2 = (_b2 = override == null ? void 0 : override.filters) != null ? _b2 : filters;
26548
+ const t4 = (_c2 = override == null ? void 0 : override.searchTarget) != null ? _c2 : searchTarget;
26549
+ const myReq = ++reqIdRef.current;
26550
+ setLoading(true);
26551
+ setError(void 0);
26552
+ try {
26553
+ const payload = (_d2 = override == null ? void 0 : override.search) != null ? _d2 : buildSearchPayloadFromTarget(t4);
26554
+ const res = await ctx.apiFetchAny(inlineDef, f2, {
26555
+ query: q2,
26556
+ search: payload
26557
+ });
26558
+ const list = (_f2 = (_e2 = res == null ? void 0 : res.rawList) != null ? _e2 : res == null ? void 0 : res.raw) != null ? _f2 : [];
26559
+ commitSelectedCache(list);
26560
+ if (selectionMode !== "none" && selectionPrune === "missing") {
26561
+ const nextIds = /* @__PURE__ */ new Set();
26562
+ for (const item of list) {
26563
+ const k2 = getItemKey(item);
26564
+ if (k2 != null) nextIds.add(k2);
26565
+ }
26566
+ setSelectedIdsArr(
26567
+ (prev) => prev.filter((x2) => nextIds.has(x2))
26568
+ );
26569
+ }
26570
+ if (reqIdRef.current !== myReq) return list;
26571
+ setData(list);
26572
+ setLoading(false);
26573
+ return list;
26574
+ } catch (e4) {
26575
+ if (reqIdRef.current !== myReq) return data;
26576
+ setError(e4);
26577
+ setLoading(false);
26578
+ return data;
26579
+ }
26580
+ },
26581
+ [
26582
+ commitSelectedCache,
26583
+ ctx,
26584
+ data,
26585
+ enabled,
26586
+ filters,
26587
+ getItemKey,
26588
+ inlineDef,
26589
+ query,
26590
+ searchTarget,
26591
+ selectionMode,
26592
+ selectionPrune
26593
+ ]
26594
+ );
26595
+ const refresh = React__namespace.useCallback(() => {
26596
+ void fetchImpl();
26597
+ }, [fetchImpl]);
26598
+ const setQuery = React__namespace.useCallback((q2) => _setQuery(q2), []);
26599
+ const setSearchMode = React__namespace.useCallback(
26600
+ (m2) => {
26601
+ if (timerRef.current) clearTimeout(timerRef.current);
26602
+ if (m2 === "remote" || m2 === "hybrid") {
26603
+ skipNextModeEffectRef.current = true;
26604
+ _setSearchMode(m2);
26605
+ void fetchImpl();
26606
+ return;
26607
+ }
26608
+ _setSearchMode(m2);
26609
+ if (m2 === "local") {
26610
+ void fetchImpl({
26611
+ query: "",
26612
+ search: void 0
26613
+ });
26614
+ }
26615
+ },
26616
+ [fetchImpl]
26617
+ );
26618
+ const setSearchTarget = React__namespace.useCallback(
26619
+ (t4) => {
26620
+ _setSearchTarget(t4);
26621
+ if (searchMode === "remote" || searchMode === "hybrid") {
26622
+ if (timerRef.current) clearTimeout(timerRef.current);
26623
+ timerRef.current = setTimeout(() => {
26624
+ void fetchImpl({ searchTarget: t4 });
26625
+ }, debounceMs);
26626
+ }
26627
+ },
26628
+ [debounceMs, fetchImpl, searchMode]
26629
+ );
26630
+ const setFilters = React__namespace.useCallback(
26631
+ (next) => _setFilters(next),
26632
+ []
26633
+ );
26634
+ const patchFilters = React__namespace.useCallback((patch) => {
26635
+ _setFilters((prev) => ({
26636
+ ...prev != null ? prev : {},
26637
+ ...patch
26638
+ }));
26639
+ }, []);
26640
+ const clearFilters = React__namespace.useCallback(() => _setFilters(void 0), []);
26641
+ const fetchOnMount = (_i = opts.fetchOnMount) != null ? _i : !opts.initial;
26642
+ React__namespace.useEffect(() => {
26643
+ if (!enabled) return;
26644
+ if (!fetchOnMount) return;
26645
+ void fetchImpl();
26646
+ }, []);
26647
+ React__namespace.useEffect(() => {
26648
+ if (!enabled) return;
26649
+ if (!didMountRef.current) {
26650
+ didMountRef.current = true;
26651
+ return;
26652
+ }
26653
+ if (searchMode !== "remote" && searchMode !== "hybrid") return;
26654
+ if (skipNextModeEffectRef.current) {
26655
+ skipNextModeEffectRef.current = false;
26656
+ return;
26657
+ }
26658
+ if (timerRef.current) clearTimeout(timerRef.current);
26659
+ timerRef.current = setTimeout(() => {
26660
+ void fetchImpl();
26661
+ }, debounceMs);
26662
+ return () => {
26663
+ if (timerRef.current) clearTimeout(timerRef.current);
26664
+ };
26665
+ }, [debounceMs, enabled, fetchImpl, query, searchMode, searchTarget]);
26666
+ React__namespace.useEffect(() => {
26667
+ if (!enabled) return;
26668
+ if (opts.autoFetchOnFilterChange === false) return;
26669
+ if (!didMountRef.current) return;
26670
+ if (searchMode !== "remote" && searchMode !== "hybrid") return;
26671
+ void fetchImpl();
26672
+ }, [enabled, fetchImpl, filters, opts.autoFetchOnFilterChange, searchMode]);
26673
+ const visible = React__namespace.useMemo(() => {
26674
+ if (searchMode !== "local" && searchMode !== "hybrid") return data;
26675
+ const payload = buildSearchPayloadFromTarget(searchTarget);
26676
+ let list = data;
26677
+ if ((payload == null ? void 0 : payload.searchOnly) && payload.searchOnly.length) {
26678
+ const allow = new Set(payload.searchOnly);
26679
+ list = list.filter((item) => {
26680
+ const k2 = getItemKey(item);
26681
+ return k2 != null && allow.has(k2);
26682
+ });
26683
+ }
26684
+ const q2 = query.trim();
26685
+ if (!q2) return list;
26686
+ const ql = q2.toLowerCase();
26687
+ if (payload == null ? void 0 : payload.subject) {
26688
+ const key = payload.subject;
26689
+ return list.filter(
26690
+ (item) => {
26691
+ var _a2;
26692
+ return String((_a2 = item == null ? void 0 : item[key]) != null ? _a2 : "").toLowerCase().includes(ql);
26693
+ }
26694
+ );
26695
+ }
26696
+ return list.filter(
26697
+ (item) => String(item != null ? item : "").toLowerCase().includes(ql)
26698
+ );
26699
+ }, [data, getItemKey, query, searchMode, searchTarget]);
26700
+ const selectedIds = React__namespace.useMemo(() => {
26701
+ var _a2;
26702
+ if (selectionMode === "none") return null;
26703
+ if (selectionMode === "single") return (_a2 = selectedIdsArr[0]) != null ? _a2 : null;
26704
+ return selectedIdsArr;
26705
+ }, [selectionMode, selectedIdsArr]);
26706
+ const isSelected = React__namespace.useCallback(
26707
+ (id) => {
26708
+ if (selectionMode === "none") return false;
26709
+ return selectedIdsArr.includes(id);
26710
+ },
26711
+ [selectedIdsArr, selectionMode]
26712
+ );
26713
+ const clearSelection = React__namespace.useCallback(() => {
26714
+ if (selectionMode === "none") return;
26715
+ setSelectedIdsArr([]);
26716
+ }, [selectionMode]);
26717
+ const select = React__namespace.useCallback(
26718
+ (idOrIds) => {
26719
+ if (selectionMode === "none") return;
26720
+ const ids = normalizeIds(idOrIds).filter(isKey);
26721
+ if (!ids.length) return;
26722
+ for (const id of ids) {
26723
+ const hit = dataById.get(id);
26724
+ if (hit) selectedCacheRef.current.set(id, hit);
26725
+ }
26726
+ if (selectionMode === "single") {
26727
+ setSelectedIdsArr([ids[0]]);
26728
+ return;
26729
+ }
26730
+ setSelectedIdsArr((prev) => {
26731
+ const set = new Set(prev);
26732
+ for (const id of ids) set.add(id);
26733
+ return Array.from(set);
26734
+ });
26735
+ },
26736
+ [dataById, normalizeIds, selectionMode]
26737
+ );
26738
+ const deselect = React__namespace.useCallback(
26739
+ (idOrIds) => {
26740
+ if (selectionMode === "none") return;
26741
+ const ids = new Set(normalizeIds(idOrIds).filter(isKey));
26742
+ if (!ids.size) return;
26743
+ setSelectedIdsArr((prev) => {
26744
+ const next = prev.filter((x2) => !ids.has(x2));
26745
+ if (selectionMode === "single") return next.slice(0, 1);
26746
+ return next;
26747
+ });
26748
+ },
26749
+ [normalizeIds, selectionMode]
26750
+ );
26751
+ const toggle = React__namespace.useCallback(
26752
+ (id) => {
26753
+ if (selectionMode === "none") return;
26754
+ const hit = dataById.get(id);
26755
+ if (hit) selectedCacheRef.current.set(id, hit);
26756
+ if (selectionMode === "single") {
26757
+ setSelectedIdsArr((prev) => prev[0] === id ? [] : [id]);
26758
+ return;
26759
+ }
26760
+ setSelectedIdsArr((prev) => {
26761
+ const set = new Set(prev);
26762
+ if (set.has(id)) set.delete(id);
26763
+ else set.add(id);
26764
+ return Array.from(set);
26765
+ });
26766
+ },
26767
+ [dataById, selectionMode]
26768
+ );
26769
+ const selected = React__namespace.useMemo(() => {
26770
+ var _a2, _b2, _c2, _d2;
26771
+ if (selectionMode === "none") return null;
26772
+ if (selectionMode === "single") {
26773
+ const id = selectedIdsArr[0];
26774
+ if (id == null) return null;
26775
+ return (_b2 = (_a2 = dataById.get(id)) != null ? _a2 : selectedCacheRef.current.get(id)) != null ? _b2 : null;
26776
+ }
26777
+ const out = [];
26778
+ for (const id of selectedIdsArr) {
26779
+ const item = (_d2 = (_c2 = dataById.get(id)) != null ? _c2 : selectedCacheRef.current.get(id)) != null ? _d2 : null;
26780
+ if (item) out.push(item);
26781
+ }
26782
+ return out;
26783
+ }, [dataById, selectedIdsArr, selectionMode]);
26784
+ const getSelection = React__namespace.useCallback(() => selected, [selected]);
26785
+ React__namespace.useEffect(() => {
26786
+ if (selectionMode === "none") {
26787
+ setSelectedIdsArr([]);
26788
+ return;
26789
+ }
26790
+ if (selectionMode === "single") {
26791
+ setSelectedIdsArr((prev) => prev.length ? [prev[0]] : []);
26792
+ }
26793
+ }, [selectionMode]);
26794
+ return {
26795
+ id: opts.id,
26796
+ data,
26797
+ visible,
26798
+ loading,
26799
+ error,
26800
+ query,
26801
+ setQuery,
26802
+ searchMode,
26803
+ setSearchMode,
26804
+ searchTarget,
26805
+ setSearchTarget,
26806
+ filters,
26807
+ setFilters,
26808
+ patchFilters,
26809
+ clearFilters,
26810
+ selectionMode,
26811
+ selectedIds,
26812
+ selected,
26813
+ select,
26814
+ deselect,
26815
+ toggle,
26816
+ clearSelection,
26817
+ isSelected,
26818
+ getSelection,
26819
+ refresh,
26820
+ fetch: fetchImpl
26821
+ };
26822
+ }
26288
26823
  /*! Bundled license information:
26289
26824
 
26290
26825
  lucide-react/dist/esm/shared/src/utils.js:
@@ -26335,6 +26870,7 @@ lucide-react/dist/esm/lucide-react.js:
26335
26870
  *)
26336
26871
  */
26337
26872
 
26873
+ exports.Ctx = Ctx;
26338
26874
  exports.FooterBar = FooterBar;
26339
26875
  exports.HeaderBar = HeaderBar;
26340
26876
  exports.JsonEditor = json_editor_default;
@@ -26342,6 +26878,8 @@ exports.ListerProvider = ListerProvider;
26342
26878
  exports.ListerUI = ListerUI;
26343
26879
  exports.OptionList = OptionList;
26344
26880
  exports.SearchBar = SearchBar;
26881
+ exports.buildSearchPayloadFromTarget = buildSearchPayloadFromTarget;
26882
+ exports.useData = useData;
26345
26883
  exports.useLister = useLister;
26346
26884
  //# sourceMappingURL=extra.js.map
26347
26885
  //# sourceMappingURL=extra.js.map