@ai-matrx/canvas 0.6.0 → 0.6.1

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,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.1
4
+
5
+ Live measurement of 0.6.0 (a 756px pane, five tabs, Quick Chat's header actions present):
6
+
7
+ - **The strip takes the header's free width** (`flex: 1`). Sized to its own intrinsic width, the browser undercut every text tab by 2–3px and cut each name; now tabs lay out in real room ("+" sits at the strip's end).
8
+ - **No ellipsis.** System fonts overflow their intrinsic width by a fraction of a pixel, which put "…" on names that fit ("Quick Ch…"). Titles clip; a name really cut (`data-truncated` on the tab, measured: more than 1px) fades at its end.
9
+ - **Room for names:** only the active tab reserves its (always shown) close's room — a background tab's close overlays on hover with the name fading under it; icon gap 4px; an empty leading slot takes no room and no gap (the actions keep the end with `margin-left: auto`).
10
+
11
+ ### Consumer action
12
+
13
+ - None.
14
+
3
15
  ## 0.6.0
4
16
 
5
17
  Independent live sweep (admin, clone):
package/dist/react.cjs CHANGED
@@ -2015,6 +2015,21 @@ var ChevronRightIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Glyph
2015
2015
 
2016
2016
  // src/react/chrome.tsx
2017
2017
  var import_jsx_runtime4 = require("react/jsx-runtime");
2018
+ var useIsoLayoutEffect = typeof window === "undefined" ? import_react3.useEffect : import_react3.useLayoutEffect;
2019
+ function useTruncated(title) {
2020
+ const ref = (0, import_react3.useRef)(null);
2021
+ const [truncated, setTruncated] = (0, import_react3.useState)(false);
2022
+ useIsoLayoutEffect(() => {
2023
+ const el = ref.current;
2024
+ if (!el) return void 0;
2025
+ const check = () => setTruncated(el.scrollWidth - el.clientWidth > 1);
2026
+ check();
2027
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(check);
2028
+ observer?.observe(el);
2029
+ return () => observer?.disconnect();
2030
+ }, [title]);
2031
+ return { ref, truncated };
2032
+ }
2018
2033
  var cx = (...names) => names.filter(Boolean).join(" ");
