@ai-matrx/canvas 0.7.0 → 0.7.2

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,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.2
4
+
5
+ Measured live on 0.7.1 (phone 375px; a 363px canvas after a reload):
6
+
7
+ - **A tab's name ends before its close.** A background tab's close used to overlay the name's end (a fade), and on touch every tab showed one, so a name ran under it ("Quick Ch" cut at 103px, close at 90px). Now the close's room is reserved while it shows (hover / focus), and on touch (no hover) only the active tab shows a close - background names keep the room.
8
+ - **The tab fit is re-read until layout settles.** A reload measured the strip before fonts and the header's actions had settled, so two tabs that fit showed "Quick ..." plus one under "All tabs". The strip is re-measured on its own resize, when `document.fonts.ready` resolves, two frames after mount, and whenever the tab count changes.
9
+
10
+ ### Consumer action
11
+
12
+ - None.
13
+
14
+ ## 0.7.1
15
+
16
+ Measured live on 0.7.0 (a 480px strip, six tabs):
17
+
18
+ - **The active tab never runs under "All tabs".** Its `flex-shrink: 0.2` made it the last tab still shrinking, and the flex algorithm then hands such an item only that fraction of the overflow — it stayed 25px too wide, its close clipped beside the button. Priority width is now its higher floor alone.
19
+ - **Floors hold ~7 letters:** "Messa…" at 78px. `CANVAS_TAB_MIN_WIDTH` 88px ("Messag…"), `CANVAS_ACTIVE_TAB_MIN_WIDTH` 112px; the fit reserves 36px for the "All tabs" button.
20
+
21
+ ### Consumer action
22
+
23
+ - None.
24
+
3
25
  ## 0.7.0
4
26
 
5
27
  Second independent live sweep (admin, clone):
package/dist/react.cjs CHANGED
@@ -3180,9 +3180,9 @@ function SingleTitle({ item, kind }) {
3180
3180
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "mxc-tab-close", "data-slot": "browser-tab-close", "aria-label": `Close ${title}`, onClick: () => canvas.close(item.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
3181
3181
  ] });
3182
3182
  }
3183
- var CANVAS_TAB_MIN_WIDTH = 78;
3184
- var CANVAS_ACTIVE_TAB_MIN_WIDTH = 100;
3185
- var TAB_LIST_BUTTON_ROOM = 30;
3183
+ var CANVAS_TAB_MIN_WIDTH = 88;
3184
+ var CANVAS_ACTIVE_TAB_MIN_WIDTH = 112;
3185
+ var TAB_LIST_BUTTON_ROOM = 36;
3186
3186
  var TAB_GAP = 2;
3187
3187
  function fitCanvasTabs(count, activeIndex, width) {
3188
3188
  if (count <= 0) return { start: 0, end: 0, overflow: false, compact: false };
@@ -3199,15 +3199,30 @@ function TabStrip({ tabs, activeItemId }) {
3199
3199
  const canvas = useCanvas();
3200
3200
  const strip = (0, import_react9.useRef)(null);
3201
3201
  const [width, setWidth] = (0, import_react9.useState)(0);
3202
+ const read = (0, import_react9.useRef)(() => {
3203
+ });
3202
3204
  useIsoLayoutEffect4(() => {
3203
3205
  const el = strip.current;
3204
3206
  if (!el) return void 0;
3205
- const read = () => setWidth(Math.floor(el.getBoundingClientRect().width));
3206
- read();
3207
- const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(read);
3207
+ let live = true;
3208
+ const measure = () => {
3209
+ if (live) setWidth(Math.floor(el.getBoundingClientRect().width));
3210
+ };
3211
+ read.current = measure;
3212
+ measure();
3213
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
3208
3214
  observer?.observe(el);
3209
- return () => observer?.disconnect();
3215
+ void document.fonts?.ready?.then(measure);
3216
+ const frame2 = typeof requestAnimationFrame === "undefined" ? 0 : requestAnimationFrame(() => requestAnimationFrame(measure));
3217
+ return () => {
3218
+ live = false;
3219
+ observer?.disconnect();
3220
+ if (frame2 && typeof cancelAnimationFrame !== "undefined") cancelAnimationFrame(frame2);
3221
+ };
3210
3222
  }, []);
3223
+ useIsoLayoutEffect4(() => {
3224
+ read.current();
3225
+ }, [tabs.length]);
3211
3226
  const activeIndex = Math.max(0, tabs.findIndex((tab) => tab.itemId === activeItemId));
3212
3227
  const fit = fitCanvasTabs(tabs.length, activeIndex, width);
3213
3228
  const shown = tabs.slice(fit.start, fit.end);