@ai-matrx/records-ui 0.115.38 → 0.115.40

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.js CHANGED
@@ -5503,9 +5503,12 @@ function withheldNoticeOf(hidden, key) {
5503
5503
  return notice && typeof notice === "object" ? notice : null;
5504
5504
  }
5505
5505
  function withheldSentence(field2, notice) {
5506
- const says = notice.says;
5507
- if (typeof says === "string" && says.trim() !== "") return says.trim();
5506
+ const extra = notice;
5507
+ if (typeof extra.says === "string" && extra.says.trim() !== "") return extra.says.trim();
5508
5508
  const name = fieldName(field2);
5509
+ if (typeof extra.part === "string" && extra.part.trim() !== "" && typeof extra.who === "string" && extra.who.trim() !== "") {
5510
+ return `${name} is in ${extra.part.trim()} \u2014 ${extra.who.trim()} see it.`;
5511
+ }
5509
5512
  const reason = notice.reason ? ` It is ${notice.reason}` : "";
5510
5513
  const needs = notice.needs ? `${reason ? "," : " It"} and reading it needs ${notice.needs}` : "";
5511
5514
  const or = notice.or ? `${needs || reason ? ", or" : " It needs"} ${notice.or}` : "";
@@ -11474,6 +11477,9 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
11474
11477
  const startedFrom = useRef21(null);
11475
11478
  const startedStored = useRef21(null);
11476
11479
  const host = useRecordsUi();
11480
+ const fieldsRef = useRef21(fields);
11481
+ fieldsRef.current = fields;
11482
+ const forceNext = useRef21(/* @__PURE__ */ new Set());
11477
11483
  const type = useCallback10((value) => {
11478
11484
  typed2.current = value;
11479
11485
  setDraft(value);
@@ -11630,6 +11636,47 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
11630
11636
  delete next[id];
11631
11637
  return next;
11632
11638
  });
11639
+ const syncedField = fieldsRef.current.find((f) => f.key === key);
11640
+ if (syncedField?.source === "synced" && host.writeSyncedCell) {
11641
+ const force = forceNext.current.delete(id);
11642
+ let outcome;
11643
+ try {
11644
+ outcome = await host.writeSyncedCell({ tableId, recordId: rowId, fieldKey: key, value: shown5, force });
11645
+ } catch (thrown) {
11646
+ outcome = { ok: false, message: thrown instanceof Error ? thrown.message : String(thrown) };
11647
+ }
11648
+ setSaving((held) => {
11649
+ const next = { ...held };
11650
+ delete next[id];
11651
+ return next;
11652
+ });
11653
+ if (outcome.ok && outcome.status === "written") {
11654
+ if (typeof outcome.version === "number") {
11655
+ rememberVersion(versions.current, rowId, outcome.version);
11656
+ source.wrote(rowId, outcome.version);
11657
+ }
11658
+ settling.current.set(id, base2);
11659
+ writtenRef.current?.({ rowId, key, before: base2, after: shown5 });
11660
+ afterWrite();
11661
+ return;
11662
+ }
11663
+ setOptimistic((held) => {
11664
+ const next = { ...held };
11665
+ delete next[id];
11666
+ return next;
11667
+ });
11668
+ const sheetValue = outcome.ok ? outcome.sheetValue : null;
11669
+ setRefusals((held) => ({
11670
+ ...held,
11671
+ [id]: outcome.ok ? {
11672
+ error: { code: "stale_write", message: `The sheet now says "${sheetValue ?? ""}". Retry keeps yours.` },
11673
+ conflict: null,
11674
+ attempted: value,
11675
+ sheet: { value: sheetValue }
11676
+ } : { error: { code: "refused_by_rule", message: outcome.message }, conflict: null, attempted: value }
11677
+ }));
11678
+ return;
11679
+ }
11633
11680
  let written;
11634
11681
  try {
11635
11682
  let version = await versionOf(source, versions.current, versionReads.current, rowId);
@@ -11789,6 +11836,7 @@ function useGridEditing({ tableId, fields, rows, reload, reloadAfterWrite, canWr
11789
11836
  (rowId, key) => {
11790
11837
  const held = refusals[cellKey(rowId, key)];
11791
11838
  if (!held) return;
11839
+ if (held.sheet) forceNext.current.add(cellKey(rowId, key));
11792
11840
  void writeCell(rowId, key, held.attempted, held.conflict?.contested_fields[key]);
11793
11841
  },
11794
11842
  [refusals, writeCell]
@@ -16573,6 +16621,7 @@ function useMergedGridControls(args) {
16573
16621
  } = args;
16574
16622
  const client = useRecordsClient27();
16575
16623
  const linkRecord = useRecordsUi().linkRecord;
16624
+ const columnAccess = useRecordsUi().columnAccess;
16576
16625
  const hrefForRecord = useRecordsUi().hrefForRecord;
16577
16626
  const tableVersion = (0, recordVersions_exports.useTableVersion)(client, tableId, table);
16578
16627
  const mutation = useFieldMutation2();
@@ -16754,6 +16803,14 @@ function useMergedGridControls(args) {
16754
16803
  writeLook({ ...rest, ...next.size > 0 ? { wrapColumns: [...next] } : {} });
16755
16804
  }
16756
16805
  });
16806
+ if (columnAccess) {
16807
+ out.push({
16808
+ id: "col-access",
16809
+ label: "Who can see and edit\u2026",
16810
+ disabledReason: rights.structure ? void 0 : rights.why("structure"),
16811
+ onSelect: () => setDialog({ kind: "access", field: field2 })
16812
+ });
16813
+ }
16757
16814
  out.push({
16758
16815
  id: "col-duplicate",
16759
16816
  label: "Duplicate property",
@@ -17035,6 +17092,7 @@ function useMergedGridControls(args) {
17035
17092
  }
17036
17093
  };
17037
17094
  }, [
17095
+ columnAccess,
17038
17096
  args,
17039
17097
  colours,
17040
17098
  fieldKeys,
@@ -17085,6 +17143,13 @@ function useMergedGridControls(args) {
17085
17143
  const close = () => setDialog(null);
17086
17144
  const dialogs = !enabled ? null : /* @__PURE__ */ jsxs57(Fragment17, { children: [
17087
17145
  colours.dialogs,
17146
+ dialog?.kind === "access" && columnAccess ? columnAccess({
17147
+ tableId,
17148
+ fieldId: dialog.field.id,
17149
+ name: fieldName(dialog.field),
17150
+ onClose: () => setDialog(null),
17151
+ onChanged: () => tableShapeChanged5(tableId)
17152
+ }) : null,
17088
17153
  /* @__PURE__ */ jsx63(RowActionsDialog, { tableId, open: rowActionsOpen, onOpenChange: setRowActionsOpen }),
17089
17154
  /* @__PURE__ */ jsx63(
17090
17155
  RowLabelPicker,
@@ -19672,6 +19737,40 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
19672
19737
  const name = fieldName(field2);
19673
19738
  const format = cellFormatFor(field2, look?.format);
19674
19739
  const workedOut = workedOutFrom(field2);
19740
+ const syncedMark = field2.source === "synced" ? /* @__PURE__ */ jsx69(
19741
+ "span",
19742
+ {
19743
+ "data-records-synced": field2.key,
19744
+ title: `Synced from ${look?.syncedFrom || "its source"}`,
19745
+ "aria-label": `Synced from ${look?.syncedFrom || "its source"}`,
19746
+ className: "text-[10px] text-muted-foreground",
19747
+ children: "\u27F3"
19748
+ }
19749
+ ) : null;
19750
+ const restricted = field2.sensitivity === "confidential" || field2.sensitivity === "restricted";
19751
+ const lockMark = restricted ? /* @__PURE__ */ jsx69(
19752
+ "span",
19753
+ {
19754
+ "data-records-restricted": field2.key,
19755
+ title: "Fewer people see this column",
19756
+ "aria-label": "Fewer people see this column",
19757
+ className: "inline-flex text-muted-foreground",
19758
+ children: /* @__PURE__ */ jsxs63("svg", { viewBox: "0 0 24 24", width: "11", height: "11", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
19759
+ /* @__PURE__ */ jsx69("rect", { x: "4", y: "11", width: "16", height: "10", rx: "2" }),
19760
+ /* @__PURE__ */ jsx69("path", { d: "M8 11V7a4 4 0 0 1 8 0v4" })
19761
+ ] })
19762
+ }
19763
+ ) : null;
19764
+ const withSynced = (inner2) => {
19765
+ const header = lockMark ? /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19766
+ inner2,
19767
+ lockMark
19768
+ ] }) : inner2;
19769
+ return syncedMark ? /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19770
+ syncedMark,
19771
+ header
19772
+ ] }) : header;
19773
+ };
19675
19774
  return {
19676
19775
  id: field2.key,
19677
19776
  /*
@@ -19679,38 +19778,40 @@ function columnForField(field2, editing, mayWriteRow, whyNotRow, look, onAskWhoC
19679
19778
  * (`custom.formula_eval`, on read or on write) and nobody types it — so its header carries
19680
19779
  * the mark, and the formula it is worked out from is one hover away, in its own words.
19681
19780
  */
19682
- header: look?.rowLabel ? (
19683
- // THE COLUMN THAT NAMES EACH RECORD says so (tranche 6i, the older grid's key marker).
19684
- /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19781
+ header: withSynced(
19782
+ look?.rowLabel ? (
19783
+ // THE COLUMN THAT NAMES EACH RECORD says so (tranche 6i, the older grid's key marker).
19784
+ /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19785
+ /* @__PURE__ */ jsx69(
19786
+ "span",
19787
+ {
19788
+ "data-records-row-label": field2.key,
19789
+ title: "This column names each record",
19790
+ "aria-label": "Names each record",
19791
+ className: "text-[10px] text-muted-foreground",
19792
+ children: "\u26BF"
19793
+ }
19794
+ ),
19795
+ name
19796
+ ] })
19797
+ ) : workedOut && stampMarkOf(field2) ? (
19798
+ // A STAMP OR A RECORD NUMBER (walk 2026-10-08 D7): kept by the store, but nobody wrote a formula
19799
+ // for it, so its header wears its own mark — a clock, a person, a number sign — never "fx".
19800
+ /* @__PURE__ */ jsx69("span", { className: "inline-flex items-center", title: workedOut, "data-records-stamp": stampMarkOf(field2), children: withTypeMark(field2, name) })
19801
+ ) : workedOut ? /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19802
+ name,
19685
19803
  /* @__PURE__ */ jsx69(
19686
19804
  "span",
19687
19805
  {
19688
- "data-records-row-label": field2.key,
19689
- title: "This column names each record",
19690
- "aria-label": "Names each record",
19691
- className: "text-[10px] text-muted-foreground",
19692
- children: "\u26BF"
19806
+ "data-records-worked-out": field2.key,
19807
+ title: workedOut,
19808
+ "aria-label": workedOut,
19809
+ className: "rounded bg-muted px-1 font-mono text-[10px] font-normal text-muted-foreground",
19810
+ children: "fx"
19693
19811
  }
19694
- ),
19695
- name
19696
- ] })
19697
- ) : workedOut && stampMarkOf(field2) ? (
19698
- // A STAMP OR A RECORD NUMBER (walk 2026-10-08 D7): kept by the store, but nobody wrote a formula
19699
- // for it, so its header wears its own mark — a clock, a person, a number sign — never "fx".
19700
- /* @__PURE__ */ jsx69("span", { className: "inline-flex items-center", title: workedOut, "data-records-stamp": stampMarkOf(field2), children: withTypeMark(field2, name) })
19701
- ) : workedOut ? /* @__PURE__ */ jsxs63("span", { className: "inline-flex items-center gap-1", children: [
19702
- name,
19703
- /* @__PURE__ */ jsx69(
19704
- "span",
19705
- {
19706
- "data-records-worked-out": field2.key,
19707
- title: workedOut,
19708
- "aria-label": workedOut,
19709
- className: "rounded bg-muted px-1 font-mono text-[10px] font-normal text-muted-foreground",
19710
- children: "fx"
19711
- }
19712
- )
19713
- ] }) : name,
19812
+ )
19813
+ ] }) : name
19814
+ ),
19714
19815
  label: name,
