@pattern-stack/frontend-patterns 0.2.0-alpha.18 → 0.2.0-alpha.20

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.
Files changed (69) hide show
  1. package/dist/frontend-patterns.css +1 -1
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.es.js +163 -35
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/index.js +163 -35
  7. package/dist/index.js.map +1 -1
  8. package/dist/swebrain/SweBrainShowcase.d.ts +8 -0
  9. package/dist/swebrain/SweBrainShowcase.d.ts.map +1 -0
  10. package/dist/swebrain/atoms/Card.d.ts +15 -0
  11. package/dist/swebrain/atoms/Card.d.ts.map +1 -0
  12. package/dist/swebrain/atoms/Chip.d.ts +17 -0
  13. package/dist/swebrain/atoms/Chip.d.ts.map +1 -0
  14. package/dist/swebrain/atoms/Duration.d.ts +7 -0
  15. package/dist/swebrain/atoms/Duration.d.ts.map +1 -0
  16. package/dist/swebrain/atoms/EmptyCell.d.ts +5 -0
  17. package/dist/swebrain/atoms/EmptyCell.d.ts.map +1 -0
  18. package/dist/swebrain/atoms/Hand.d.ts +8 -0
  19. package/dist/swebrain/atoms/Hand.d.ts.map +1 -0
  20. package/dist/swebrain/atoms/ID.d.ts +9 -0
  21. package/dist/swebrain/atoms/ID.d.ts.map +1 -0
  22. package/dist/swebrain/atoms/IdTag.d.ts +9 -0
  23. package/dist/swebrain/atoms/IdTag.d.ts.map +1 -0
  24. package/dist/swebrain/atoms/KV.d.ts +7 -0
  25. package/dist/swebrain/atoms/KV.d.ts.map +1 -0
  26. package/dist/swebrain/atoms/LiveIndicator.d.ts +7 -0
  27. package/dist/swebrain/atoms/LiveIndicator.d.ts.map +1 -0
  28. package/dist/swebrain/atoms/PoolChip.d.ts +14 -0
  29. package/dist/swebrain/atoms/PoolChip.d.ts.map +1 -0
  30. package/dist/swebrain/atoms/Row.d.ts +10 -0
  31. package/dist/swebrain/atoms/Row.d.ts.map +1 -0
  32. package/dist/swebrain/atoms/Sparkline.d.ts +11 -0
  33. package/dist/swebrain/atoms/Sparkline.d.ts.map +1 -0
  34. package/dist/swebrain/atoms/StatusBadge.d.ts +11 -0
  35. package/dist/swebrain/atoms/StatusBadge.d.ts.map +1 -0
  36. package/dist/swebrain/atoms/StatusDot.d.ts +11 -0
  37. package/dist/swebrain/atoms/StatusDot.d.ts.map +1 -0
  38. package/dist/swebrain/atoms/Timestamp.d.ts +8 -0
  39. package/dist/swebrain/atoms/Timestamp.d.ts.map +1 -0
  40. package/dist/swebrain/atoms/index.d.ts +34 -0
  41. package/dist/swebrain/atoms/index.d.ts.map +1 -0
  42. package/dist/swebrain/atoms/pool-tokens.d.ts +14 -0
  43. package/dist/swebrain/atoms/pool-tokens.d.ts.map +1 -0
  44. package/dist/swebrain/atoms/tokens.d.ts +96 -0
  45. package/dist/swebrain/atoms/tokens.d.ts.map +1 -0
  46. package/dist/swebrain/index.d.ts +4 -0
  47. package/dist/swebrain/index.d.ts.map +1 -0
  48. package/dist/swebrain/lib/favs.d.ts +5 -0
  49. package/dist/swebrain/lib/favs.d.ts.map +1 -0
  50. package/dist/swebrain/lib/vendors.d.ts +14 -0
  51. package/dist/swebrain/lib/vendors.d.ts.map +1 -0
  52. package/dist/swebrain/molecules/PoolLegend.d.ts +8 -0
  53. package/dist/swebrain/molecules/PoolLegend.d.ts.map +1 -0
  54. package/dist/swebrain/molecules/SearchInput.d.ts +17 -0
  55. package/dist/swebrain/molecules/SearchInput.d.ts.map +1 -0
  56. package/dist/swebrain/molecules/StatCard.d.ts +11 -0
  57. package/dist/swebrain/molecules/StatCard.d.ts.map +1 -0
  58. package/dist/swebrain/molecules/TimeRangePicker.d.ts +18 -0
  59. package/dist/swebrain/molecules/TimeRangePicker.d.ts.map +1 -0
  60. package/dist/swebrain/molecules/index.d.ts +9 -0
  61. package/dist/swebrain/molecules/index.d.ts.map +1 -0
  62. package/dist/sync/createEntityHooks.d.ts.map +1 -1
  63. package/dist/sync/createStore.d.ts +78 -15
  64. package/dist/sync/createStore.d.ts.map +1 -1
  65. package/dist/sync/index.d.ts +2 -2
  66. package/dist/sync/index.d.ts.map +1 -1
  67. package/dist/sync/types.d.ts +216 -23
  68. package/dist/sync/types.d.ts.map +1 -1
  69. package/package.json +2 -1