2019
2034
  function useTooltip(text) {
2020
2035
  const internals = useOptionalCanvasInternals();
@@ -2154,6 +2169,7 @@ function CanvasPanelEmpty({ children, className }) {
2154
2169
  }
2155
2170
  var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon, note, active, onSelect, onClose, className, onKeyDown, onClick, ...rest }, ref) {
2156
2171
  const shown = title || "New tab";
2172
+ const name = useTruncated(shown);
2157
2173
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2158
2174
  "div",
2159
2175
  {
@@ -2163,6 +2179,7 @@ var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon,
2163
2179
  tabIndex: active ? 0 : -1,
2164
2180
  "data-slot": "browser-tab",
2165
2181
  "data-active": active ? "" : void 0,
2182
+ "data-truncated": name.truncated ? "" : void 0,
2166
2183
  title: shown,
2167
2184
  className: cx("mxc-tab", className),
2168
2185
  ...rest,
@@ -2180,7 +2197,7 @@ var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon,
2180
2197
  },
2181
2198
  children: [
2182
2199
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-icon", children: icon }),
2183
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-title", children: shown }),
2200
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { ref: name.ref, className: "mxc-tab-title", children: shown }),
2184
2201
  note ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-note", "data-slot": "browser-tab-note", children: note }) : null,
2185
2202
  onClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2186
2203
  "button",
@@ -2512,7 +2529,7 @@ function useSlotSize(slots, paneId) {
2512
2529
 
2513
2530
  // src/react/bodies.tsx
2514
2531
  var import_jsx_runtime6 = require("react/jsx-runtime");
2515
- var useIsoLayoutEffect = typeof window === "undefined" ? import_react7.useEffect : import_react7.useLayoutEffect;
2532
+ var useIsoLayoutEffect2 = typeof window === "undefined" ? import_react7.useEffect : import_react7.useLayoutEffect;
2516
2533
  var LAZY = /* @__PURE__ */ Symbol.for("ai-matrx.canvas.lazy");
2517
2534
  function kindComponent(kind) {
2518
2535
  if (kind.component) return kind.component;
@@ -2629,8 +2646,8 @@ function CanvasBodyLayer() {
2629
2646
  const [placement] = (0, import_react7.useState)(
2630
2647
  () => slots ? createPlacement(() => root.current, slots, () => layer.native.remeasure()) : null
2631
2648
  );
2632
- useIsoLayoutEffect(() => placement?.place());
2633
- useIsoLayoutEffect(() => slots && placement ? slots.subscribe(placement.place) : void 0, [slots, placement]);
2649
+ useIsoLayoutEffect2(() => placement?.place());
2650
+ useIsoLayoutEffect2(() => slots && placement ? slots.subscribe(placement.place) : void 0, [slots, placement]);
2634
2651
  const shape = parseSignature(signature);
2635
2652
  if (!slots || !placement || !shape) return null;
2636
2653
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: root, className: "mxc-bodies", "data-mxc-bodies": windowId, children: shape.placed.map(({ hostId, itemId, paneId, active, kept }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
@@ -2712,7 +2729,7 @@ var BodyHost = (0, import_react7.memo)(function BodyHost2({
2712
2729
  const mounted = kind?.unmountWhenHidden ? visible : everShown;
2713
2730
  const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
2714
2731
  const drop = usePaneDrop(paneId, () => slots.section(paneId));
2715
- useIsoLayoutEffect(() => {
2732
+ useIsoLayoutEffect2(() => {
2716
2733
  const el = element.current;
2717
2734
  if (!placement || !el) return void 0;
2718
2735
  return placement.register(hostId, { element: el, paneId });
@@ -2810,8 +2827,8 @@ function NativeBody({ itemId, windowId, visible, children }) {
2810
2827
  const rect = { ...toCanvasRect(box), devicePixelRatio: window.devicePixelRatio || 1 };
2811
2828
  layer.native.report(itemId, rect, { visible: !layer.isBlocked(), windowId });
2812
2829
  };
2813
- useIsoLayoutEffect(() => measure.current());
2814
- useIsoLayoutEffect(() => {
2830
+ useIsoLayoutEffect2(() => measure.current());
2831
+ useIsoLayoutEffect2(() => {
2815
2832
  const el = ref.current;
2816
2833
  const run = () => measure.current();
2817
2834
  const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(run);
@@ -2867,7 +2884,7 @@ var ItemBoundary = class extends import_react7.Component {
2867
2884
  var import_react8 = require("react");
2868
2885
  var Menu = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
2869
2886
  var import_jsx_runtime7 = require("react/jsx-runtime");
2870
- var useIsoLayoutEffect2 = typeof window === "undefined" ? import_react8.useEffect : import_react8.useLayoutEffect;
2887
+ var useIsoLayoutEffect3 = typeof window === "undefined" ? import_react8.useEffect : import_react8.useLayoutEffect;
2871
2888
  function itemTitle(item, kind) {
2872
2889
  if (item.title) return item.title;
2873
2890
  if (item.kind === CANVAS_LAUNCHER_KIND) return "New tab";
@@ -2924,7 +2941,7 @@ function CanvasPaneView({ paneId }) {
2924
2941
  const bodyRef = (0, import_react8.useRef)(null);
2925
2942
  const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
2926
2943
  const drop = usePaneDrop(paneId, () => sectionRef.current);
2927
- useIsoLayoutEffect2(() => {
2944
+ useIsoLayoutEffect3(() => {
2928
2945
  const body = bodyRef.current;
2929
2946
  const section = sectionRef.current;
2930
2947
  if (body) slots.set(paneId, body);
@@ -3014,7 +3031,7 @@ function TabStrip({ tabs, activeItemId }) {
3014
3031
  setOverflow((prev) => prev.start === start && prev.end === end ? prev : { start, end });
3015
3032
  };
3016
3033
  const tabKey = tabs.map((tab) => tab.itemId).join("|");
3017
- useIsoLayoutEffect2(() => {
3034
+ useIsoLayoutEffect3(() => {
3018
3035
  const el = strip.current;
3019
3036
  if (!el) return void 0;
3020
3037
  const reveal = () => {
@@ -3190,7 +3207,7 @@ function safeMenu(build) {
3190
3207
 
3191
3208
  // src/react/CanvasColumn.tsx
3192
3209
  var import_jsx_runtime8 = require("react/jsx-runtime");
3193
- var useIsoLayoutEffect3 = typeof window === "undefined" ? import_react9.useEffect : import_react9.useLayoutEffect;
3210
+ var useIsoLayoutEffect4 = typeof window === "undefined" ? import_react9.useEffect : import_react9.useLayoutEffect;
3194
3211
  function subscribeViewport(listener) {
3195
3212
  window.addEventListener("resize", listener);
3196
3213
  return () => window.removeEventListener("resize", listener);
@@ -3348,7 +3365,7 @@ function LayoutNodeView({ node }) {
3348
3365
  }
3349
3366
  function useMeasuredWidth(ref, enabled) {
3350
3367
  const [width, setWidth] = (0, import_react9.useState)(0);
3351
- useIsoLayoutEffect3(() => {
3368
+ useIsoLayoutEffect4(() => {
3352
3369
  const el = ref.current;
3353
3370
  if (!enabled || !el) return;
3354
3371
  setWidth(el.getBoundingClientRect().width);