@sprocketui-react/button 1.1.0 → 1.2.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
  <a href="https://sprocketui.com">
3
- <img alt="Necto Logo" src="https://avatars.githubusercontent.com/u/206497492?s=100&v=4">
3
+ <img alt="Sprocket Logo" src="https://avatars.githubusercontent.com/u/206497492?s=100&v=4">
4
4
  <a>
5
5
 
6
6
  <h2>Sprocket UI React - Button</h2>
@@ -16,4 +16,5 @@
16
16
  <a aria-label="License" href="https://github.com/sprocketui/NodeKit/blob/main/LICENSE">
17
17
  <img src="https://img.shields.io/badge/License-MIT-97CA25.svg?style=for-the-badge">
18
18
  </a>
19
+ <img src="https://img.shields.io/badge/-ReactJs-61DAFB?logo=react&logoColor=white&style=for-the-badge">
19
20
  </div>
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var L=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var et=(t,e)=>{for(var n in e)L(t,n,{get:e[n],enumerable:!0})},ot=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Y(e))!tt.call(t,o)&&o!==n&&L(t,o,{get:()=>e[o],enumerable:!(s=Q(e,o))||s.enumerable});return t};var rt=t=>ot(L({},"__esModule",{value:!0}),t);var nt={};et(nt,{Button:()=>C,ButtonContext:()=>m,SprocketButton:()=>C,SprocketButtonContext:()=>m,useButton:()=>P,useButtonContext:()=>w,useSprocketButton:()=>P,useSprocketButtonContext:()=>w});module.exports=rt(nt);var p=require("@necto-react/hooks"),a=require("@necto/dom"),k=require("@necto/mergers"),_=require("@necto-react/helpers");var F=["rel","href","ping","target","download","hrefLang","referrerPolicy"],M=["id","form","name","value","formAction","formEncType","formMethod","formTarget","formNoValidate"];function O(t,e){return t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function S({prefix:t=":sprocket:=",component:e,variant:n,state:s,unique:o,obscure:f}){if(!e)throw new Error("Component context is required!");let u=[t+O(e,!1)];return n&&u.push(O(n,!1)),Array.isArray(s)&&s.length&&u.push(...s.map(l=>O(l,!1))),o&&u.push(Math.random().toString(36).slice(2,8)),f&&u.push(Math.random().toString(36).slice(2,16)),u.join("--")}var H=a.HTMLElements.Button;function P(t,e){let{rel:n,href:s,target:o,autoFocus:f,focusDisabled:u,preventFocusOnPress:l,isDisabled:r=!1,type:R="button",as:x=H,elementType:i=x||H,onClick:c,onPress:y,onPressStart:T,onPressEnd:E,onPressUp:B,onPressChange:$}=t,g;i===a.HTMLElements.Button?g={type:R,disabled:r}:g={role:"button",href:i===a.HTMLElements.A&&!r?s:void 0,target:i===a.HTMLElements.A?o:void 0,type:i===a.HTMLElements.Input?R:void 0,disabled:i===a.HTMLElements.Input?r:void 0,"aria-disabled":!r||i===a.HTMLElements.Input?void 0:r,rel:i===a.HTMLElements.A?n:void 0};let{hoverProps:G,isHovered:W}=(0,p.useHover)({...t,isDisabled:r}),{focusProps:X,isFocused:q,isFocusVisible:z}=(0,p.useFocusRing)({autoFocus:f}),{focusableProps:A}=(0,p.useFocusable)(t,e),{pressProps:Z,isPressed:J}=(0,p.usePress)({ref:e,isDisabled:r,preventFocusOnPress:l,onPressStart:T,onPressEnd:E,onPressChange:$,onPress:y,onPressUp:B,onClick:c});u&&(A.tabIndex=r?-1:A.tabIndex);let K=(0,k.mergeProps)(A,Z,G,X,(0,_.filterDOMProps)(t,{allowLabelableProps:!0,allowedLabelableProps:new Set([]),allowedLinkProps:new Set(F),extraAllowedProps:new Set(M)}));return{isFocused:q,isPressed:J,isHovered:W,isDisabled:r,isFocusVisible:z,elementType:i,buttonProps:(0,k.mergeProps)(K,g)}}var v=require("react"),m=(0,v.createContext)(null);var N=require("react");function w(){return(0,N.useContext)(m)}var h=require("@necto/strings"),I=require("@necto/mergers"),b=require("react");var D=require("@necto-react/components");var d=require("@necto-react/hooks"),V=require("react/jsx-runtime"),j="Button";function U(t,e){[t,e]=(0,d.useContextProps)({props:t,ref:e,context:m});let{buttonProps:n,isHovered:s,isPressed:o,isFocused:f,isDisabled:u,elementType:l,isFocusVisible:r}=P(t,e),R=(0,d.useId)({defaultId:n.id}),x=(0,d.useRenderer)({...t,values:{isHovered:s,isPressed:o,isFocused:f,isFocusVisible:r,isDisabled:u},defaultClassName:S({component:j}),style:c=>({...t.style instanceof Function?t.style(c):t.style})}),i=(0,b.useMemo)(()=>{let c={hover:s,focus:f,focusVisible:r,disabled:u,pressed:o},y={},T=[];for(let[E,B]of Object.entries(c))typeof B=="boolean"&&(y[`data-${(0,h.kebabCase)(E)}`]=B?String(!0):void 0,B&&T.push((0,h.kebabCase)(E)));return{...y,"data-sprocket-state":T.join(" ")}},[s,f,r,u,o]);return(0,V.jsxs)(D.Primitive,{ref:e,as:l,...x,...(0,I.mergeProps)(n,i),id:R,slot:t.slot||void 0,children:["''",x.children]})}var C=Object.assign((0,b.forwardRef)((t,e)=>U(t,e)),{Root:(0,b.forwardRef)((t,e)=>U(t,e))});C.displayName=j;0&&(module.exports={Button,ButtonContext,SprocketButton,SprocketButtonContext,useButton,useButtonContext,useSprocketButton,useSprocketButtonContext});
1
+ "use strict";var H=Object.defineProperty;var gt=Object.getOwnPropertyDescriptor;var Bt=Object.getOwnPropertyNames;var Tt=Object.prototype.hasOwnProperty;var Pt=(t,e)=>{for(var o in e)H(t,o,{get:e[o],enumerable:!0})},yt=(t,e,o,u)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Bt(e))!Tt.call(t,r)&&r!==o&&H(t,r,{get:()=>e[r],enumerable:!(u=gt(e,r))||u.enumerable});return t};var Et=t=>yt(H({},"__esModule",{value:!0}),t);var Ot={};Pt(Ot,{Button:()=>C,ButtonContext:()=>R,SprocketButton:()=>C,SprocketButtonContext:()=>R,SprocketToggleButton:()=>S,SprocketToggleButtonContext:()=>b,ToggleButton:()=>S,ToggleButtonContext:()=>b,useButton:()=>B,useSprocketButton:()=>B,useSprocketToggleButton:()=>O,useToggleButton:()=>O});module.exports=Et(Ot);var X=require("react"),R=(0,X.createContext)(null);var Q=require("react"),b=(0,Q.createContext)(null);var m=require("@necto-react/hooks"),K=require("defu"),g=require("@necto/dom"),G=require("@necto/mergers"),Y=require("@necto-react/helpers");var q=["rel","href","ping","target","download","hrefLang","referrerPolicy"],z=["id","form","name","value","defaultValue","formAction","formEncType","formMethod","formTarget","formNoValidate"];function L(t,e=!1){let o=t.replace(/\p{Lu}/gu,u=>`-${u.toLowerCase()}`);return e?o:o.startsWith("-")?o.slice(1):o}L.reverse=t=>t.replace(/-\p{Ll}/gu,e=>e.slice(1).toUpperCase());var Rt=6,bt=14;function $(t){return Math.random().toString(36).slice(2,2+t)}function U({prefix:t="__sprocket:=[",component:e,variant:o,state:u,unique:r,obscure:a}){let d=e?.trim();if(!d)throw new Error("Component context is required!");let p=1+(o?1:0)+(u?.length??0)+(r?1:0)+(a?1:0),n=new Array(p),s=0;if(n[s++]=t+L(d,!1)+"]",o&&(n[s++]=L(o,!1)),u?.length)for(let i of u)n[s++]=L(i,!1);return r&&(n[s++]=$(Rt)),a&&(n[s++]=$(bt)),n.join("--")}var J=require("@necto/dom"),v="Button",D="ToggleButton",I=J.HTMLElements.Button;function B(t,e){let{rel:o,href:u,target:r,autoFocus:a,focusDisabled:d,preventFocusOnPress:p,isDisabled:n,isPending:s,type:i,elementType:l,onClick:f,onPress:T,onPressStart:x,onPressEnd:W,onPressUp:_,onPressChange:h}=(0,K.defu)(t,{isDisabled:!1,isPending:!1,type:"button",as:I,elementType:t.elementType||t.as||I}),P;l===g.HTMLElements.Button?P={type:i,disabled:n}:P={role:"button",href:l===g.HTMLElements.A&&!n?u:void 0,target:l===g.HTMLElements.A?r:void 0,type:l===g.HTMLElements.Input?i:void 0,disabled:l===g.HTMLElements.Input?n:void 0,"aria-disabled":!n||l===g.HTMLElements.Input?void 0:n,rel:l===g.HTMLElements.A?o:void 0};let{hoverProps:at,isHovered:F}=(0,m.useHover)({...t,isDisabled:n}),{focusProps:pt,isFocused:M,isFocusVisible:N}=(0,m.useFocusRing)({autoFocus:a}),{focusableProps:w}=(0,m.useFocusable)(t,e),{pressProps:dt,isPressed:k}=(0,m.usePress)({ref:e,isDisabled:n||s,preventFocusOnPress:p,onPressStart:x,onPressEnd:W,onPressChange:h,onPress:T,onPressUp:_,onClick:f}),ft=(0,m.useAriaProps)({isBusy:s||void 0});d&&(w.tabIndex=n?-1:w.tabIndex);let mt=(0,G.mergeProps)(w,dt,at,pt,(0,Y.filterDOMProps)(t,{allowLabelableProps:!0,allowedLabelableProps:new Set([]),allowedLinkProps:new Set(q),extraAllowedProps:new Set(z)})),c=[];F&&c.push("hover"),M&&c.push("focus"),N&&c.push("focus-visible"),n&&c.push("disabled"),k&&c.push("pressed"),s&&c.push("pending");let ct={"data-hover":F?"true":void 0,"data-focus":M?"true":void 0,"data-focus-visible":N?"true":void 0,"data-disabled":n?"true":void 0,"data-pressed":k?"true":void 0,"data-pending":s?"true":void 0,"data-sprocket-state":c.length>0?c.join(" "):void 0};return{isFocused:M,isPressed:k,isHovered:F,isDisabled:n,isPending:s,isFocusVisible:N,elementType:l,buttonProps:(0,G.mergeProps)(mt,P,ft,ct)}}var Z=require("defu"),tt=require("@necto/mergers"),A=require("react");function O(t,e){let{isSelected:o,defaultSelected:u,onChange:r,onPress:a,...d}=(0,Z.defu)(t,{defaultSelected:!1}),p=o!==void 0,[n,s]=(0,A.useState)(u),i=p?o:n,l=(0,A.useCallback)(h=>{let P=!i;p||s(P),r?.(P),a?.(h)},[i,p,r,a]),f=B({...d,onPress:l},e),T=[];i&&T.push("selected");let x={"data-selected":i?"true":void 0},_=[f.buttonProps["data-sprocket-state"],...T].filter(Boolean).join(" ");return x["data-sprocket-state"]=_||void 0,{...f,isSelected:i,buttonProps:(0,tt.mergeProps)(f.buttonProps,{"aria-pressed":i,...x})}}var j=require("react"),ot=require("@necto/mergers");var nt=require("@necto-react/components"),y=require("@necto-react/hooks");var rt=require("react/jsx-runtime");function et(t,e){[t,e]=(0,y.useContextProps)({props:t,ref:e,context:R});let{buttonProps:o,isHovered:u,isPressed:r,isFocused:a,isDisabled:d,isPending:p,elementType:n,isFocusVisible:s}=B(t,e),i=(0,y.useId)({defaultId:o.id}),l=(0,y.useRenderer)({...t,values:{isHovered:u,isPressed:r,isFocused:a,isFocusVisible:s,isDisabled:d,isPending:p},defaultClassName:U({component:v}),style:f=>({...t.style instanceof Function?t.style(f):t.style})});return(0,rt.jsx)(nt.Primitive,{ref:e,as:n,...l,...(0,ot.mergeProps)(o),id:i,slot:t.slot||void 0,children:l.children})}var C=Object.assign((0,j.forwardRef)((t,e)=>et(t,e)),{Root:(0,j.forwardRef)((t,e)=>et(t,e))});C.displayName=v;var V=require("react"),ut=require("@necto/mergers");var it=require("@necto-react/components"),E=require("@necto-react/hooks");var lt=require("react/jsx-runtime");function st(t,e){[t,e]=(0,E.useContextProps)({props:t,ref:e,context:b});let{buttonProps:o,isHovered:u,isPressed:r,isFocused:a,isDisabled:d,isPending:p,isSelected:n,elementType:s,isFocusVisible:i}=O(t,e),l=(0,E.useId)({defaultId:o.id}),f=(0,E.useRenderer)({...t,values:{isHovered:u,isPressed:r,isFocused:a,isFocusVisible:i,isDisabled:d,isPending:p,isSelected:n},defaultClassName:U({component:D}),style:T=>({...t.style instanceof Function?t.style(T):t.style})});return(0,lt.jsx)(it.Primitive,{ref:e,as:s,...f,...(0,ut.mergeProps)(o),id:l,slot:t.slot||void 0,children:f.children})}var S=Object.assign((0,V.forwardRef)((t,e)=>st(t,e)),{Root:(0,V.forwardRef)((t,e)=>st(t,e))});S.displayName=D;0&&(module.exports={Button,ButtonContext,SprocketButton,SprocketButtonContext,SprocketToggleButton,SprocketToggleButtonContext,ToggleButton,ToggleButtonContext,useButton,useSprocketButton,useSprocketToggleButton,useToggleButton});
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
- import { ElementType, HTMLAttributes, RefObject, Context, ForwardRefExoticComponent, RefAttributes } from 'react';
2
- import { ButtonOptions } from '@sprocketui-types/button';
1
+ import * as react from 'react';
2
+ import { ElementType, HTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, RefObject, ForwardRefExoticComponent, RefAttributes } from 'react';
3
+ import { ButtonOptions, ToggleButtonOptions } from '@sprocketui-types/buttons';
3
4
  import { RenderProps } from '@necto-react/types';