package/dist/index.es.js CHANGED
@@ -19047,20 +19047,50 @@ function createEntityHooks(config) {
19047
19047
  /** Key for a specific entity detail query */
19048
19048
  detail: (id) => [...keys.details(), id]
19049
19049
  };
19050
- function useListSync(filters) {
19050
+ const DEFAULT_PAGE_SIZE = 50;
19051
+ function toPage(raw, requestedPage, requestedPageSize) {
19052
+ if (Array.isArray(raw)) {
19053
+ const items2 = raw;
19054
+ return {
19055
+ items: items2,
19056
+ page: requestedPage,
19057
+ pageCount: 1,
19058
+ total: items2.length,
19059
+ pageSize: requestedPageSize || items2.length || DEFAULT_PAGE_SIZE,
19060
+ nextCursor: null
19061
+ };
19062
+ }
19063
+ const env2 = raw ?? {};
19064
+ const items = Array.isArray(env2.items) ? env2.items : [];
19065
+ const pageSize = typeof env2.pageSize === "number" && env2.pageSize > 0 ? env2.pageSize : requestedPageSize || DEFAULT_PAGE_SIZE;
19066
+ const total = typeof env2.total === "number" ? env2.total : items.length;
19067
+ const pageCount = typeof env2.pageCount === "number" ? env2.pageCount : Math.max(1, Math.ceil(total / Math.max(1, pageSize)));
19068
+ return {
19069
+ items,
19070
+ page: typeof env2.page === "number" ? env2.page : requestedPage,
19071
+ pageCount,
19072
+ total,
19073
+ pageSize,
19074
+ nextCursor: env2.nextCursor ?? null
19075
+ };
19076
+ }
19077
+ function useListSync(params, requestedPage, requestedPageSize) {
19051
19078
  const query = useQuery({
19052
- queryKey: keys.list(filters),
19053
- queryFn: () => api.list(filters),
19079
+ queryKey: keys.list(params),
19080
+ queryFn: () => api.list(params),
19054
19081
  staleTime
19055
19082
  });
19083
+ const pageEnvelope = useMemo(
19084
+ () => query.data === void 0 ? void 0 : toPage(query.data, requestedPage, requestedPageSize),
19085
+ [query.data, requestedPage, requestedPageSize]
19086
+ );
19056
19087
  useEffect(() => {
19057
19088
  var _a, _b;
19058
- if (query.data) {
19059
- const items = Array.isArray(query.data) ? query.data : query.data.items || [];
19060
- (_b = (_a = collection.utils) == null ? void 0 : _a.writeUpsert) == null ? void 0 : _b.call(_a, items);
19089
+ if (pageEnvelope) {
19090
+ (_b = (_a = collection.utils) == null ? void 0 : _a.writeUpsert) == null ? void 0 : _b.call(_a, pageEnvelope.items);
19061
19091
  }
19062
- }, [query.data]);
19063
- return query;
19092
+ }, [pageEnvelope]);
19093
+ return { query, pageEnvelope };
19064
19094
  }
