@tangle-network/ui 11.51.19 → 11.51.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 11.51.20
2
+
3
+ ### Patch Changes
4
+
5
+ - 9d50cbe: `FileTabs`: `onClose` is optional. Without it the tabs render no close buttons and Delete does nothing, for tab strips that only switch between files.
6
+
1
7
  ## 11.51.19
2
8
 
3
9
  ### Patch Changes
@@ -15,7 +15,7 @@ export interface FileTabsProps {
15
15
  tabs: FileTabData[];
16
16
  activeId?: string;
17
17
  onSelect: (id: string) => void;
18
- onClose: (id: string) => void;
18
+ onClose?: (id: string) => void;
19
19
  /** Accessible name of the tab list. Defaults to "Open files". */
20
20
  label?: string;
21
21
  className?: string;
@@ -64,14 +64,14 @@ function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open files", cla
64
64
  Home: 0,
65
65
  End: last
66
66
  }[event.key];
67
- if (at < 0 || next === void 0 && event.key !== "Delete") return;
67
+ if (at < 0 || next === void 0 && (event.key !== "Delete" || !onClose)) return;
68
68
  event.preventDefault();
69
69
  if (next !== void 0) {
70
70
  tabButtons()[next]?.focus();
71
71
  onSelect(tabs[next].id);
72
72
  return;
73
73
  }
74
- onClose(tabs[at].id);
74
+ onClose?.(tabs[at].id);
75
75
  requestAnimationFrame(() => (tabButtons().find((tab) => tab.getAttribute("aria-selected") === "true") ?? tabButtons().at(-1))?.focus());
76
76
  };
