@primitiv-ui/react 0.1.40 → 0.1.41

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.
@@ -132,6 +132,11 @@ export declare namespace TabsList {
132
132
  * move focus without switching the panel — `Enter` or `Space` confirms the
133
133
  * selection. Use manual mode for panels that are expensive to render.
134
134
  *
135
+ * **Your `onClick` and `onKeyDown`** run *after* the built-in activation and
136
+ * keyboard navigation, and cannot veto them: by the time your `onKeyDown` sees
137
+ * a handled key, `event.defaultPrevented` is already `true`. Use them to observe
138
+ * or to add behaviour, not to replace the tab contract.
139
+ *
135
140
  * **`asChild` prop.** Pass `asChild` to render an arbitrary child element
136
141
  * instead of the default `<button>`. All tab ARIA attributes, event handlers,
137
142
  * and the roving `tabIndex` are merged onto the child element following the
@@ -171,7 +176,7 @@ export declare namespace TabsList {
171
176
  * </Tabs.Trigger>
172
177
  * ```
173
178
  */
174
- export declare function TabsTrigger<T extends HTMLElement = HTMLButtonElement>({ ref: externalRef, children, className, value, onClick, disabled, asChild, ...rest }: TabsTriggerProps<T>): ReactElement;
179
+ export declare function TabsTrigger<T extends HTMLElement = HTMLButtonElement>({ ref: externalRef, children, className, value, onClick, onKeyDown, disabled, asChild, ...rest }: TabsTriggerProps<T>): ReactElement;
175
180
  export declare namespace TabsTrigger {
176
181
  var displayName: string;
177
182
  }
package/dist/Tabs/Tabs.js CHANGED
@@ -158,6 +158,11 @@ TabsList.displayName = "TabsList";
158
158
  * move focus without switching the panel — `Enter` or `Space` confirms the
159
159
  * selection. Use manual mode for panels that are expensive to render.
160
160
  *
161
+ * **Your `onClick` and `onKeyDown`** run *after* the built-in activation and
162
+ * keyboard navigation, and cannot veto them: by the time your `onKeyDown` sees
163
+ * a handled key, `event.defaultPrevented` is already `true`. Use them to observe
164
+ * or to add behaviour, not to replace the tab contract.
165
+ *
161
166
  * **`asChild` prop.** Pass `asChild` to render an arbitrary child element
162
167
  * instead of the default `<button>`. All tab ARIA attributes, event handlers,
163
168
  * and the roving `tabIndex` are merged onto the child element following the
@@ -197,8 +202,8 @@ TabsList.displayName = "TabsList";
197
202
  * </Tabs.Trigger>
198
203
  * ```
199
204
  */
200
- export function TabsTrigger({ ref: externalRef, children, className = "", value, onClick, disabled = false, asChild = false, ...rest }) {
201
- const { buttonRef, triggerId, panelId, isActive, orientation, state, tabIndex, handleClick, handleKeyDown, } = useTabsTrigger({ value, onClick, disabled });
205
+ export function TabsTrigger({ ref: externalRef, children, className = "", value, onClick, onKeyDown, disabled = false, asChild = false, ...rest }) {
206
+ const { buttonRef, triggerId, panelId, isActive, orientation, state, tabIndex, handleClick, handleKeyDown, } = useTabsTrigger({ value, onClick, onKeyDown, disabled });
202
207
  // Compose our internal ref with any external ref the consumer passes.
203
208
  // The external ref is cast to match the internal ref's element type —
204
209
  // RefObject<T> is invariant in React's types, but at runtime the callback
@@ -1,6 +1,6 @@
1
- import { MouseEvent } from "react";
1
+ import { type KeyboardEvent, MouseEvent } from "react";
2
2
  import { TabsTriggerProps } from "../types.js";
3
- export declare function useTabsTrigger({ value, onClick, disabled, }: Pick<TabsTriggerProps, "value" | "onClick" | "disabled">): {
3
+ export declare function useTabsTrigger({ value, onClick, onKeyDown, disabled, }: Pick<TabsTriggerProps, "value" | "onClick" | "onKeyDown" | "disabled">): {
4
4
  buttonRef: import("react").RefObject<HTMLButtonElement | null>;
5
5
  triggerId: string;
6
6
  panelId: string;
@@ -9,5 +9,5 @@ export declare function useTabsTrigger({ value, onClick, disabled, }: Pick<TabsT
9
9
  state: string;
10
10
  tabIndex: number;
11
11
  handleClick: (e: MouseEvent<HTMLButtonElement>) => void;
12
- handleKeyDown: (e: import("react").KeyboardEvent<HTMLElement>) => void;
12
+ handleKeyDown: (e: KeyboardEvent<HTMLButtonElement>) => void;
13
13
  };
@@ -3,7 +3,7 @@ import { useRef, useEffect, useCallback, } from "react";
3
3
  import { useRovingTabindex } from "../../hooks/index.js";
4
4
  import { getTriggerAndPanelIds } from "../utils.js";
5
5
  import { useTabsContext } from "./useTabsContext.js";
6
- export function useTabsTrigger({ value, onClick, disabled, }) {
6
+ export function useTabsTrigger({ value, onClick, onKeyDown, disabled, }) {
7
7
  const { orientation, dir, activationMode, activeValue, isControlled, setActiveValue, onValueChange, onChange, tabsId, registerTrigger, triggerValues, disabledTriggerValues, focusTrigger, } = useTabsContext();
8
8
  const isActive = activeValue === value;
9
9
  const { triggerId, panelId } = getTriggerAndPanelIds(tabsId, value);
@@ -49,7 +49,7 @@ export function useTabsTrigger({ value, onClick, disabled, }) {
49
49
  // *land* on disabled tabs (focus moves there) without activating them —
50
50
  // that's the Tabs-specific keyboard contract, distinct from RadioGroup
51
51
  // and Accordion which both skip disabled siblings entirely.
52
- const { handleKeyDown } = useRovingTabindex({
52
+ const { handleKeyDown: navigate } = useRovingTabindex({
53
53
  orientation,
54
54
  dir,
55
55
  navigable: triggerValues,
@@ -69,6 +69,13 @@ export function useTabsTrigger({ value, onClick, disabled, }) {
69
69
  focusTrigger(targetValue);
70
70
  },
71
71
  });
72
+ // A consumer onKeyDown runs AFTER the built-in navigation and cannot veto it,
73
+ // the same contract handleClick gives onClick. It used to be spread over this
74
+ // handler and silently disabled arrow-key navigation.
75
+ function handleKeyDown(e) {
76
+ navigate(e);
77
+ onKeyDown?.(e);
78
+ }
72
79
  return {
73
80
  buttonRef,
74
81
  triggerId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitiv-ui/react",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "description": "Headless, accessible React components built on the WAI-ARIA authoring patterns. Zero styles ship with this package — bring your own (CSS, Tailwind, CSS-in-JS, design tokens).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",