19715
19816
  accessorFn: (row) => row.document?.[field2.key],
19716
19817
  // A column the store keeps no value for is not offered a sort it would refuse (`sortRefusal`).
@@ -20921,7 +21022,7 @@ function columnsSentence(mapped, total, unmapped) {
20921
21022
  if (unmapped === "ignore") return `${mapped} of ${total} columns go into this table \xB7 ${rest} left out`;
20922
21023
  return `${mapped} of ${total} go in now \xB7 ${rest} wait for approval with their values`;
20923
21024
  }
20924
- function ImportWizard({ tableId, source, onDone, onWrote, className }) {
21025
+ function ImportWizard({ tableId, source, onDone, onWrote, autoRun, className }) {
20925
21026
  const client = useRecordsClient35();
20926
21027
  const table = useTable8(tableId);
20927
21028
  const fields = useFields10(tableId);
@@ -21543,6 +21644,13 @@ function ImportWizard({ tableId, source, onDone, onWrote, className }) {
21543
21644
  const refusedByRules = ruleVerdicts.reduce((n, v) => n + v.refused, 0);
21544
21645
  const [goAheadAnyway, setGoAheadAnyway] = useState61(false);
21545
21646
  useEffect46(() => setGoAheadAnyway(false), [ruleVerdicts]);
21647
+ const [autoRan, setAutoRan] = useState61(false);
21648
+ useEffect46(() => {
21649
+ if (!autoRun || autoRan || !source || phase !== "ready" || !plan) return;
21650
+ if (busy || !rights.write || rows.length === 0 || titleMissing || ruleVerdicts.length > 0) return;
21651
+ setAutoRan(true);
21652
+ void run();
21653
+ }, [autoRun, autoRan, source, phase, plan, busy, rights.write, rows.length, titleMissing, ruleVerdicts, run]);
21546
21654
  const afterWrite = !busy && (phase === "done" || alreadyRan !== null || ledger !== null && ledger.seen > 0);
21547
21655
  return /* @__PURE__ */ jsxs68("div", { className: cn37("flex min-w-0 flex-col gap-2 text-xs", className), children: [
21548
21656
  /* @__PURE__ */ jsxs68("div", { className: "flex items-center gap-2", children: [
@@ -24251,6 +24359,8 @@ import {
24251
24359
  designateView,
24252
24360
  viewPatchFor,
24253
24361
  groupViewsBySection,
24362
+ planViewDrop,
24363
+ sectionDropId,
24254
24364
  sectionNames,
24255
24365
  sectionNameOk,
24256
24366
  reassignSection
@@ -25710,7 +25820,8 @@ function GridBody({
25710
25820
  ...presentation.formats?.[field2.key] ? { format: presentation.formats[field2.key] } : {},
25711
25821
  frozen: frozenKeys.has(field2.key),
25712
25822
  // The column that names each record wears the mark (merged grid, tranche 6i).
25713
- rowLabel: merged && field2.key === (table.data?.title_field ?? null)
25823
+ rowLabel: merged && field2.key === (table.data?.title_field ?? null),
25824
+ syncedFrom: syncedFromWords(table.data)
25714
25825
  },
25715
25826
  onAskWhoChanged,
25716
25827
  {
@@ -26899,6 +27010,12 @@ function withHeaderMenus(columns, menuFor, filterFor) {
26899
27010
  return filter ? { ...withMenu, ...filter } : withMenu;
26900
27011
  });
26901
27012
  }
27013
+ function syncedFromWords(table) {
27014
+ const source = table?.sync_source;
27015
+ if (!source?.provider) return null;
27016
+ const from = source.provider === "google_sheets" ? "Google Sheets" : source.provider === "csv_url" ? "a CSV link" : source.provider === "postgres" ? "an outside database" : source.provider === "matrx_view" ? "another table" : source.provider;
27017
+ return source.label ? `${from} \xB7 ${source.label}` : from;
27018
+ }
26902
27019
  function withoutGoneColumns(query, liveKeys, openingSort) {
26903
27020
  const sortGone = Boolean(query.sort && !liveKeys.has(query.sort.id));
26904
27021
  const goneFilters = Object.keys(query.columnFilters ?? {}).filter((key) => !liveKeys.has(key));
@@ -28163,7 +28280,7 @@ function NewTableStart({
28163
28280
  /* @__PURE__ */ jsx89(Button53, { disabled: !importReady || busy, onClick: () => void continueImport(), "data-new-table-continue": "", children: busy ? "Creating\u2026" : "Next: columns" })
28164
28281
  ] });
28165
28282
  } else {
28166
- body = /* @__PURE__ */ jsx89("div", { "data-new-table-wizard": "", children: /* @__PURE__ */ jsx89(ImportWizard, { tableId: step2.tableId, source: step2.source, onDone: () => onOpenTable?.(step2.tableId) }) });
28283
+ body = /* @__PURE__ */ jsx89("div", { "data-new-table-wizard": "", children: /* @__PURE__ */ jsx89(ImportWizard, { tableId: step2.tableId, source: step2.source, autoRun: step2.made, onDone: () => onOpenTable?.(step2.tableId) }) });
28167
28284
  footer = /* @__PURE__ */ jsxs79(Fragment30, { children: [
28168
28285
  !step2.made ? /* @__PURE__ */ jsx89(Button53, { variant: "ghost", className: "mr-auto", onClick: () => setStep({ at: "import" }), children: "Back" }) : null,
28169
28286
  /* @__PURE__ */ jsx89(Button53, { variant: "outline", onClick: () => onOpenTable?.(step2.tableId), "data-new-table-open": "", children: "Open the table" })
@@ -35008,6 +35125,7 @@ function TimelineView({
35008
35125
  const [dragging, setDragging] = useState99(null);
35009
35126
  const [linking, setLinking] = useState99(null);
35010
35127
  const [ganttBusy, setGanttBusy] = useState99(false);
35128
+ const [linkTarget, setLinkTarget] = useState99(null);
35011
35129
  const { placed, unscheduled } = useMemo57(() => {
35012
35130
  const out = [];
35013
35131
  const without = [];
@@ -35176,6 +35294,18 @@ function TimelineView({
35176
35294
  label: `${titleOf(target)} now waits on ${titleOf(source)}`
35177
35295
  });
35178
35296
  };
35297
+ const taskRowAt = (x, y) => {
35298
+ const canvas = scroller.current?.querySelector("[data-timeline-canvas]");
35299
+ const body2 = scroller.current;
35300
+ if (!canvas || !body2) return null;
35301
+ const box = canvas.getBoundingClientRect();
35302
+ const frame2 = body2.getBoundingClientRect();
35303
+ if (frame2.width === 0 || x < frame2.left || x > frame2.right) return null;
35304
+ const index = Math.floor((y - box.top - LANE_PAD / 2) / ROW_PX);
35305
+ if (index < 0) return null;
35306
+ const lane = laneRows[0];
35307
+ return lane?.packed.find((b) => b.row === index)?.p.row.id ?? null;
35308
+ };
35179
35309
  const beginLink = (p) => (e) => {
35180
35310
  if (e.button !== void 0 && e.button !== 0) return;
35181
35311
  e.stopPropagation();
@@ -35184,13 +35314,21 @@ function TimelineView({
35184
35314
  const x1 = box.left + box.width / 2;
35185
35315
  const y1 = box.top + box.height / 2;
35186
35316
  setLinking({ id: p.row.id, x1, y1, x2: e.clientX, y2: e.clientY });
35187
- const onMove = (ev) => setLinking((l) => l ? { ...l, x2: ev.clientX, y2: ev.clientY } : l);
35317
+ const onMove = (ev) => {
35318
+ const x = ev.clientX;
35319
+ const y = ev.clientY;
35320
+ setLinking((l) => l ? { ...l, x2: x, y2: y } : l);
35321
+ const over = taskRowAt(x, y);
35322
+ setLinkTarget(over && over !== p.row.id ? over : null);
35323
+ };
35188
35324
  const onUp = (ev) => {
35189
35325
  window.removeEventListener("pointermove", onMove);
35190
35326
  window.removeEventListener("pointerup", onUp);
35191
35327
  setLinking(null);
35328
+ setLinkTarget(null);
35329
+ const at = ev;
35192
35330
  const hit = ev.target?.closest?.("[data-timeline-bar]");
35193
- const id = hit?.getAttribute("data-timeline-bar");
35331
+ const id = taskRowAt(at.clientX, at.clientY) ?? hit?.getAttribute("data-timeline-bar");
35194
35332
  if (id && id !== p.row.id) connect(p.row.id, id);
35195
35333
  };
35196
35334
  window.addEventListener("pointermove", onMove);
@@ -35202,7 +35340,7 @@ function TimelineView({
35202
35340
  try {
35203
35341
  const make = async (current, key, label) => {
35204
35342
  if (current) return current.key;
35205
- const made = await knobClient.fieldDeclare({ table_id: tableId, spec: { key, label, type: "datetime", kind: "date" } });
35343
+ const made = await knobClient.fieldDeclare({ table_id: tableId, spec: { key, label, parity_type: "datetime", kind: "date" } });
35206
35344
  if (!made.ok) {
35207
35345
  moves.say(refusalSentence(made.error));
35208
35346
  return null;
@@ -35421,6 +35559,7 @@ function TimelineView({
35421
35559
  "data-timeline-span": `${first}..${last}`,
35422
35560
  ...p.marker ? { "data-timeline-marker": "" } : {},
35423
35561
  ...milestone ? { "data-timeline-milestone": "" } : {},
35562
+ ...linkTarget === p.row.id ? { "data-timeline-drop-target": "" } : {},
35424
35563
  ...onCritical ? { "data-timeline-critical": "" } : {},
35425
35564
  ...slip !== null ? { "data-timeline-slip": slip } : {},
35426
35565
  ...may ? {} : { "data-timeline-locked": "" },
@@ -35434,6 +35573,7 @@ function TimelineView({
35434
35573
  outside ? "overflow-visible" : "overflow-hidden",
35435
35574
  milestone ? "border-transparent bg-transparent" : color ? CHOICE_CHIP_CLASS4[color] : "bg-muted",
35436
35575
  onCritical ? "ring-2 ring-amber-500" : void 0,
35576
+ linkTarget === p.row.id ? "ring-2 ring-primary" : void 0,
35437
35577
  may ? "cursor-grab active:cursor-grabbing" : "cursor-pointer",
35438
35578
  dragging?.id === p.row.id ? "z-20 shadow-md" : "z-10",
35439
35579
  refused ? "ring-2 ring-destructive" : void 0
@@ -35515,7 +35655,7 @@ function TimelineView({
35515
35655
  /* @__PURE__ */ jsxs109("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: [
35516
35656
  settings,
35517
35657
  /* @__PURE__ */ jsxs109(DropdownMenu8, { children: [
35518
- /* @__PURE__ */ jsx120(DropdownMenuTrigger8, { asChild: true, children: /* @__PURE__ */ jsx120(Button75, { size: "sm", variant: ganttOn ? "secondary" : "outline", "aria-label": "Gantt options", "data-timeline-gantt-menu": "", children: "Gantt" }) }),
35658
+ /* @__PURE__ */ jsx120(DropdownMenuTrigger8, { asChild: true, children: /* @__PURE__ */ jsx120(Button75, { size: "sm", variant: "outline", className: ganttOn ? "bg-secondary" : void 0, "aria-label": "Gantt options", "data-timeline-gantt-menu": "", children: "Gantt" }) }),
35519
35659
  /* @__PURE__ */ jsxs109(DropdownMenuContent8, { align: "end", className: "min-w-48", children: [
35520
35660
  /* @__PURE__ */ jsx120(DropdownMenuCheckboxItem2, { checked: ganttOn, onCheckedChange: (on) => setGantt({ mode: on === true }), children: "Gantt view" }),
35521
35661
  ganttOn ? /* @__PURE__ */ jsxs109(Fragment45, { children: [
@@ -35593,6 +35733,7 @@ function TimelineView({
35593
35733
  const ghost = baselineOf(b.p.row);
35594
35734
  const at = shown5(b.p);
35595
35735
  return /* @__PURE__ */ jsxs109("div", { children: [
35736
+ linkTarget === b.p.row.id ? /* @__PURE__ */ jsx120("div", { "aria-hidden": "true", "data-timeline-drop-band": b.p.row.id, className: "pointer-events-none absolute inset-x-0 bg-primary/10", style: { top: LANE_PAD / 2 + b.row * ROW_PX, height: ROW_PX } }) : null,
35596
35737
  ghost ? /* @__PURE__ */ jsx120(
35597
35738
  "div",
35598
35739
  {
@@ -38927,6 +39068,9 @@ function ArchivedPortals({
38927
39068
  import { useCallback as useCallback43, useEffect as useEffect89, useRef as useRef50, useState as useState109 } from "react";
38928
39069
  import { useRecordsClient as useRecordsClient74 } from "@ai-matrx/records/react";
38929
39070
  import { Badge as Badge15, Button as Button80, Input as Input6, Popover as Popover16, PopoverContent as PopoverContent16, PopoverTrigger as PopoverTrigger16, Skeleton as Skeleton18, cn as cn65 } from "@ai-matrx/design-system";
39071
+ import { DndContext, PointerSensor, closestCenter, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
39072
+ import { SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
39073
+ import { CSS as CSS2 } from "@dnd-kit/utilities";
38930
39074
 
38931
39075
  // src/seedOnce.ts
38932
39076
  import { useCallback as useCallback42, useRef as useRef49 } from "react";
@@ -38948,7 +39092,7 @@ var NOOP3 = () => {
38948
39092
  };
38949
39093
  function viewActions(whyNot, host, locked = false, personal = false) {
38950
39094
  const one = (base2, run) => {
38951
- if (whyNot !== null) return { ...base2, disabledReason: whyNot, run: NOOP3 };
39095
+ if (whyNot !== null) return { ...base2, disabledReason: locked && base2.id !== "duplicate" && base2.id !== "lock" ? VIEW_LOCKED_REASON : whyNot, run: NOOP3 };
38952
39096
  if (!run) return { ...base2, disabledReason: ACTION_NOT_HERE_REASON, run: NOOP3 };
38953
39097
  return { ...base2, run };
38954
39098
  };
@@ -38991,6 +39135,25 @@ function seedIsSatisfied(seed, views) {
38991
39135
  if (views.some((v) => v.name === seed.name)) return true;
38992
39136
  return seed.isDefault === true && views.some((v) => v.isDefault);
38993
39137
  }
39138
+ function SectionBox({ id, children, ...rest }) {
39139
+ const { setNodeRef, isOver } = useDroppable({ id });
39140
+ return /* @__PURE__ */ jsx131("div", { ref: setNodeRef, className: cn65("rounded-sm", isOver && "bg-accent/40"), ...rest, children });
39141
+ }
39142
+ function SortableRow({ id, disabled, children }) {
39143
+ const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = useSortable({ id, disabled });
39144
+ return /* @__PURE__ */ jsx131(
39145
+ "div",
39146
+ {
39147
+ ref: setNodeRef,
39148
+ style: { transform: CSS2.Transform.toString(transform), transition },
39149
+ className: cn65(isDragging && "relative z-10 opacity-80"),
39150
+ "data-view-row": id,
39151
+ ...disabled ? {} : attributes,
39152
+ ...disabled ? {} : listeners2,
39153
+ children
39154
+ }
39155
+ );
39156
+ }
38994
39157
  function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews, initialViews, className }) {
38995
39158
  const client = useRecordsClient74();
38996
39159
  const claimSeed = useSeedGuard();
@@ -39022,6 +39185,26 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
39022
39185
  }
39023
39186
  });
39024
39187
  const [renamingSection, setRenamingSection] = useState109(null);
39188
+ const [dragging, setDragging] = useState109(false);
39189
+ const justDragged = useRef50(false);
39190
+ const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }));
39191
+ async function dropped(event) {
39192
+ setDragging(false);
39193
+ justDragged.current = true;
39194
+ setTimeout(() => {
39195
+ justDragged.current = false;
39196
+ }, 250);
39197
+ if (!event.over || !views) return;
39198
+ const writes = planViewDrop(views, String(event.active.id), String(event.over.id));
39199
+ for (const w of writes) {
39200
+ const written = await saveViewPatch(client, tableId, w.id, { position: w.position, ..."section" in w ? { section: w.section ?? null } : {} });
39201
+ if (!written.ok) {
39202
+ setError(written.error);
39203
+ break;
39204
+ }
39205
+ }
39206
+ if (writes.length > 0) await load();
39207
+ }
39025
39208
  const toggleShut = (name) => {
39026
39209
  setShut((all) => {
39027
39210
  const next = all.includes(name) ? all.filter((n) => n !== name) : [...all, name];
@@ -39234,83 +39417,89 @@ function ViewBar({ tableId, activeViewId, onActiveView, seed, settings, onViews,
39234
39417
  ) }),
39235
39418
  /* @__PURE__ */ jsxs119(PopoverContent16, { sizing: "content", align: "start", className: "w-64 p-1", "data-view-picker-content": "", children: [
39236
39419
  /* @__PURE__ */ jsxs119("div", { role: "group", "aria-label": "Saved views", className: "flex max-h-[50dvh] flex-col overflow-y-auto", children: [
39237
- groupViewsBySection(views).map((group) => /* @__PURE__ */ jsxs119("div", { role: "group", "aria-label": group.name ?? "Views", "data-view-section": group.name ?? "", children: [
39238
- group.name !== null ? renamingSection?.from === group.name ? /* @__PURE__ */ jsxs119(
39239
- "form",
39240
- {
39241
- className: "flex items-center gap-1 px-1 py-1",
39242
- onSubmit: (e) => {
39243
- e.preventDefault();
39244
- void renameSection(group.name, renamingSection.draft);
39245
- },
39246
- children: [
39247
- /* @__PURE__ */ jsx131(
39248
- Input6,
39249
- {
39250
- autoFocus: true,
39251
- "aria-label": "New name for this section",
39252
- value: renamingSection.draft,
39253
- onChange: (e) => setRenamingSection({ from: group.name, draft: e.target.value }),
39254
- onKeyDown: (e) => {
39255
- if (e.key === "Escape") {
39256
- e.preventDefault();
39257
- e.stopPropagation();
39258
- setRenamingSection(null);
39259
- }
39260
- },
39261
- className: "h-7 min-w-0 flex-1 text-xs"
39262
- }
39263
- ),
39264
- /* @__PURE__ */ jsx131(Button80, { size: "sm", type: "submit", className: "h-7", children: "Save" })
39265
- ]
39266
- }
39267
- ) : /* @__PURE__ */ jsxs119("div", { className: "group flex min-h-7 items-center gap-1 px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: [
39268
- /* @__PURE__ */ jsxs119(
39420
+ /* @__PURE__ */ jsx131(DndContext, { sensors, collisionDetection: closestCenter, onDragStart: () => setDragging(true), onDragCancel: () => setDragging(false), onDragEnd: (e) => void dropped(e), children: (() => {
39421
+ const groups = groupViewsBySection(views);
39422
+ return groups.some((g) => g.name === null) || !dragging ? groups : [{ name: null, views: [] }, ...groups];
39423
+ })().map((group) => /* @__PURE__ */ jsxs119(SectionBox, { id: sectionDropId(group.name), role: "group", "aria-label": group.name ?? "Views", "data-view-section": group.name ?? "", children: [
39424
+ group.name === null && group.views.length === 0 ? /* @__PURE__ */ jsx131("span", { className: "block px-2 py-1.5 text-[11px] text-muted-foreground", children: "No section" }) : null,
39425
+ /* @__PURE__ */ jsxs119(SortableContext, { items: group.views.map((v) => v.id), strategy: verticalListSortingStrategy, children: [
39426
+ group.name !== null ? renamingSection?.from === group.name ? /* @__PURE__ */ jsxs119(
39427
+ "form",
39428
+ {
39429
+ className: "flex items-center gap-1 px-1 py-1",
39430
+ onSubmit: (e) => {
39431
+ e.preventDefault();
39432
+ void renameSection(group.name, renamingSection.draft);
39433
+ },
39434
+ children: [
39435
+ /* @__PURE__ */ jsx131(
39436
+ Input6,
39437
+ {
39438
+ autoFocus: true,
39439
+ "aria-label": "New name for this section",
39440
+ value: renamingSection.draft,
39441
+ onChange: (e) => setRenamingSection({ from: group.name, draft: e.target.value }),
39442
+ onKeyDown: (e) => {
39443
+ if (e.key === "Escape") {
39444
+ e.preventDefault();
39445
+ e.stopPropagation();
39446
+ setRenamingSection(null);
39447
+ }
39448
+ },
39449
+ className: "h-7 min-w-0 flex-1 text-xs"
39450
+ }
39451
+ ),
39452
+ /* @__PURE__ */ jsx131(Button80, { size: "sm", type: "submit", className: "h-7", children: "Save" })
39453
+ ]
39454
+ }
39455
+ ) : /* @__PURE__ */ jsxs119("div", { className: "group flex min-h-7 items-center gap-1 px-2 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: [
39456
+ /* @__PURE__ */ jsxs119(
39457
+ "button",
39458
+ {
39459
+ type: "button",
39460
+ className: "flex min-w-0 flex-1 items-center gap-1 text-left",
39461
+ "aria-expanded": !shut.includes(group.name),
39462
+ "data-view-section-toggle": "",
39463
+ onClick: () => toggleShut(group.name),
39464
+ children: [
39465
+ /* @__PURE__ */ jsx131("svg", { viewBox: "0 0 24 24", className: cn65("h-3 w-3 shrink-0", shut.includes(group.name) && "-rotate-90"), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx131("path", { d: "m6 9 6 6 6-6" }) }),
39466
+ /* @__PURE__ */ jsx131("span", { className: "truncate", children: group.name }),
39467
+ /* @__PURE__ */ jsx131("span", { className: "shrink-0 font-normal normal-case", children: group.views.length })
39468
+ ]
39469
+ }
39470
+ ),
39471
+ rights.admin ? /* @__PURE__ */ jsxs119(Fragment49, { children: [
39472
+ /* @__PURE__ */ jsx131("button", { type: "button", className: "shrink-0 normal-case hover:text-foreground", "data-view-section-rename": "", onClick: () => setRenamingSection({ from: group.name, draft: group.name }), children: "Rename" }),
39473
+ /* @__PURE__ */ jsx131("button", { type: "button", className: "shrink-0 normal-case hover:text-destructive", "data-view-section-delete": "", title: "The views stay; they leave the section", onClick: () => void renameSection(group.name, null), children: "Delete" })
39474
+ ] }) : null
39475
+ ] }) : null,
39476
+ group.name !== null && shut.includes(group.name) && !group.views.some((v) => v.id === active) ? null : group.views.map((view) => /* @__PURE__ */ jsx131(SortableRow, { id: view.id, disabled: !(rights.admin || view.personal) || view.presentation?.locked === true, children: /* @__PURE__ */ jsxs119(
39269
39477
  "button",
39270
39478
  {
39271
39479
  type: "button",
39272
- className: "flex min-w-0 flex-1 items-center gap-1 text-left",
39273
- "aria-expanded": !shut.includes(group.name),
39274
- "data-view-section-toggle": "",
39275
- onClick: () => toggleShut(group.name),
39480
+ "aria-pressed": view.id === active,
39481
+ className: cn65(
39482
+ "flex min-h-8 w-full items-center gap-2 rounded-sm px-2 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
39483
+ group.name !== null && "pl-4",
39484
+ view.id === active && "font-medium"
39485
+ ),
39486
+ onClick: () => {
39487
+ if (justDragged.current) return;
39488
+ setActive(view.id);
39489
+ onActiveView?.(view);
39490
+ setOpen(false);
39491
+ },
39492
+ title: view.ruleId ? "Membership is this view's Rule" : "The whole table",
39276
39493
  children: [
39277
- /* @__PURE__ */ jsx131("svg", { viewBox: "0 0 24 24", className: cn65("h-3 w-3 shrink-0", shut.includes(group.name) && "-rotate-90"), fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx131("path", { d: "m6 9 6 6 6-6" }) }),
39278
- /* @__PURE__ */ jsx131("span", { className: "truncate", children: group.name }),
39279
- /* @__PURE__ */ jsx131("span", { className: "shrink-0 font-normal normal-case", children: group.views.length })
39494
+ /* @__PURE__ */ jsx131("span", { className: "min-w-0 flex-1 truncate", children: view.name }),
39495
+ view.presentation?.locked === true ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-locked": "", title: VIEW_LOCKED_REASON, children: "Locked" }) : null,
39496
+ view.personal ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-personal": "", title: "Only you see this view", children: "Personal" }) : null,
39497
+ view.isDefault ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-default": "", children: "Default" }) : null
39280
39498
  ]
39281
39499
  }
39282
- ),
39283
- rights.admin ? /* @__PURE__ */ jsxs119(Fragment49, { children: [
39284
- /* @__PURE__ */ jsx131("button", { type: "button", className: "shrink-0 normal-case hover:text-foreground", "data-view-section-rename": "", onClick: () => setRenamingSection({ from: group.name, draft: group.name }), children: "Rename" }),
39285
- /* @__PURE__ */ jsx131("button", { type: "button", className: "shrink-0 normal-case hover:text-destructive", "data-view-section-delete": "", title: "The views stay; they leave the section", onClick: () => void renameSection(group.name, null), children: "Delete" })
39286
- ] }) : null
39287
- ] }) : null,
39288
- group.name !== null && shut.includes(group.name) && !group.views.some((v) => v.id === active) ? null : group.views.map((view) => /* @__PURE__ */ jsxs119(
39289
- "button",
39290
- {
39291
- type: "button",
39292
- "aria-pressed": view.id === active,
39293
- className: cn65(
39294
- "flex min-h-8 w-full items-center gap-2 rounded-sm px-2 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
39295
- group.name !== null && "pl-4",
39296
- view.id === active && "font-medium"
39297
- ),
39298
- onClick: () => {
39299
- setActive(view.id);
39300
- onActiveView?.(view);
39301
- setOpen(false);
39302
- },
39303
- title: view.ruleId ? "Membership is this view's Rule" : "The whole table",
39304
- children: [
39305
- /* @__PURE__ */ jsx131("span", { className: "min-w-0 flex-1 truncate", children: view.name }),
39306
- view.presentation?.locked === true ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-locked": "", title: VIEW_LOCKED_REASON, children: "Locked" }) : null,
39307
- view.personal ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-personal": "", title: "Only you see this view", children: "Personal" }) : null,
39308
- view.isDefault ? /* @__PURE__ */ jsx131(Badge15, { variant: "neutral", className: "shrink-0 px-1.5 py-0 text-[10px]", "data-view-default": "", children: "Default" }) : null
39309
- ]
39310
- },
39311
- view.id
39312
- ))
39313
- ] }, group.name ?? "__loose")),
39500
+ ) }, view.id))
39501
+ ] })
39502
+ ] }, group.name ?? "__loose")) }),
39314
39503
  views.length === 0 && !rights.admin ? /* @__PURE__ */ jsx131("span", { className: "px-2 py-1 text-xs text-muted-foreground", children: rights.why("structure") }) : null
39315
39504
  ] }),
39316
39505
  /* @__PURE__ */ jsx131("div", { className: "mt-1 border-t border-border pt-1", children: naming ? /* @__PURE__ */ jsxs119(
@@ -44610,9 +44799,9 @@ function SubscriptionsPanel({ tableId, activeRuleId, className }) {
44610
44799
  import { copyText as copyText8 } from "@ai-matrx/kit/clipboard";
44611
44800
  import { ErrorBox as ErrorBox7 } from "@ai-matrx/design-system";
44612
44801
  import { useCallback as useCallback56, useEffect as useEffect106, useMemo as useMemo73, useRef as useRef58, useState as useState127 } from "react";
44613
- import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
44614
- import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
44615
- import { CSS as CSS2 } from "@dnd-kit/utilities";
44802
+ import { DndContext as DndContext2, KeyboardSensor, PointerSensor as PointerSensor2, closestCenter as closestCenter2, useSensor as useSensor2, useSensors as useSensors2 } from "@dnd-kit/core";
44803
+ import { SortableContext as SortableContext2, arrayMove, sortableKeyboardCoordinates, useSortable as useSortable2, verticalListSortingStrategy as verticalListSortingStrategy2 } from "@dnd-kit/sortable";
44804
+ import { CSS as CSS3 } from "@dnd-kit/utilities";
44616
44805
  import { useFields as useFields28, useRecordsClient as useRecordsClient89, useTable as useTable30 } from "@ai-matrx/records/react";
44617
44806
  import { publicFormPath } from "@ai-matrx/records";
44618
44807
  import {
@@ -46269,9 +46458,9 @@ function QuestionList({
46269
46458
  onQuestions,
46270
46459
  onQuestion
46271
46460
  }) {
46272
- const sensors = useSensors(
46273
- useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),
46274
- useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
46461
+ const sensors = useSensors2(
46462
+ useSensor2(PointerSensor2, { activationConstraint: { distance: 4 } }),
46463
+ useSensor2(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
46275
46464
  );
46276
46465
  const askable = askableFields([...fields]);
46277
46466
  const unasked = askable.filter((f) => !draft.questions.some((q) => q.field === f.key));
@@ -46293,7 +46482,7 @@ function QuestionList({
46293
46482
  /* @__PURE__ */ jsx151("span", { className: "font-medium text-foreground", children: "Questions" }),
46294
46483
  /* @__PURE__ */ jsx151("span", { className: "tabular-nums", children: draft.questions.length })
46295
46484
  ] }),
46296
- /* @__PURE__ */ jsx151(DndContext, { sensors, collisionDetection: closestCenter, onDragEnd: dragEnd, children: /* @__PURE__ */ jsx151(SortableContext, { items: draft.questions.map((q) => q.field), strategy: verticalListSortingStrategy, children: draft.questions.map((question, index) => /* @__PURE__ */ jsx151(
46485
+ /* @__PURE__ */ jsx151(DndContext2, { sensors, collisionDetection: closestCenter2, onDragEnd: dragEnd, children: /* @__PURE__ */ jsx151(SortableContext2, { items: draft.questions.map((q) => q.field), strategy: verticalListSortingStrategy2, children: draft.questions.map((question, index) => /* @__PURE__ */ jsx151(
46297
46486
  QuestionRow,
46298
46487
  {
46299
46488
  index,
@@ -46346,14 +46535,14 @@ function QuestionRow({
46346
46535
  onChange,
46347
46536
  onRemove
46348
46537
  }) {
46349
- const sortable = useSortable({ id: question.field });
46538
+ const sortable = useSortable2({ id: question.field });
46350
46539
  const [open, setOpen] = useState127(true);
46351
46540
  const name = field2 ? fieldName(field2) : question.field;
46352
46541
  return /* @__PURE__ */ jsxs139(
46353
46542
  "div",
46354
46543
  {
46355
46544
  ref: sortable.setNodeRef,
46356
- style: { transform: CSS2.Transform.toString(sortable.transform), transition: sortable.transition },
46545
+ style: { transform: CSS3.Transform.toString(sortable.transform), transition: sortable.transition },
46357
46546
  className: cn84("rounded border bg-background px-2 py-1.5", sortable.isDragging && "z-10 shadow-md"),
46358
46547
  "data-records-form-question-row": question.field,
46359
46548
  children: [
@@ -47303,20 +47492,20 @@ import {
47303
47492
 
47304
47493
  // src/DashboardGrid.tsx
47305
47494
  import {
47306
- DndContext as DndContext2,
47495
+ DndContext as DndContext3,
47307
47496
  KeyboardSensor as KeyboardSensor2,
47308
- PointerSensor as PointerSensor2,
47497
+ PointerSensor as PointerSensor3,
47309
47498
  pointerWithin,
47310
- useSensor as useSensor2,
47311
- useSensors as useSensors2
47499
+ useSensor as useSensor3,
47500
+ useSensors as useSensors3
47312
47501
  } from "@dnd-kit/core";
47313
47502
  import {
47314
- SortableContext as SortableContext2,
47503
+ SortableContext as SortableContext3,
47315
47504
  rectSortingStrategy,
47316
47505
  sortableKeyboardCoordinates as sortableKeyboardCoordinates2,
47317
- useSortable as useSortable2
47506
+ useSortable as useSortable3
47318
47507
  } from "@dnd-kit/sortable";
47319
- import { CSS as CSS3 } from "@dnd-kit/utilities";
47508
+ import { CSS as CSS4 } from "@dnd-kit/utilities";
47320
47509
  import { cn as cn89 } from "@ai-matrx/design-system";
47321
47510
 
47322
47511
  // src/dashboardLayout.ts
@@ -47380,9 +47569,9 @@ var dashboardCollision = (args) => {
47380
47569
  }).sort((a, b) => a.data.value - b.data.value);
47381
47570
  };
47382
47571
  function DashboardGrid({ items, arranging, onMove, onSpan }) {
47383
- const sensors = useSensors2(
47384
- useSensor2(PointerSensor2, { activationConstraint: { distance: 4 } }),
47385
- useSensor2(KeyboardSensor2, { coordinateGetter: sortableKeyboardCoordinates2 })
47572
+ const sensors = useSensors3(
47573
+ useSensor3(PointerSensor3, { activationConstraint: { distance: 4 } }),
47574
+ useSensor3(KeyboardSensor2, { coordinateGetter: sortableKeyboardCoordinates2 })
47386
47575
  );
47387
47576
  const ids = items.map((item) => item.id);
47388
47577
  function dragEnd(event) {
@@ -47392,7 +47581,7 @@ function DashboardGrid({ items, arranging, onMove, onSpan }) {
47392
47581
  }
47393
47582
  const grid = /* @__PURE__ */ jsx156("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-12", children: items.map((item, index) => /* @__PURE__ */ jsx156(GridCell2, { item, index, arranging, onSpan }, item.id)) });
47394
47583
  if (!arranging) return grid;
47395
- return /* @__PURE__ */ jsx156(DndContext2, { sensors, collisionDetection: dashboardCollision, onDragEnd: dragEnd, children: /* @__PURE__ */ jsx156(SortableContext2, { items: ids, strategy: rectSortingStrategy, children: grid }) });
47584
+ return /* @__PURE__ */ jsx156(DndContext3, { sensors, collisionDetection: dashboardCollision, onDragEnd: dragEnd, children: /* @__PURE__ */ jsx156(SortableContext3, { items: ids, strategy: rectSortingStrategy, children: grid }) });
47396
47585
  }
47397
47586
  function GridCell2({
47398
47587
  item,
@@ -47400,8 +47589,8 @@ function GridCell2({
47400
47589
  arranging,
47401
47590
  onSpan
47402
47591
  }) {
47403
- const sortable = useSortable2({ id: item.id, disabled: !arranging });
47404
- const style = arranging ? { transform: CSS3.Transform.toString(sortable.transform), transition: sortable.transition } : void 0;
47592
+ const sortable = useSortable3({ id: item.id, disabled: !arranging });
47593
+ const style = arranging ? { transform: CSS4.Transform.toString(sortable.transform), transition: sortable.transition } : void 0;
47405
47594
  return /* @__PURE__ */ jsxs144(
47406
47595
  "div",
47407
47596
  {