@ai-matrx/records-ui 0.3.2 → 0.5.4

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.d.cts CHANGED
@@ -521,8 +521,16 @@ declare function ViewBar({ tableId, activeViewId, onActiveView, seed, className
521
521
  interface ProposedChange {
522
522
  id: string;
523
523
  act: "add" | "update" | "remove";
524
- /** The Table the change lands in. */
525
- table: Uuid;
524
+ /**
525
+ * The Table a NEW record lands in. Required for `add` and unused by `update`
526
+ * and `remove`, which name a record instead — and it is optional for exactly
527
+ * that reason: it used to be required for all three, so a proposer wanting to
528
+ * change an existing record had to supply the id of the kernel Table that
529
+ * record lives in, which is a fact the client has no door to ask for. A
530
+ * required field a caller cannot fill is a field that gets filled with
531
+ * something untrue.
532
+ */
533
+ table?: Uuid | undefined;
526
534
  /** The record it changes. Required for `update` and `remove`. */
527
535
  record?: Uuid | undefined;
528
536
  /** The document for `add`, or the patch for `update`. */
@@ -1087,9 +1095,16 @@ interface TablePageProps {
1087
1095
  tableId: Uuid$1;
1088
1096
  /** Rows per page for every layout. */
1089
1097
  pageSize?: number | undefined;
1098
+ /**
1099
+ * The views this table should have. Each one whose NAME the table does not
1100
+ * hold yet is saved the first time the bar loads, and a name a person has
1101
+ * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is
1102
+ * used — see why that default is not optional.
1103
+ */
1104
+ seedViews?: SavedViewSpec[] | undefined;
1090
1105
  className?: string | undefined;
1091
1106
  }
1092
- declare function TablePage({ tableId, pageSize, className }: TablePageProps): react.JSX.Element;
1107
+ declare function TablePage({ tableId, pageSize, seedViews, className }: TablePageProps): react.JSX.Element;
1093
1108
 
1094
1109
  /** One Field a person asked for, in the store's own behaviour words (FLD-1). */
1095
1110
  interface NewFieldSpec {
package/dist/index.d.ts CHANGED
@@ -521,8 +521,16 @@ declare function ViewBar({ tableId, activeViewId, onActiveView, seed, className
521
521
  interface ProposedChange {
522
522
  id: string;
523
523
  act: "add" | "update" | "remove";
524
- /** The Table the change lands in. */
525
- table: Uuid;
524
+ /**
525
+ * The Table a NEW record lands in. Required for `add` and unused by `update`
526
+ * and `remove`, which name a record instead — and it is optional for exactly
527
+ * that reason: it used to be required for all three, so a proposer wanting to
528
+ * change an existing record had to supply the id of the kernel Table that
529
+ * record lives in, which is a fact the client has no door to ask for. A
530
+ * required field a caller cannot fill is a field that gets filled with
531
+ * something untrue.
532
+ */
533
+ table?: Uuid | undefined;
526
534
  /** The record it changes. Required for `update` and `remove`. */
527
535
  record?: Uuid | undefined;
528
536
  /** The document for `add`, or the patch for `update`. */
@@ -1087,9 +1095,16 @@ interface TablePageProps {
1087
1095
  tableId: Uuid$1;
1088
1096
  /** Rows per page for every layout. */
1089
1097
  pageSize?: number | undefined;
1098
+ /**
1099
+ * The views this table should have. Each one whose NAME the table does not
1100
+ * hold yet is saved the first time the bar loads, and a name a person has
1101
+ * since tweaked is never overwritten. Left out, `DEFAULT_VIEW_NAME` below is
1102
+ * used — see why that default is not optional.
1103
+ */
1104
+ seedViews?: SavedViewSpec[] | undefined;
1090
1105
  className?: string | undefined;
1091
1106
  }
1092
- declare function TablePage({ tableId, pageSize, className }: TablePageProps): react.JSX.Element;
1107
+ declare function TablePage({ tableId, pageSize, seedViews, className }: TablePageProps): react.JSX.Element;
1093
1108
 
1094
1109
  /** One Field a person asked for, in the store's own behaviour words (FLD-1). */
1095
1110
  interface NewFieldSpec {
package/dist/index.js CHANGED
@@ -872,17 +872,18 @@ async function ensureSystemTable(client, spec) {
872
872
  if (found) {
873
873
  const grown = await addMissingFields(client, spec, found.id);
874
874
  if (!grown.ok) return grown;
875
+ const levelled = await reconcileFieldShapes(client, spec, found.id);
876
+ if (!levelled.ok) return levelled;
875
877
  return { ok: true, data: found.id };
876
878
  }
877
879
  let settle = () => void 0;
878
880
  let fail = () => void 0;
879
- inFlight.set(
880
- cacheKey,
881
- new Promise((resolve, reject) => {
882
- settle = resolve;
883
- fail = reject;
884
- })
885
- );
881
+ const pending = new Promise((resolve, reject) => {
882
+ settle = resolve;
883
+ fail = reject;
884
+ });
885
+ pending.catch(() => void 0);
886
+ inFlight.set(cacheKey, pending);
886
887
  const declared = await declare(client, spec);
887
888
  if (declared.ok) settle(declared.data);
888
889
  else {
@@ -911,6 +912,22 @@ async function addMissingFields(client, spec, tableId) {
911
912
  }
912
913
  return { ok: true, data: true };
913
914
  }
915
+ async function reconcileFieldShapes(client, spec, tableId) {
916
+ const held = await client.fields({ table_id: tableId });
917
+ if (!held.ok) return held;
918
+ const byKey = new Map(held.data.map((f) => [f.key, f]));
919
+ for (const field of spec.fields) {
920
+ const have = byKey.get(field.key);
921
+ if (!have) continue;
922
+ const patch = {};
923
+ if (have.type !== field.type) patch.type = field.type;
924
+ if (have.multi !== (field.multi ?? false)) patch.multi = field.multi ?? false;
925
+ if (Object.keys(patch).length === 0) continue;
926
+ const written = await client.recordUpdate({ record_id: have.id, patch });
927
+ if (!written.ok) return written;
928
+ }
929
+ return { ok: true, data: true };
930
+ }
914
931
  function fieldDocument(field, tableId) {
915
932
  return {
916
933
  key: field.key,
@@ -2097,6 +2114,12 @@ function ProposalRow({
2097
2114
  const [confirming, setConfirming] = useState14(false);
2098
2115
  async function applyThroughTheStore() {
2099
2116
  if (change.act === "add") {
2117
+ if (!change.table) {
2118
+ return {
2119
+ settled: "refused",
2120
+ sentence: "This proposal asks to add a record but does not name the table it goes in, so nothing was written."
2121
+ };
2122
+ }
2100
2123
  const written = await client.recordWrite({ table_id: change.table, data: change.data ?? {} });
2101
2124
  return written.ok ? { settled: "accepted", sentence: "Written." } : { settled: "refused", sentence: written.error.message };
2102
2125
  }
@@ -5814,7 +5837,11 @@ import { useState as useState35 } from "react";
5814
5837
  import { useTable as useTable21 } from "@ai-matrx/records/react";
5815
5838
  import { Button as Button31, Separator as Separator7, Skeleton as Skeleton25, cn as cn36 } from "@ai-matrx/design-system";
5816
5839
  import { Fragment as Fragment8, jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
5817
- function TablePage({ tableId, pageSize = 100, className }) {
5840
+ var DEFAULT_VIEW_NAME = "All records";
5841
+ function defaultView(tableId) {
5842
+ return { name: DEFAULT_VIEW_NAME, subject: tableId, layout: "grid", isDefault: true };
5843
+ }
5844
+ function TablePage({ tableId, pageSize = 100, seedViews, className }) {
5818
5845
  const table = useTable21(tableId);
5819
5846
  const rights = useTableRights(table.data);
5820
5847
  const [view, setView] = useState35(null);
@@ -5826,7 +5853,15 @@ function TablePage({ tableId, pageSize = 100, className }) {
5826
5853
  return /* @__PURE__ */ jsxs35("div", { className: cn36("flex min-h-0 gap-4", className), children: [
5827
5854
  /* @__PURE__ */ jsxs35("div", { className: "flex min-w-0 flex-1 flex-col gap-2", children: [
5828
5855
  /* @__PURE__ */ jsxs35("div", { className: "flex flex-wrap items-center gap-1.5", children: [
5829
- /* @__PURE__ */ jsx38(ViewBar, { tableId, onActiveView: setView, className: "min-w-0 flex-1" }),
5856
+ /* @__PURE__ */ jsx38(
5857
+ ViewBar,
5858
+ {
5859
+ tableId,
5860
+ onActiveView: setView,
5861
+ seed: seedViews ?? [defaultView(tableId)],
5862
+ className: "min-w-0 flex-1"
5863
+ }
5864
+ ),
5830
5865
  rights.write ? /* @__PURE__ */ jsx38(Button31, { size: "sm", onClick: () => show("new-record"), children: "New record" }) : null,
5831
5866
  rights.admin ? /* @__PURE__ */ jsxs35(Fragment8, { children: [
5832
5867
  /* @__PURE__ */ jsx38(Button31, { size: "sm", variant: "outline", onClick: () => show("field"), children: "Add field" }),