4
5
 
5
6
  /**
@@ -10,21 +11,20 @@ import { RenderProps } from '@necto-react/types';
10
11
  *
11
12
  */
12
13
 
13
- interface UseButtonProps<T extends ElementType> extends ButtonOptions<T> {
14
- elementType?: string;
15
- preventFocusOnPress?: boolean;
16
- href?: string;
17
- target?: string;
18
- rel?: string;
19
- isDisabled?: boolean;
20
- onClick?: (e: any) => void;
14
+ interface UseButtonCallbackProps {
21
15
  onPress?: (e: any) => void;
22
16
  onPressStart?: (e: any) => void;
23
17
  onPressEnd?: (e: any) => void;
24
18
  onPressUp?: (e: any) => void;
25
19
  onPressChange?: (isPressed: boolean) => void;
26
20
  }
27
- type ButtonHookReturn<T extends ElementType> = Readonly<{
21
+ interface UseButtonOptions<T extends ElementType> extends Omit<HTMLAttributes<HTMLElement>, keyof ButtonOptions<any> | 'children' | 'className' | 'style' | 'slot'>, Pick<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'target' | 'rel'>, Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof HTMLAttributes<any> | keyof ButtonOptions<any>>, ButtonOptions<T>, UseButtonCallbackProps {
22
+ elementType?: T;
23
+ preventFocusOnPress?: boolean;
24
+ isDisabled?: boolean;
25
+ isPending?: boolean;
26
+ }
27
+ type UseButtonReturn<T extends ElementType> = Readonly<{
28
28
  elementType: T;
29
29
  buttonProps: HTMLAttributes<any>;
30
30
  isPressed: boolean;
@@ -32,18 +32,10 @@ type ButtonHookReturn<T extends ElementType> = Readonly<{
32
32
  isFocused: boolean;
33
33
  isDisabled: boolean;
34
34
  isFocusVisible: boolean;
35
+ isPending: boolean;
35
36
  }>;
36
37
 
37
- declare const DEFAULT_BUTTON_TAG: keyof HTMLElementTagNameMap;
38
- /**
39
- * React hook that provides all necessary props and state for a headless button component.
40
- *
41
- * @template T The element type to render as (e.g., 'button', 'a', 'input').
42
- * @param {UseButtonProps<T>} props - The props for configuring the button's behavior and accessibility.
43
- * @param {RefObject<any>} ref - The ref to the button element.
44
- * @returns {ButtonHookReturn<T>} An object containing readonly state and props for the button element.
45
- */
46
- declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseButtonProps<T>, ref: RefObject<any>): ButtonHookReturn<T>;
38
+ declare const ButtonContext: react.Context<Partial<UseButtonOptions<"button">> | null>;
47
39
 
48
40
  /**
49
41
  * Copyright (c) Corinvo, LLC. and affiliates.
@@ -53,16 +45,38 @@ declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(pr
53
45
  *
54
46
  */
55
47
 
56
- declare const ButtonContext: Context<any>;
48
+ interface UseToggleButtonOptions<T extends ElementType> extends Omit<UseButtonOptions<T>, 'onChange'>, Omit<ToggleButtonOptions<T>, 'selected'> {
49
+ isSelected?: boolean;
50
+ onChange?: (isSelected: boolean) => void;
51
+ }
52
+ type UseToggleButtonReturn<T extends ElementType> = UseButtonReturn<T> & Readonly<{
53
+ isSelected: boolean;
54
+ }>;
55
+
56
+ declare const ToggleButtonContext: react.Context<Partial<UseToggleButtonOptions<"button">> | null>;
57
+
58
+ declare const DEFAULT_BUTTON_TAG: keyof HTMLElementTagNameMap;
57
59
 
58
60
  /**
59
- * Copyright (c) Corinvo, LLC. and affiliates.
61
+ * React hook that provides all necessary props and state for a headless button component.
60
62
  *
61
- * This source code is licensed under the MIT license found in the
62
- * LICENSE file in the root directory of this source tree.
63
+ * @template T The element type to render as (e.g., 'button', 'a', 'input').
64
+ * @param {UseButtonProps<T>} props - The props for configuring the button's behavior and accessibility.
65
+ * @param {RefObject<HTMLButtonElement>} ref - The ref to the button element.
66
+ * @returns {ButtonHookReturn<T>} An object containing readonly state and props for the button element.
67
+ */
68
+ declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseButtonOptions<T>, ref: RefObject<HTMLButtonElement>): UseButtonReturn<T>;
69
+
70
+ /**
71
+ * React hook that provides all necessary props and state for a headless toggle button component.
72
+ * Builds on top of useButton, adding selection state and aria-pressed.
63
73
  *
74
+ * @template T The element type to render as (e.g., 'button', 'a', 'input').
75
+ * @param {UseToggleButtonOptions<T>} props - The props for configuring the toggle button.
76
+ * @param {RefObject<HTMLButtonElement>} ref - The ref to the button element.
77
+ * @returns {UseToggleButtonReturn<T>} An object containing readonly state and props for the toggle button.
64
78
  */
65
- declare function useButtonContext(): any;
79
+ declare function useToggleButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseToggleButtonOptions<T>, ref: RefObject<HTMLButtonElement>): UseToggleButtonReturn<T>;
66
80
 
