@anchrd/intel-ui 0.36.0 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anchrd/intel-ui",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1,10 +1,15 @@
1
1
  import { useNavigate, useRouterState } from "@tanstack/react-router";
2
- import { History, Network, PencilRuler } from "lucide-react";
2
+ import { ListChecks, Network, PencilRuler } from "lucide-react";
3
3
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
4
4
  import { useI18n } from "@/i18n/i18n-context.tsx";
5
5
  import { type IntelView, viewFrom } from "@/router/selection-search.ts";
6
6
 
7
- const icons = { editor: PencilRuler, graph: Network, runs: History } as const;
7
+ // ⚠️ `runs` is NOT `History`, and that is the point of this line rather than a taste in icons.
8
+ // `History` is what the resource menu draws beside "Version history" (`resource-menu.tsx`), and both
9
+ // are visible on the same flow header — one as this switch, one in the menu right below it. The same
10
+ // clock for two different things was read as one: the switch was taken for the version history and
11
+ // asked about as such (#635). Whatever stands here has to stay out of that menu.
12
+ const icons = { editor: PencilRuler, graph: Network, runs: ListChecks } as const;
8
13
  const labels = {
9
14
  editor: "view.showEditor",
10
15
  graph: "view.showGraph",
@@ -675,6 +675,7 @@ function FlowsEditor() {
675
675
  saving={save.isPending}
676
676
  canMutate={canMutate}
677
677
  incomplete={stepsMissingServer.map((node) => ({ label: node.data.node.label }))}
678
+ scrollingView={selection.view === "runs"}
678
679
  onSave={() => save.mutate()}
679
680
  onPublish={() => setPublishing(true)}
680
681
  />
@@ -943,6 +944,7 @@ function FlowTitle({
943
944
  saving,
944
945
  canMutate,
945
946
  incomplete,
947
+ scrollingView,
946
948
  onSave,
947
949
  onPublish,
948
950
  }: {
@@ -950,6 +952,9 @@ function FlowTitle({
950
952
  dirty: boolean;
951
953
  saving: boolean;
952
954
  canMutate: boolean;
955
+ // Whether what stands below this line can scroll under it. The runs list can and earns its edge
956
+ // the usual way; the canvas and the graph pan instead, and would never get one (#634).
957
+ scrollingView: boolean;
953
958
  // Tool steps that name no server yet. They cannot be saved, so the refusal is shown here rather
954
959
  // than fetched from the server as a message that names no step.
955
960
  incomplete: Array<{ label: string }>;
@@ -974,7 +979,12 @@ function FlowTitle({
974
979
  // loudest thing in this line and used to hold the edge; the menu takes it, because a menu one can
975
980
  // hit without looking is worth more than the primary button being outermost. `TitleRow` is what
976
981
  // enforces that — nothing passed in here can get past the menu.
977
- <TitleRow title={flow.title} description={flow.description} target={{ type: "flow", flow }}>
982
+ <TitleRow
983
+ title={flow.title}
984
+ description={flow.description}
985
+ target={{ type: "flow", flow }}
986
+ separated={!scrollingView}
987
+ >
978
988
  {/* ⚠️ #454: the toggle used to stand in the global header, beside the search — where what
979
989
  applies EVERYWHERE stands. But it says how THIS flow is shown, and so belongs in the line
980
990
  that names this flow. A flow is the only level with runs, and therefore the only one with
package/src/i18n/de.json CHANGED
@@ -75,7 +75,6 @@
75
75
  "resource.archive": "Archivieren",
76
76
  "resource.columns": "Spalten",
77
77
  "resource.export": "Export",
78
- "resource.exportExcludes": "Nimmt den aktuellen Stand mit. Frühere Versionen, Freigaben und Flow-Läufe bleiben zurück. Von einem veröffentlichten Flow reist der veröffentlichte Graph — spätere Änderungen am Entwurf bleiben zurück.",
79
78
  "resource.import": "Import",
80
79
  "resource.validate": "Prüfen",
81
80
  "resource.links": "Verweise",
package/src/i18n/en.json CHANGED
@@ -75,7 +75,6 @@
75
75
  "resource.archive": "Archive",
76
76
  "resource.columns": "Columns",
77
77
  "resource.export": "Export",
78
- "resource.exportExcludes": "Carries the current state. Earlier versions, shares and flow runs stay behind. A published flow travels as its published graph — changes drafted since stay behind.",
79
78
  "resource.import": "Import",
80
79
  "resource.validate": "Check",
81
80
  "resource.links": "Links",
package/src/i18n/es.json CHANGED
@@ -75,7 +75,6 @@
75
75
  "resource.archive": "Archivar",
76
76
  "resource.columns": "Columnas",
77
77
  "resource.export": "Exportar",
78
- "resource.exportExcludes": "Se lleva el estado actual. Las versiones anteriores, los permisos y las ejecuciones de flujo se quedan. Un flujo publicado viaja con su grafo publicado; los cambios redactados después se quedan.",
79
78
  "resource.import": "Importar",
80
79
  "resource.validate": "Comprobar",
81
80
  "resource.links": "Enlaces",
@@ -18,7 +18,7 @@ import {
18
18
  ShieldCheck,
19
19
  } from "lucide-react";
20
20
  import type * as React from "react";
21
- import { useId, useState } from "react";
21
+ import { useState } from "react";
22
22
  import { AccessSummary } from "@/access-summary/access-summary.tsx";
23
23
  import { allTreeLevelsKey, moveErrorKey, useTreeMove } from "@/app/tree-move/tree-move.tsx";
24
24
  import {
@@ -154,11 +154,6 @@ export function ResourceMenu({
154
154
  // nowhere else: a person had strictly less reach on their own table than a model did.
155
155
  const isTable = node !== null && node.kind === "table";
156
156
  const bundleImport = useBundleImport({ where: title });
157
- // ⚠️ Per instance, not a constant: the folder table renders one menu PER ROW, so a fixed id would
158
- // put the same `id` in the document twenty times and every entry's name would resolve to the
159
- // first one's.
160
- const exportLabelId = useId();
161
- const exportHintId = useId();
162
157
 
163
158
  // Everything a change here can make stale. The row sits in one level of the tree, the open screen
164
159
  // reads the record, and the flat collections behind the search, the link picker and the relation
@@ -323,38 +318,17 @@ export function ResourceMenu({
323
318
  (#534). That is the export's gap on every kind it can hit, not something this entry
324
319
  was covering — which is why it is fixed there and not by keeping a second entry.
325
320
 
326
- ⚠️ The second line is not decoration and it belongs HERE rather than after the click
327
- (#433, ADR-0006). A bundle carries one version per node; whoever moves an installation
328
- this way loses every earlier one, and until now the only place that said so was
329
- `excluded` in a `manifest.json` inside the zipread, if ever, long after the source
330
- installation is gone. A loss that cannot be undone has to be readable BEFORE the
331
- gesture, and a menu item is where this gesture is chosen.
332
-
333
- ⚠️ Its third clause is the flow half (#585), and it is a DIFFERENT loss from the first
334
- two rather than an example of them: a published flow travels as its published graph,
335
- so edits drafted since do not travel at all. Those edits are not an earlier version —
336
- they are the newest state there is, and somebody reading only "earlier versions stay
337
- behind" would expect the opposite of what happens. `Excluded` in `bundle.ts` names it
338
- with a word of its own for the same reason.
339
-
340
- ⚠️ It is the entry's DESCRIPTION, not part of its name: `aria-labelledby` keeps the
341
- name at the one word every other entry here uses, and `aria-describedby` is what a
342
- screen reader reads after it. Folding a whole sentence into the name would make this
343
- the only entry in the menu somebody has to listen through to know what it does — and
344
- the sentence is a condition of the action, which is what a description is for. */}
345
- <DropdownMenuItem
346
- className="items-start"
347
- aria-labelledby={exportLabelId}
348
- aria-describedby={exportHintId}
349
- onSelect={() => exportBundle.mutate()}
350
- >
351
- <FolderDown aria-hidden="true" className="mt-0.5" />
352
- <span className="flex flex-col gap-0.5">
353
- <span id={exportLabelId}>{i18n.t("resource.export")}</span>
354
- <span id={exportHintId} className="text-xs text-muted-foreground">
355
- {i18n.t("resource.exportExcludes")}
356
- </span>
357
- </span>
321
+ ⚠️ The entry carried a three-clause description under its name until 2026-08-19, put
322
+ there by #433/ADR-0006 so that an irreversible loss was readable BEFORE the gesture: a
323
+ bundle takes one version per node, shares and runs stay behind, and a published flow
324
+ travels as its published graph (#585). Jack removed itit was the only entry running
325
+ over two lines and it pushed the menu apart. What the reader now gets instead is
326
+ `excluded` in the zip's `manifest.json` and `BundleImportResult.excluded` after an
327
+ import, both of which are read only once the zip exists. That is a deliberate trade,
328
+ recorded in ADR-0006 and in #636, and NOT a leftover to be restored. */}
329
+ <DropdownMenuItem onSelect={() => exportBundle.mutate()}>
330
+ <FolderDown aria-hidden="true" />
331
+ {i18n.t("resource.export")}
358
332
  </DropdownMenuItem>
359
333
  {/* The other half of the same round trip, next to it rather than in the tree's plus
360
334
  (#346): one word in the menu, both sources under it. */}
@@ -69,11 +69,22 @@ export function TitleRow({
69
69
  title,
70
70
  description,
71
71
  target,
72
+ separated,
72
73
  children,
73
74
  }: {
74
75
  title: string;
75
76
  description?: string | null;
76
77
  target: ResourceTarget;
78
+ /**
79
+ * A separator that does NOT wait for a scroll.
80
+ *
81
+ * ⚠️ For a surface where scrolling cannot happen, and that is the only case it is for (#634). The
82
+ * edge below this row is normally `scrolled`, set by `TitleRowScrollArea` — which is right where
83
+ * content moves under the row. The flow canvas does not scroll, it pans: nothing ever sets
84
+ * `scrolled`, so the row sat on the dark canvas with no edge at all. Do not pass this where the
85
+ * content does scroll; a permanent edge there would replace a signal with decoration.
86
+ */
87
+ separated?: boolean;
77
88
  children?: ReactNode;
78
89
  }) {
79
90
  const scroll = useContext(TitleRowScrollContext);
@@ -88,7 +99,7 @@ export function TitleRow({
88
99
  data-scrolled={scroll?.scrolled || undefined}
89
100
  className={cn(
90
101
  "relative z-10 flex shrink-0 items-start justify-between gap-5 px-6 py-4 transition-shadow",
91
- scroll?.scrolled && "shadow-[inset_0_-1px_0_var(--border)]",
102
+ (separated || scroll?.scrolled) && "shadow-[inset_0_-1px_0_var(--border)]",
92
103
  )}
93
104
  >
94
105
  <div className="flex min-w-0 items-center gap-3">