19065
19095
  function useGetSync(id) {
19066
19096
  const query = useQuery({
@@ -19078,41 +19108,71 @@ function createEntityHooks(config) {
19078
19108
  return query;
19079
19109
  }
19080
19110
  function useList(options = {}) {
19081
- const { where, orderBy, enabled = true } = options;
19082
- const sync = useListSync(enabled ? where : void 0);
19111
+ const { where, orderBy, enabled = true, pageSize, cursor } = options;
19112
+ const [page, setPageState] = useState(() => Math.max(1, options.page ?? 1));
19113
+ const params = useMemo(() => {
19114
+ if (!enabled) return void 0;
19115
+ const p = { page };
19116
+ if (pageSize !== void 0) p.pageSize = pageSize;
19117
+ if (cursor !== void 0) p.cursor = cursor;
19118
+ if (orderBy) {
19119
+ p.sort_by = orderBy.field;
19120
+ p.sort_order = orderBy.direction;
19121
+ }
19122
+ if (where) Object.assign(p, where);
19123
+ return p;
19124
+ }, [enabled, page, pageSize, cursor, orderBy, where]);
19125
+ const { query: sync, pageEnvelope } = useListSync(params, page, pageSize ?? DEFAULT_PAGE_SIZE);
19126
+ const pageIds = useMemo(() => {
19127
+ if (!pageEnvelope) return [];
19128
+ return pageEnvelope.items.map((item) => item.id).filter((id) => typeof id === "string");
19129
+ }, [pageEnvelope]);
19083
19130
  const liveResult = useLiveQuery(collection);
19084
19131
  const data = useMemo(() => {
19085
- let items = liveResult.data ?? [];
19086
- if (where) {
19087
- items = items.filter((item) => {
19088
- return Object.entries(where).every(([key, value]) => {
19089
- if (value === void 0) return true;
19090
- const itemValue = item[key];
19091
- if (Array.isArray(value)) {
19092
- return value.includes(itemValue);
19093
- }
19094
- return itemValue === value;
19095
- });
19096
- });
19132
+ var _a, _b;
19133
+ const live = liveResult.data ?? [];
19134
+ const byId = /* @__PURE__ */ new Map();
19135
+ for (const row of live) {
19136
+ const id = row.id;
19137
+ if (typeof id === "string") byId.set(id, row);
19097
19138
  }
19098
- if (orderBy) {
19099
- items = [...items].sort((a, b) => {
19100
- const aVal = a[orderBy.field];
19101
- const bVal = b[orderBy.field];
19102
- if (aVal < bVal) return orderBy.direction === "asc" ? -1 : 1;
19103
- if (aVal > bVal) return orderBy.direction === "asc" ? 1 : -1;
19104
- return 0;
19105
- });
19139
+ const rows = [];
19140
+ for (const id of pageIds) {
19141
+ const row = byId.get(id) ?? // eslint-disable-next-line @typescript-eslint/no-explicit-any
19142
+ ((_b = (_a = collection.state) == null ? void 0 : _a.get) == null ? void 0 : _b.call(_a, id));
19143
+ if (row !== void 0) rows.push(row);
19106
19144
  }
19107
- return items;
19108
- }, [liveResult.data, where, orderBy]);
19145
+ return rows;
19146
+ }, [liveResult.data, pageIds]);
19147
+ const pageCount = (pageEnvelope == null ? void 0 : pageEnvelope.pageCount) ?? 1;
19148
+ const total = (pageEnvelope == null ? void 0 : pageEnvelope.total) ?? data.length;
19149
+ const resolvedPageSize = (pageEnvelope == null ? void 0 : pageEnvelope.pageSize) ?? pageSize ?? DEFAULT_PAGE_SIZE;
19150
+ const currentPage = (pageEnvelope == null ? void 0 : pageEnvelope.page) ?? page;
19151
+ const setPage = useCallback(
19152
+ (next2) => {
19153
+ const clamped = Math.max(1, pageCount > 0 ? Math.min(next2, pageCount) : next2);
19154
+ setPageState(clamped);
19155
+ },
19156
+ [pageCount]
19157
+ );
19158
+ const next = useCallback(() => setPage(page + 1), [setPage, page]);
19159
+ const prev = useCallback(() => setPage(page - 1), [setPage, page]);
19109
19160
  return {
19110
19161
  data,
19111
19162
  isLoading: sync.isLoading || liveResult.isLoading,
19112
19163
  isError: sync.isError,
19113
19164
  error: sync.error,
19114
19165
  refetch: sync.refetch,
19115
- collection
19166
+ collection,
19167
+ page: currentPage,
19168
+ pageCount,
19169
+ total,
19170
+ pageSize: resolvedPageSize,
19171
+ setPage,
19172
+ next,
19173
+ prev,
19174
+ hasNext: currentPage < pageCount,
19175
+ hasPrev: currentPage > 1
19116
19176
  };
19117
19177
  }
19118
19178
  function useGet(id, options = {}) {
@@ -19237,7 +19297,8 @@ function createEntityHooks(config) {
19237
19297
  };
19238
19298
  }
19239
19299
  function createStore(config) {
19240
- const { entities, collections } = config;
19300
+ const { entities, collections, fields, lookups: lookupsEngine } = config;
19301
+ const defaultGetRowId = (row) => String(row.id);
19241
19302
  const resolve = {};
19242
19303
  for (const [name, collection] of Object.entries(collections)) {
19243
19304
  const singular = name.endsWith("ies") ? name.slice(0, -3) + "y" : name.endsWith("s") ? name.slice(0, -1) : name;
@@ -19267,8 +19328,75 @@ function createStore(config) {
19267
19328
  lookupCache = null;
19268
19329
  }
19269
19330
  };
19331
+ function makeUseData(entityName, entity) {
19332
+ const meta = fields ? fields[entityName] : void 0;
19333
+ return function useData(opts = {}) {
19334
+ const { pageSize } = opts;
19335
+ const list = entity.useList({ pageSize });
19336
+ useEffect(() => {
19337
+ if (lookupsEngine) {
19338
+ void lookupsEngine.hydrate().catch(() => {
19339
+ });
19340
+ }
19341
+ }, []);
19342
+ const hydratedLookups = lookupsEngine ? lookupsEngine.current : null;
19343
+ const result = useMemo(
19344
+ () => ({
19345
+ rows: list.data,
19346
+ isLoading: list.isLoading,
19347
+ isError: list.isError,
19348
+ error: list.error,
19349
+ refetch: list.refetch,
19350
+ page: list.page,
19351
+ pageCount: list.pageCount,
19352
+ total: list.total,
19353
+ pageSize: list.pageSize,
19354
+ setPage: list.setPage,
19355
+ next: list.next,
19356
+ prev: list.prev,
19357
+ hasNext: list.hasNext,
19358
+ hasPrev: list.hasPrev,
19359
+ getRowId: defaultGetRowId,
19360
+ meta,
19361
+ lookups: hydratedLookups,
19362
+ // Reserved (inert):
19363
+ sort: null,
19364
+ setSort: () => {
19365
+ },
19366
+ filter: null,
19367
+ setFilter: () => {
19368
+ }
19369
+ }),
19370
+ [
19371
+ list.data,
19372
+ list.isLoading,
19373
+ list.isError,
19374
+ list.error,
19375
+ list.refetch,
19376
+ list.page,
19377
+ list.pageCount,
19378
+ list.total,
19379
+ list.pageSize,
19380
+ list.setPage,
19381
+ list.next,
19382
+ list.prev,
19383
+ list.hasNext,
19384
+ list.hasPrev,
19385
+ hydratedLookups
19386
+ ]
19387
+ );
19388
+ return result;
19389
+ };
19390
+ }
19391
+ const augmentedEntities = {};
19392
+ for (const [name, entity] of Object.entries(entities)) {
19393
+ augmentedEntities[name] = {
19394
+ ...entity,
19395
+ useData: makeUseData(name, entity)
19396
+ };
19397
+ }
19270
19398
  return {
19271
- ...entities,
19399
+ ...augmentedEntities,
19272
19400
  collections,
19273
19401
  resolve,
19274
19402
  lookups