67
81
  /**
68
82
  * Copyright (c) Corinvo, LLC. and affiliates.
@@ -75,7 +89,7 @@ declare function useButtonContext(): any;
75
89
  /**
76
90
  * Props for the Button component.
77
91
  */
78
- interface ButtonProps extends ButtonOptions<ElementType>, RenderProps<any>, UseButtonProps<ElementType> {
92
+ interface ButtonProps extends ButtonOptions<ElementType>, RenderProps<any>, UseButtonOptions<ElementType> {
79
93
  slot?: string | null;
80
94
  }
81
95
 
@@ -90,4 +104,27 @@ declare const Button: ForwardRefExoticComponent<Omit<ButtonProps, 'ref'> & RefAt
90
104
  Root: ForwardRefExoticComponent<Omit<ButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>>;
91
105
  };
92
106
 
93
- export { Button, ButtonContext, type ButtonProps, Button as SprocketButton, ButtonContext as SprocketButtonContext, type ButtonProps as SprocketButtonProps, type UseButtonProps, type UseButtonProps as UseSprocketButtonProps, useButton, useButtonContext, useButton as useSprocketButton, useButtonContext as useSprocketButtonContext };
107
+ /**
108
+ * Copyright (c) Corinvo, LLC. and affiliates.
109
+ *
110
+ * This source code is licensed under the MIT license found in the
111
+ * LICENSE file in the root directory of this source tree.
112
+ *
113
+ */
114
+
115
+ /**
116
+ * Props for the ToggleButton component.
117
+ */
118
+ interface ToggleButtonProps extends RenderProps<any>, UseToggleButtonOptions<ElementType> {
119
+ slot?: string | null;
120
+ }
121
+
122
+ /**
123
+ * A ToggleButton component for Sprocket UI.
124
+ * Allows users to toggle a selection on or off.
125
+ */
126
+ declare const ToggleButton: ForwardRefExoticComponent<Omit<ToggleButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>> & {
127
+ Root: ForwardRefExoticComponent<Omit<ToggleButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>>;
128
+ };
129
+
130
+ export { Button, ButtonContext, type ButtonProps, Button as SprocketButton, ButtonContext as SprocketButtonContext, type ButtonProps as SprocketButtonProps, ToggleButton as SprocketToggleButton, ToggleButtonContext as SprocketToggleButtonContext, type ToggleButtonProps as SprocketToggleButtonProps, ToggleButton, ToggleButtonContext, type ToggleButtonProps, type UseButtonOptions, type UseButtonReturn, type UseButtonOptions as UseSprocketButtonOptions, type UseToggleButtonOptions as UseSprocketToggleButtonOptions, type UseToggleButtonOptions, type UseToggleButtonReturn, useButton, useButton as useSprocketButton, useToggleButton as useSprocketToggleButton, useToggleButton };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { ElementType, HTMLAttributes, RefObject, Context, ForwardRefExoticComponent, RefAttributes } from 'react';
2
- import { ButtonOptions } from '@sprocketui-types/button';
1
+ import * as react from 'react';
2
+ import { ElementType, HTMLAttributes, AnchorHTMLAttributes, ButtonHTMLAttributes, RefObject, ForwardRefExoticComponent, RefAttributes } from 'react';
3
+ import { ButtonOptions, ToggleButtonOptions } from '@sprocketui-types/buttons';
3
4
  import { RenderProps } from '@necto-react/types';