77
77
  return /* @__PURE__ */ jsx("div", {
@@ -96,7 +96,7 @@ function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open files", cla
96
96
  "aria-label": `${tab.name}${hint ? ` in ${hint}` : ""}${tab.dirty ? ", unsaved changes" : ""}`,
97
97
  tabIndex: isActive || !activeId && tab === tabs[0] ? 0 : -1,
98
98
  onClick: () => onSelect(tab.id),
99
- className: cn("flex h-full min-w-0 items-center gap-1.5 rounded-t-lg pl-3 pr-1", focusRingInset),
99
+ className: cn("flex h-full min-w-0 items-center gap-1.5 rounded-t-lg pl-3", onClose ? "pr-1" : "pr-3", focusRingInset),
100
100
  children: [
101
101
  /* @__PURE__ */ jsx(Icon, {
102
102
  "aria-hidden": true,
@@ -121,12 +121,12 @@ function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open files", cla
121
121
  className: "size-1.5 shrink-0 rounded-full bg-[var(--accent-text)]"
122
122
  })
123
123
  ]
124
- }), /* @__PURE__ */ jsx("button", {
124
+ }), onClose && /* @__PURE__ */ jsx("button", {
125
125
  type: "button",
126
126
  tabIndex: -1,
127
127
  "aria-label": `Close ${tab.name}`,
128
128
  onClick: () => onClose(tab.id),
129
- className: cn("mr-1.5 grid size-5 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-[var(--ix-hover-bg)] hover:text-foreground", controlMotion, !isActive && "opacity-0 group-focus-within:opacity-100 group-hover:opacity-100"),
129
+ className: cn("mr-1.5 grid size-5 shrink-0 place-items-center rounded-md text-muted-foreground hover:bg-[var(--ix-hover-bg)] hover:text-foreground", "[transition:color_var(--motion-control),background-color_var(--motion-control),border-color_var(--motion-control),box-shadow_var(--motion-control),transform_var(--motion-control),scale_var(--motion-control),opacity_var(--motion-control)] motion-reduce:transition-none", !isActive && "opacity-0 group-focus-within:opacity-100 group-hover:opacity-100"),
130
130
  children: /* @__PURE__ */ jsx(X, {
131
131
  "aria-hidden": true,
132
132
  className: "size-3"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "11.51.19",
3
+ "version": "11.51.20",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -216,7 +216,7 @@
216
216
  "peerDependencies": {
217
217
  "@hocuspocus/provider": ">=2.15.0 <5.0.0",
218
218
  "@nanostores/react": ">=0.8.4 <3.0.0",
219
- "@tangle-network/brand": "^1.31.4",
219
+ "@tangle-network/brand": "^1.31.8",
220
220
  "@tiptap/core": ">=3.20.4 <4.0.0",
221
221
  "@tiptap/extension-collaboration": ">=3.20.4 <4.0.0",
222
222
  "@tiptap/extension-collaboration-caret": ">=3.7.0 <4.0.0",
@@ -23,7 +23,7 @@ export interface FileTabsProps {
23
23
  tabs: FileTabData[];
24
24
  activeId?: string;
25
25
  onSelect: (id: string) => void;
26
- onClose: (id: string) => void;
26
+ onClose?: (id: string) => void; // without it the tabs have no close buttons and Delete does nothing
27
27
  /** Accessible name of the tab list. Defaults to "Open files". */
28
28
  label?: string;
29
29
  className?: string;
@@ -84,14 +84,14 @@ export function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open file
84
84
  const at = tabButtons().indexOf(event.target as HTMLButtonElement);
85
85
  const last = tabs.length - 1;
86
86
  const next = ({ ArrowRight: at === last ? 0 : at + 1, ArrowLeft: at === 0 ? last : at - 1, Home: 0, End: last } as Record<string, number>)[event.key];
87
- if (at < 0 || (next === undefined && event.key !== "Delete")) return;
87
+ if (at < 0 || (next === undefined && (event.key !== "Delete" || !onClose))) return;
88
88
  event.preventDefault();
89
89
  if (next !== undefined) {
90
90
  tabButtons()[next]?.focus();
91
91
  onSelect(tabs[next]!.id);
92
92
  return;
93
93
  }
94
- onClose(tabs[at]!.id);
94
+ onClose?.(tabs[at]!.id);
95
95
  // Once the host has re-rendered, keep focus on the tab it opened.
96
96
  requestAnimationFrame(() => (tabButtons().find((tab) => tab.getAttribute("aria-selected") === "true") ?? tabButtons().at(-1))?.focus());
97
97
  };
@@ -136,7 +136,7 @@ export function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open file
136
136
  aria-label={`${tab.name}${hint ? ` in ${hint}` : ""}${tab.dirty ? ", unsaved changes" : ""}`}
137
137
  tabIndex={isActive || (!activeId && tab === tabs[0]) ? 0 : -1}
138
138
  onClick={() => onSelect(tab.id)}
139
- className={cn("flex h-full min-w-0 items-center gap-1.5 rounded-t-lg pl-3 pr-1", focusRingInset)}
139
+ className={cn("flex h-full min-w-0 items-center gap-1.5 rounded-t-lg pl-3", onClose ? "pr-1" : "pr-3", focusRingInset)}
140
140
  >
141
141
  <Icon aria-hidden className="size-3.5 shrink-0 text-muted-foreground" />
142
142
  <span className="flex min-w-0">
@@ -146,7 +146,7 @@ export function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open file
146
146
  {hint && <span className="min-w-0 truncate text-muted-foreground">· {hint}</span>}
147
147
  {tab.dirty && <span aria-hidden className="size-1.5 shrink-0 rounded-full bg-[var(--accent-text)]" />}
148
148
  </button>
149
- <button
149
+ {onClose && <button
150
150
  type="button"
151
151
  tabIndex={-1}
152
152
  aria-label={`Close ${tab.name}`}
@@ -158,7 +158,7 @@ export function FileTabs({ tabs, activeId, onSelect, onClose, label = "Open file
158
158
  )}
159
159
  >
160
160
  <X aria-hidden className="size-3" />
161
- </button>
161
+ </button>}
162
162
  </div>
163
163
  );
164
164
  })}