@ai-matrx/canvas 0.8.1 → 0.8.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,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.2
4
+ ### Unreleased
5
+
6
+ - The tab strip follows the tablist keyboard pattern: Left/Right (wrapping), Home and End move to and open the neighbouring tab. Only the active tab is in the Tab order, so a background tab was unreachable without a mouse.
7
+ - Consumer action: none.
8
+
3
9
  ## 0.8.1
4
10
 
5
11
  Live check of 0.8.0 (1440px, canvas expanded, 5 tabs): a 1428px window strip drew 127px tabs — a `flex-basis` alone let the tab list size itself to the names.
@@ -231,3 +237,4 @@ One canvas for the web app and the desktop app: the package now owns the pane ch
231
237
 
232
238
  - Replace workspace Canvas imports with `@ai-matrx/canvas` at `latest`; remove source aliases and transpile overrides.
233
239
  - Import `@ai-matrx/canvas/styles.css` and optionally `@ai-matrx/canvas/tokens.css`; keep the existing host identity, store and theme ports.
240
+
package/dist/react.cjs CHANGED
@@ -3324,24 +3324,49 @@ function TabStrip({
3324
3324
  "data-overflow": overflow ? "" : void 0,
3325
3325
  style: { ["--mxc-tab-min"]: `${CANVAS_TAB_MIN_WIDTH}px` },
3326
3326
  children: [
3327
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: list, className: "mxc-tabs", role: "tablist", "aria-label": "Canvas tabs", "aria-multiselectable": joined ? true : void 0, children: entries.map(
3328
- (entry) => entry.type === "tab" ? tabView(entry.tab) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3329
- "div",
3330
- {
3331
- className: "mxc-tab-group",
3332
- "data-split": "",
3333
- role: "presentation",
3334
- style: { ["--mxc-group-n"]: entry.tabs.length },
3335
- children: entry.tabs.map(tabView)
3336
- },
3337
- `split:${entry.tabs.map((tab) => tab.itemId).join("|")}`
3338
- )
3339
- ) }),
3327
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3328
+ "div",
3329
+ {
3330
+ ref: list,
3331
+ className: "mxc-tabs",
3332
+ role: "tablist",
3333
+ "aria-label": "Canvas tabs",
3334
+ "aria-multiselectable": joined ? true : void 0,
3335
+ onKeyDown: moveTabFocus,
3336
+ children: entries.map(
3337
+ (entry) => entry.type === "tab" ? tabView(entry.tab) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
3338
+ "div",
3339
+ {
3340
+ className: "mxc-tab-group",
3341
+ "data-split": "",
3342
+ role: "presentation",
3343
+ style: { ["--mxc-group-n"]: entry.tabs.length },
3344
+ children: entry.tabs.map(tabView)
3345
+ },
3346
+ `split:${entry.tabs.map((tab) => tab.itemId).join("|")}`
3347
+ )
3348
+ )
3349
+ }
3350
+ ),
3340
3351
  overflow ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TabListMenu, { tabs, activeItemId }) : null
3341
3352
  ]
3342
3353
  }
3343
3354
  );
3344
3355
  }
3356
+ function moveTabFocus(event) {
3357
+ const keys = ["ArrowLeft", "ArrowRight", "Home", "End"];
3358
+ if (!keys.includes(event.key) || event.altKey || event.ctrlKey || event.metaKey) return;
3359
+ const tabs = [...event.currentTarget.querySelectorAll('[role="tab"]')];
3360
+ const at = tabs.findIndex((tab) => tab === event.target || tab.contains(event.target));
3361
+ if (at < 0 || tabs.length < 2) return;
3362
+ event.preventDefault();
3363
+ const rtl = getComputedStyle(event.currentTarget).direction === "rtl";
3364
+ const step = event.key === "ArrowRight" !== rtl ? 1 : -1;
3365
+ const next = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : (at + step + tabs.length) % tabs.length;
3366
+ const target = tabs[next];
3367
+ target?.focus();
3368
+ target?.click();
3369
+ }
3345
3370
  function TabListMenu({ tabs, activeItemId }) {
3346
3371
  const canvas = useCanvas();
3347
3372
  const { ports, layer } = useCanvasInternals();