4
5
 
5
6
  /**
@@ -10,21 +11,20 @@ import { RenderProps } from '@necto-react/types';
10
11
  *
11
12
  */
12
13
 
13
- interface UseButtonProps<T extends ElementType> extends ButtonOptions<T> {
14
- elementType?: string;
15
- preventFocusOnPress?: boolean;
16
- href?: string;
17
- target?: string;
18
- rel?: string;
19
- isDisabled?: boolean;
20
- onClick?: (e: any) => void;
14
+ interface UseButtonCallbackProps {
21
15
  onPress?: (e: any) => void;
22
16
  onPressStart?: (e: any) => void;
23
17
  onPressEnd?: (e: any) => void;
24
18
  onPressUp?: (e: any) => void;
25
19
  onPressChange?: (isPressed: boolean) => void;
26
20
  }
27
- type ButtonHookReturn<T extends ElementType> = Readonly<{
21
+ interface UseButtonOptions<T extends ElementType> extends Omit<HTMLAttributes<HTMLElement>, keyof ButtonOptions<any> | 'children' | 'className' | 'style' | 'slot'>, Pick<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'target' | 'rel'>, Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof HTMLAttributes<any> | keyof ButtonOptions<any>>, ButtonOptions<T>, UseButtonCallbackProps {
22
+ elementType?: T;
23
+ preventFocusOnPress?: boolean;
24
+ isDisabled?: boolean;
25
+ isPending?: boolean;
26
+ }
27
+ type UseButtonReturn<T extends ElementType> = Readonly<{
28
28
  elementType: T;
29
29
  buttonProps: HTMLAttributes<any>;
30
30
  isPressed: boolean;
@@ -32,18 +32,10 @@ type ButtonHookReturn<T extends ElementType> = Readonly<{
32
32
  isFocused: boolean;
33
33
  isDisabled: boolean;
34
34
  isFocusVisible: boolean;
35
+ isPending: boolean;
35
36
  }>;
36
37
 
37
- declare const DEFAULT_BUTTON_TAG: keyof HTMLElementTagNameMap;
38
- /**
39
- * React hook that provides all necessary props and state for a headless button component.
40
- *
41
- * @template T The element type to render as (e.g., 'button', 'a', 'input').
42
- * @param {UseButtonProps<T>} props - The props for configuring the button's behavior and accessibility.
43
- * @param {RefObject<any>} ref - The ref to the button element.
44
- * @returns {ButtonHookReturn<T>} An object containing readonly state and props for the button element.
45
- */
46
- declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseButtonProps<T>, ref: RefObject<any>): ButtonHookReturn<T>;
38
+ declare const ButtonContext: react.Context<Partial<UseButtonOptions<"button">> | null>;
47
39
 
48
40
  /**
49
41
  * Copyright (c) Corinvo, LLC. and affiliates.
@@ -53,16 +45,38 @@ declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(pr
53
45
  *
54
46
  */
55
47
 
56
- declare const ButtonContext: Context<any>;
48
+ interface UseToggleButtonOptions<T extends ElementType> extends Omit<UseButtonOptions<T>, 'onChange'>, Omit<ToggleButtonOptions<T>, 'selected'> {
49
+ isSelected?: boolean;
50
+ onChange?: (isSelected: boolean) => void;
51
+ }
52
+ type UseToggleButtonReturn<T extends ElementType> = UseButtonReturn<T> & Readonly<{
53
+ isSelected: boolean;
54
+ }>;
55
+
56
+ declare const ToggleButtonContext: react.Context<Partial<UseToggleButtonOptions<"button">> | null>;
57
+
58
+ declare const DEFAULT_BUTTON_TAG: keyof HTMLElementTagNameMap;
57
59
 
58
60
  /**
59
- * Copyright (c) Corinvo, LLC. and affiliates.
61
+ * React hook that provides all necessary props and state for a headless button component.
60
62
  *
61
- * This source code is licensed under the MIT license found in the
62
- * LICENSE file in the root directory of this source tree.
63
+ * @template T The element type to render as (e.g., 'button', 'a', 'input').
64
+ * @param {UseButtonProps<T>} props - The props for configuring the button's behavior and accessibility.
65
+ * @param {RefObject<HTMLButtonElement>} ref - The ref to the button element.
66
+ * @returns {ButtonHookReturn<T>} An object containing readonly state and props for the button element.
67
+ */
68
+ declare function useButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseButtonOptions<T>, ref: RefObject<HTMLButtonElement>): UseButtonReturn<T>;
69
+
70
+ /**
71
+ * React hook that provides all necessary props and state for a headless toggle button component.
72
+ * Builds on top of useButton, adding selection state and aria-pressed.
63
73
  *
74
+ * @template T The element type to render as (e.g., 'button', 'a', 'input').
75
+ * @param {UseToggleButtonOptions<T>} props - The props for configuring the toggle button.
76
+ * @param {RefObject<HTMLButtonElement>} ref - The ref to the button element.
77
+ * @returns {UseToggleButtonReturn<T>} An object containing readonly state and props for the toggle button.
64
78
  */
65
- declare function useButtonContext(): any;
79
+ declare function useToggleButton<T extends ElementType = typeof DEFAULT_BUTTON_TAG>(props: UseToggleButtonOptions<T>, ref: RefObject<HTMLButtonElement>): UseToggleButtonReturn<T>;
66
80
 
67
81
  /**
68
82
  * Copyright (c) Corinvo, LLC. and affiliates.
@@ -75,7 +89,7 @@ declare function useButtonContext(): any;
75
89
  /**
76
90
  * Props for the Button component.
77
91
  */
78
- interface ButtonProps extends ButtonOptions<ElementType>, RenderProps<any>, UseButtonProps<ElementType> {
92
+ interface ButtonProps extends ButtonOptions<ElementType>, RenderProps<any>, UseButtonOptions<ElementType> {
79
93
  slot?: string | null;
80
94
  }
81
95
 
@@ -90,4 +104,27 @@ declare const Button: ForwardRefExoticComponent<Omit<ButtonProps, 'ref'> & RefAt
90
104
  Root: ForwardRefExoticComponent<Omit<ButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>>;
91
105
  };
92
106
 
93
- export { Button, ButtonContext, type ButtonProps, Button as SprocketButton, ButtonContext as SprocketButtonContext, type ButtonProps as SprocketButtonProps, type UseButtonProps, type UseButtonProps as UseSprocketButtonProps, useButton, useButtonContext, useButton as useSprocketButton, useButtonContext as useSprocketButtonContext };
107
+ /**
108
+ * Copyright (c) Corinvo, LLC. and affiliates.
109
+ *
110
+ * This source code is licensed under the MIT license found in the
111
+ * LICENSE file in the root directory of this source tree.
112
+ *
113
+ */
114
+
115
+ /**
116
+ * Props for the ToggleButton component.
117
+ */
118
+ interface ToggleButtonProps extends RenderProps<any>, UseToggleButtonOptions<ElementType> {
119
+ slot?: string | null;
120
+ }
121
+
122
+ /**
123
+ * A ToggleButton component for Sprocket UI.
124
+ * Allows users to toggle a selection on or off.
125
+ */
126
+ declare const ToggleButton: ForwardRefExoticComponent<Omit<ToggleButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>> & {
127
+ Root: ForwardRefExoticComponent<Omit<ToggleButtonProps, 'ref'> & RefAttributes<HTMLButtonElement>>;
128
+ };
129
+
130
+ export { Button, ButtonContext, type ButtonProps, Button as SprocketButton, ButtonContext as SprocketButtonContext, type ButtonProps as SprocketButtonProps, ToggleButton as SprocketToggleButton, ToggleButtonContext as SprocketToggleButtonContext, type ToggleButtonProps as SprocketToggleButtonProps, ToggleButton, ToggleButtonContext, type ToggleButtonProps, type UseButtonOptions, type UseButtonReturn, type UseButtonOptions as UseSprocketButtonOptions, type UseToggleButtonOptions as UseSprocketToggleButtonOptions, type UseToggleButtonOptions, type UseToggleButtonReturn, useButton, useButton as useSprocketButton, useToggleButton as useSprocketToggleButton, useToggleButton };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{useHover as $,usePress as G,useFocusRing as W,useFocusable as X}from"@necto-react/hooks";import{HTMLElements as u}from"@necto/dom";import{mergeProps as O}from"@necto/mergers";import{filterDOMProps as q}from"@necto-react/helpers";var g=["rel","href","ping","target","download","hrefLang","referrerPolicy"],A=["id","form","name","value","formAction","formEncType","formMethod","formTarget","formNoValidate"];function E(t,e){return t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_]+/g,"-").toLowerCase()}function L({prefix:t=":sprocket:=",component:e,variant:i,state:s,unique:a,obscure:p}){if(!e)throw new Error("Component context is required!");let r=[t+E(e,!1)];return i&&r.push(E(i,!1)),Array.isArray(s)&&s.length&&r.push(...s.map(m=>E(m,!1))),a&&r.push(Math.random().toString(36).slice(2,8)),p&&r.push(Math.random().toString(36).slice(2,16)),r.join("--")}var k=u.Button;function x(t,e){let{rel:i,href:s,target:a,autoFocus:p,focusDisabled:r,preventFocusOnPress:m,isDisabled:o=!1,type:c="button",as:B=k,elementType:n=B||k,onClick:d,onPress:P,onPressStart:b,onPressEnd:R,onPressUp:l,onPressChange:H}=t,y;n===u.Button?y={type:c,disabled:o}:y={role:"button",href:n===u.A&&!o?s:void 0,target:n===u.A?a:void 0,type:n===u.Input?c:void 0,disabled:n===u.Input?o:void 0,"aria-disabled":!o||n===u.Input?void 0:o,rel:n===u.A?i:void 0};let{hoverProps:_,isHovered:v}=$({...t,isDisabled:o}),{focusProps:N,isFocused:U,isFocusVisible:I}=W({autoFocus:p}),{focusableProps:T}=X(t,e),{pressProps:D,isPressed:j}=G({ref:e,isDisabled:o,preventFocusOnPress:m,onPressStart:b,onPressEnd:R,onPressChange:H,onPress:P,onPressUp:l,onClick:d});r&&(T.tabIndex=o?-1:T.tabIndex);let V=O(T,D,_,N,q(t,{allowLabelableProps:!0,allowedLabelableProps:new Set([]),allowedLinkProps:new Set(g),extraAllowedProps:new Set(A)}));return{isFocused:U,isPressed:j,isHovered:v,isDisabled:o,isFocusVisible:I,elementType:n,buttonProps:O(V,y)}}import{createContext as z}from"react";var f=z(null);import{useContext as Z}from"react";function w(){return Z(f)}import{kebabCase as h}from"@necto/strings";import{mergeProps as J}from"@necto/mergers";import{forwardRef as F,useMemo as K}from"react";import{Primitive as Q}from"@necto-react/components";import{useContextProps as Y,useRenderer as tt,useId as et}from"@necto-react/hooks";import{jsxs as ot}from"react/jsx-runtime";var S="Button";function M(t,e){[t,e]=Y({props:t,ref:e,context:f});let{buttonProps:i,isHovered:s,isPressed:a,isFocused:p,isDisabled:r,elementType:m,isFocusVisible:o}=x(t,e),c=et({defaultId:i.id}),B=tt({...t,values:{isHovered:s,isPressed:a,isFocused:p,isFocusVisible:o,isDisabled:r},defaultClassName:L({component:S}),style:d=>({...t.style instanceof Function?t.style(d):t.style})}),n=K(()=>{let d={hover:s,focus:p,focusVisible:o,disabled:r,pressed:a},P={},b=[];for(let[R,l]of Object.entries(d))typeof l=="boolean"&&(P[`data-${h(R)}`]=l?String(!0):void 0,l&&b.push(h(R)));return{...P,"data-sprocket-state":b.join(" ")}},[s,p,o,r,a]);return ot(Q,{ref:e,as:m,...B,...J(i,n),id:c,slot:t.slot||void 0,children:["''",B.children]})}var C=Object.assign(F((t,e)=>M(t,e)),{Root:F((t,e)=>M(t,e))});C.displayName=S;export{C as Button,f as ButtonContext,C as SprocketButton,f as SprocketButtonContext,x as useButton,w as useButtonContext,x as useSprocketButton,w as useSprocketButtonContext};
1
+ import{createContext as K}from"react";var y=K(null);import{createContext as Y}from"react";var E=Y(null);import{useHover as ot,usePress as nt,useFocusRing as rt,useFocusable as st,useAriaProps as ut}from"@necto-react/hooks";import{defu as it}from"defu";import{HTMLElements as c}from"@necto/dom";import{mergeProps as I}from"@necto/mergers";import{filterDOMProps as lt}from"@necto-react/helpers";var v=["rel","href","ping","target","download","hrefLang","referrerPolicy"],D=["id","form","name","value","defaultValue","formAction","formEncType","formMethod","formTarget","formNoValidate"];function R(t,e=!1){let n=t.replace(/\p{Lu}/gu,i=>`-${i.toLowerCase()}`);return e?n:n.startsWith("-")?n.slice(1):n}R.reverse=t=>t.replace(/-\p{Ll}/gu,e=>e.slice(1).toUpperCase());var Z=6,tt=14;function H(t){return Math.random().toString(36).slice(2,2+t)}function b({prefix:t="__sprocket:=[",component:e,variant:n,state:i,unique:l,obscure:a}){let d=e?.trim();if(!d)throw new Error("Component context is required!");let p=1+(n?1:0)+(i?.length??0)+(l?1:0)+(a?1:0),o=new Array(p),r=0;if(o[r++]=t+R(d,!1)+"]",n&&(o[r++]=R(n,!1)),i?.length)for(let s of i)o[r++]=R(s,!1);return l&&(o[r++]=H(Z)),a&&(o[r++]=H(tt)),o.join("--")}import{HTMLElements as et}from"@necto/dom";var h="Button",F="ToggleButton",M=et.Button;function T(t,e){let{rel:n,href:i,target:l,autoFocus:a,focusDisabled:d,preventFocusOnPress:p,isDisabled:o,isPending:r,type:s,elementType:u,onClick:f,onPress:g,onPressStart:P,onPressEnd:k,onPressUp:x,onPressChange:L}=it(t,{isDisabled:!1,isPending:!1,type:"button",as:M,elementType:t.elementType||t.as||M}),B;u===c.Button?B={type:s,disabled:o}:B={role:"button",href:u===c.A&&!o?i:void 0,target:u===c.A?l:void 0,type:u===c.Input?s:void 0,disabled:u===c.Input?o:void 0,"aria-disabled":!o||u===c.Input?void 0:o,rel:u===c.A?n:void 0};let{hoverProps:X,isHovered:U}=ot({...t,isDisabled:o}),{focusProps:Q,isFocused:A,isFocusVisible:C}=rt({autoFocus:a}),{focusableProps:S}=st(t,e),{pressProps:$,isPressed:_}=nt({ref:e,isDisabled:o||r,preventFocusOnPress:p,onPressStart:P,onPressEnd:k,onPressChange:L,onPress:g,onPressUp:x,onClick:f}),q=ut({isBusy:r||void 0});d&&(S.tabIndex=o?-1:S.tabIndex);let z=I(S,$,X,Q,lt(t,{allowLabelableProps:!0,allowedLabelableProps:new Set([]),allowedLinkProps:new Set(v),extraAllowedProps:new Set(D)})),m=[];U&&m.push("hover"),A&&m.push("focus"),C&&m.push("focus-visible"),o&&m.push("disabled"),_&&m.push("pressed"),r&&m.push("pending");let J={"data-hover":U?"true":void 0,"data-focus":A?"true":void 0,"data-focus-visible":C?"true":void 0,"data-disabled":o?"true":void 0,"data-pressed":_?"true":void 0,"data-pending":r?"true":void 0,"data-sprocket-state":m.length>0?m.join(" "):void 0};return{isFocused:A,isPressed:_,isHovered:U,isDisabled:o,isPending:r,isFocusVisible:C,elementType:u,buttonProps:I(z,B,q,J)}}import{defu as at}from"defu";import{mergeProps as pt}from"@necto/mergers";import{useState as dt,useCallback as ft}from"react";function O(t,e){let{isSelected:n,defaultSelected:i,onChange:l,onPress:a,...d}=at(t,{defaultSelected:!1}),p=n!==void 0,[o,r]=dt(i),s=p?n:o,u=ft(L=>{let B=!s;p||r(B),l?.(B),a?.(L)},[s,p,l,a]),f=T({...d,onPress:u},e),g=[];s&&g.push("selected");let P={"data-selected":s?"true":void 0},x=[f.buttonProps["data-sprocket-state"],...g].filter(Boolean).join(" ");return P["data-sprocket-state"]=x||void 0,{...f,isSelected:s,buttonProps:pt(f.buttonProps,{"aria-pressed":s,...P})}}import{forwardRef as G}from"react";import{mergeProps as mt}from"@necto/mergers";import{Primitive as ct}from"@necto-react/components";import{useContextProps as gt,useRenderer as Bt,useId as Tt}from"@necto-react/hooks";import{jsx as Pt}from"react/jsx-runtime";function j(t,e){[t,e]=gt({props:t,ref:e,context:y});let{buttonProps:n,isHovered:i,isPressed:l,isFocused:a,isDisabled:d,isPending:p,elementType:o,isFocusVisible:r}=T(t,e),s=Tt({defaultId:n.id}),u=Bt({...t,values:{isHovered:i,isPressed:l,isFocused:a,isFocusVisible:r,isDisabled:d,isPending:p},defaultClassName:b({component:h}),style:f=>({...t.style instanceof Function?t.style(f):t.style})});return Pt(ct,{ref:e,as:o,...u,...mt(n),id:s,slot:t.slot||void 0,children:u.children})}var N=Object.assign(G((t,e)=>j(t,e)),{Root:G((t,e)=>j(t,e))});N.displayName=h;import{forwardRef as V}from"react";import{mergeProps as yt}from"@necto/mergers";import{Primitive as Et}from"@necto-react/components";import{useContextProps as Rt,useRenderer as bt,useId as Ot}from"@necto-react/hooks";import{jsx as xt}from"react/jsx-runtime";function W(t,e){[t,e]=Rt({props:t,ref:e,context:E});let{buttonProps:n,isHovered:i,isPressed:l,isFocused:a,isDisabled:d,isPending:p,isSelected:o,elementType:r,isFocusVisible:s}=O(t,e),u=Ot({defaultId:n.id}),f=bt({...t,values:{isHovered:i,isPressed:l,isFocused:a,isFocusVisible:s,isDisabled:d,isPending:p,isSelected:o},defaultClassName:b({component:F}),style:g=>({...t.style instanceof Function?t.style(g):t.style})});return xt(Et,{ref:e,as:r,...f,...yt(n),id:u,slot:t.slot||void 0,children:f.children})}var w=Object.assign(V((t,e)=>W(t,e)),{Root:V((t,e)=>W(t,e))});w.displayName=F;export{N as Button,y as ButtonContext,N as SprocketButton,y as SprocketButtonContext,w as SprocketToggleButton,E as SprocketToggleButtonContext,w as ToggleButton,E as ToggleButtonContext,T as useButton,T as useSprocketButton,O as useSprocketToggleButton,O as useToggleButton};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprocketui-react/button",
3
- "version": "1.1.0",
3
+ "version": "1.2.2",
4
4
  "description": "Sprocket's standalone React button component.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -16,16 +16,15 @@
16
16
  "node": ">=10"
17
17
  },
18
18
  "dependencies": {
19
- "@necto-react/components": "^1.2.14",
20
- "@necto-react/helpers": "^2.4.5",
21
- "@necto-react/hooks": "^2.12.6",
22
- "@necto-react/types": "^2.3.0",
23
- "@necto/dom": "^1.4.5",
24
- "@necto/mergers": "^1.4.0",
25
- "@necto/strings": "^1.4.0",
26
- "@react-aria/focus": "^3.20.2",
27
- "react-aria": "^3.39.0",
28
- "@sprocketui-types/button": "1.0.2"
19
+ "@necto-react/components": "1.4.2",
20
+ "@necto-react/helpers": "2.6.1",
21
+ "@necto-react/hooks": "2.14.2",
22
+ "@necto-react/types": "2.4.0",
23
+ "@necto/dom": "1.6.1",
24
+ "@necto/mergers": "1.5.0",
25
+ "@necto/strings": "1.6.0",
26
+ "defu": "^6.1.4",
27
+ "@sprocketui-types/buttons": "1.1.0"
29
28
  },
30
29
  "peerDependencies": {
31
30
  "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",