@nild/components 0.0.39 → 0.0.40
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/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/modal/Close.js +1 -1
- package/dist/modal/Modal.js +1 -1
- package/dist/modal/Portal.js +1 -1
- package/dist/modal/Trigger.js +1 -1
- package/dist/modal/_shared/index.d.ts +0 -3
- package/dist/modal/_shared/index.js +1 -1
- package/dist/modal/contexts/index.d.ts +1 -4
- package/dist/modal/contexts/index.js +1 -1
- package/dist/modal/hooks/index.d.ts +1 -0
- package/dist/modal/hooks/useModalFocusScope.d.ts +12 -0
- package/dist/modal/hooks/useModalFocusScope.js +1 -0
- package/dist/popup/Trigger.js +1 -1
- package/dist/select/Option.d.ts +5 -0
- package/dist/select/Option.js +1 -0
- package/dist/select/Select.d.ts +4 -0
- package/dist/select/Select.js +1 -0
- package/dist/select/__tests__/Select.test.d.ts +0 -0
- package/dist/select/hooks/index.d.ts +1 -0
- package/dist/select/hooks/useSelectNavigation.d.ts +23 -0
- package/dist/select/hooks/useSelectNavigation.js +1 -0
- package/dist/select/index.d.ts +8 -0
- package/dist/select/index.js +1 -0
- package/dist/select/style/index.d.ts +30 -0
- package/dist/select/style/index.js +1 -0
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { default as Input } from './input';
|
|
|
5
5
|
import { default as Modal } from './modal';
|
|
6
6
|
import { default as Popover } from './popover';
|
|
7
7
|
import { default as Radio } from './radio';
|
|
8
|
+
import { default as Select } from './select';
|
|
8
9
|
import { default as Switch } from './switch';
|
|
9
10
|
import { default as Tooltip } from './tooltip';
|
|
10
11
|
import { default as Transition, TransitionStatus } from './transition';
|
|
11
12
|
import { default as Typography } from './typography';
|
|
12
|
-
export { Button, Checkbox, Divider, Input, Modal, Popover, Radio, Switch, Tooltip, Transition, TransitionStatus, Typography, };
|
|
13
|
+
export { Button, Checkbox, Divider, Input, Modal, Popover, Radio, Select, Switch, Tooltip, Transition, TransitionStatus, Typography, };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{default as a}from"./button/index.js";import{default as o}from"./checkbox/index.js";import{default as t}from"./divider/Divider.js";import{default as r}from"./input/index.js";import{default as s}from"./modal/index.js";import{default as m}from"./popover/index.js";import{default as
|
|
1
|
+
import{default as a}from"./button/index.js";import{default as o}from"./checkbox/index.js";import{default as t}from"./divider/Divider.js";import{default as r}from"./input/index.js";import{default as s}from"./modal/index.js";import{default as m}from"./popover/index.js";import{default as f}from"./radio/index.js";import{default as i}from"./select/index.js";import{default as p}from"./switch/index.js";import{default as e}from"./tooltip/index.js";import{default as d}from"./transition/Transition.js";import{TransitionStatus as u}from"./transition/interfaces/index.js";import{default as l}from"./typography/index.js";/* empty css */export{a as Button,o as Checkbox,t as Divider,r as Input,s as Modal,m as Popover,f as Radio,i as Select,p as Switch,e as Tooltip,d as Transition,u as TransitionStatus,l as Typography};
|
package/dist/modal/Close.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as o}from"react/jsx-runtime";import{Icon as C}from"@nild/icons";import
|
|
1
|
+
import{jsx as o}from"react/jsx-runtime";import{Icon as C}from"@nild/icons";import h from"@nild/icons/Close";import{cnMerge as x}from"@nild/shared";import{forwardRef as M,isValidElement as N}from"react";import q from"../_shared/utils/merge-handlers/index.js";import y from"../button/index.js";import{useModalContext as E}from"./contexts/index.js";import g from"./style/index.js";const j=a=>N(a)&&a.type===e,e=M(({children:a,variant:r="text",shape:s="square",size:l="small",equal:i=!0,"aria-label":m="Close",onClick:t,className:n,disabled:p,...d},c)=>{const{disabled:f,updateOpen:u}=E();return o(y,{...d,"aria-label":m,className:x(g.close(),n),disabled:f||p,equal:i,onClick:q(t,b=>(u(!1),b)),ref:c,shape:s,size:l,variant:r,children:a??o(C,{component:h})})});e.displayName="Modal.Close";export{e as default,j as isCloseElement};
|
package/dist/modal/Modal.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as
|
|
1
|
+
import{jsxs as I,jsx as M}from"react/jsx-runtime";import{useControllableState as J,useEffectCallback as R}from"@nild/hooks";import{isFunction as X,cnJoin as h}from"@nild/shared";import{useRef as N,useMemo as q,cloneElement as w}from"react";import A from"../_shared/utils/register-slots/index.js";import G from"../transition/Transition.js";import{TransitionStatus as k}from"../transition/interfaces/index.js";import{resolvePlacement as H}from"./_shared/index.js";import{ModalProvider as K}from"./contexts/index.js";import{isPortalElement as F}from"./Portal.js";import S from"./style/index.js";import L,{isTriggerElement as T}from"./Trigger.js";const Q=A({trigger:{isMatched:e=>T(e)},portal:{isMatched:e=>F(e)},firstBare:{isMatched:e=>!T(e)&&!F(e),strategy:"first"}}),x=e=>{const{children:B,variant:s="dialog",size:c="medium",open:P,defaultOpen:j=!1,disabled:t=!1,closeOnEscape:m=!0,closeOnOverlayClick:p=!0,trapFocus:u=!0,restoreFocus:d=!0,lockScroll:f=!0,"aria-label":b,"aria-labelledby":v,"aria-describedby":y,onOpen:g,onClose:O}=e,{slots:r}=Q(B),[l,z]=J(P,j),i=N(l),D=N(null),n=H(s,e.placement);i.current=l;const C=R(a=>{if(t)return;const E=i.current,o=X(a)?a(E):a;o!==E&&(i.current=o,z(o),o?g?.():O?.())}),U=q(()=>({open:l,variant:s,placement:n,size:c,disabled:t,closeOnEscape:m,closeOnOverlayClick:p,trapFocus:u,restoreFocus:d,lockScroll:f,accessibility:{"aria-label":b,"aria-labelledby":v,"aria-describedby":y},refs:{trigger:D},updateOpen:C}),[y,b,v,m,p,t,f,l,n,C,d,c,u,s]);return I(K,{value:U,children:[r.trigger.el??(r.firstBare.el&&M(L,{children:r.firstBare.el})),r.portal.el&&M(G,{visible:l,children:a=>!l&&[k.UNMOUNTED,k.EXITED].includes(a)?null:w(r.portal.el,{...r.portal.el.props,overlayClassName:h(S.overlayMotion({status:a}),r.portal.el.props.overlayClassName),surfaceClassName:h(S.surfaceMotion({status:a,variant:s,placement:n}),r.portal.el.props.surfaceClassName)})})]})};x.displayName="Modal";export{x as default};
|
package/dist/modal/Portal.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsxs as
|
|
1
|
+
import{jsxs as v,jsx as g}from"react/jsx-runtime";import{useEffectCallback as h,useEventListener as B}from"@nild/hooks";import{cnMerge as n,mergeRefs as H}from"@nild/shared";import{forwardRef as L,useRef as V,useEffect as q,isValidElement as A}from"react";import{createPortal as G}from"react-dom";import J from"../_shared/utils/get-owner-document/index.js";import K from"../_shared/utils/lock-document-scroll/index.js";import Q from"../_shared/utils/register-slots/index.js";import{isBodyElement as U}from"./Body.js";import W,{isCloseElement as X}from"./Close.js";import{useModalContext as Y}from"./contexts/index.js";import{isFooterElement as Z}from"./Footer.js";import{isHeaderElement as _}from"./Header.js";import{useModalStack as $}from"./hooks/useModalStack.js";import{useModalFocusScope as ee}from"./hooks/useModalFocusScope.js";import m from"./style/index.js";const re=e=>A(e)&&e.type===c,ae=Q({header:{isMatched:e=>_(e)},body:{isMatched:e=>U(e)},footer:{isMatched:e=>Z(e)},close:{isMatched:e=>X(e)}}),c=L(({className:e,style:M,children:k,container:d,overlayless:f=!1,overlayClassName:N,surfaceClassName:x,onTransitionEnd:C,...F},z)=>{const{open:s,variant:R,placement:p,size:w,closeOnEscape:I,closeOnOverlayClick:O,trapFocus:P,lockScroll:u,restoreFocus:j,accessibility:t,refs:y,updateOpen:b}=Y(),l=V(null),r=J(d,l.current,y.trigger.current),a=d??r?.body??null,{zIndex:D,topmost:i}=$(r,!!a),S=h(()=>{f||!s||!O||!i||b(!1)}),T=h(E=>{!s||!i||E.key==="Escape"&&I&&(E.preventDefault(),b(!1))});if(q(()=>{if(!(!a||!u||!r))return K(r)},[u,r,a]),ee({open:s,trapFocus:P,restoreFocus:j,topmost:i,ownerDocument:r,surfaceRef:l,triggerRef:y.trigger}),B(r,"keydown",T),!a)return null;const{slots:o}=ae(k);return G(v("div",{className:n(m.portal({placement:p}),e),style:{zIndex:D,...M},...F,children:[!f&&g("div",{className:n(m.overlay(),N),onClick:S}),v("div",{ref:H(l,z),className:n(m.surface({variant:R,placement:p,size:w}),x),"aria-describedby":t["aria-describedby"],"aria-label":t["aria-label"],"aria-labelledby":t["aria-labelledby"],"aria-modal":"true",role:"dialog",tabIndex:-1,onTransitionEnd:C,children:[o.header.el,o.body.el,o.footer.el,o.close.el??g(W,{})]})]}),a)});c.displayName="Modal.Portal";export{c as default,re as isPortalElement};
|
package/dist/modal/Trigger.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffectCallback as
|
|
1
|
+
import{useEffectCallback as l}from"@nild/hooks";import{mergeRefs as p}from"@nild/shared";import{isValidElement as t,Children as f,cloneElement as n}from"react";import d from"../_shared/utils/merge-props/index.js";import{useModalContext as g}from"./contexts/index.js";import c from"./style/index.js";const u=e=>t(e)&&e.type===o,o=({children:e})=>{const{refs:a,updateOpen:s}=g(),r=f.toArray(e).find(m=>t(m)),i=l(()=>{s(!0)});return r?n(r,d(r.props,{className:c.trigger(),onClick:i,ref:p(a.trigger,r.props.ref)})):null};o.displayName="Modal.Trigger";export{o as default,u as isTriggerElement};
|
|
@@ -1,5 +1,2 @@
|
|
|
1
1
|
import { ModalPlacement, ModalVariant } from '../interfaces';
|
|
2
2
|
export declare const resolvePlacement: (variant: ModalVariant, placement?: ModalPlacement) => ModalPlacement;
|
|
3
|
-
export declare const getFocusableElements: (container: HTMLElement) => HTMLElement[];
|
|
4
|
-
export declare const focusWithin: (container: HTMLElement, fromEnd?: boolean) => HTMLElement;
|
|
5
|
-
export declare const restoreFocusTo: (target?: HTMLElement | null, fallback?: HTMLElement | null) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const r=(t,e)=>t==="drawer"?e&&e!=="center"?e:"right":"center";export{r as resolvePlacement};
|
|
@@ -14,11 +14,8 @@ export interface ModalContextValue {
|
|
|
14
14
|
accessibility: ModalAccessibility;
|
|
15
15
|
refs: {
|
|
16
16
|
trigger: RefObject<Element>;
|
|
17
|
-
surface: RefObject<HTMLDivElement>;
|
|
18
|
-
lastActiveEl: RefObject<HTMLElement | null>;
|
|
19
17
|
};
|
|
20
|
-
|
|
21
|
-
close: () => void;
|
|
18
|
+
updateOpen: Dispatch<SetStateAction<boolean>>;
|
|
22
19
|
}
|
|
23
20
|
declare const ModalProvider: import('react').Provider<ModalContextValue>, useModalContext: () => ModalContextValue;
|
|
24
21
|
export { ModalProvider, useModalContext };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createContextSuite as e}from"@nild/shared";const[l
|
|
1
|
+
import{createContextSuite as e}from"@nild/shared";const[a,l]=e({defaultValue:{open:!1,variant:"dialog",placement:"center",size:"medium",disabled:!1,closeOnEscape:!0,closeOnOverlayClick:!0,trapFocus:!0,restoreFocus:!0,lockScroll:!0,accessibility:{"aria-label":void 0,"aria-labelledby":void 0,"aria-describedby":void 0},refs:{trigger:{current:null}},updateOpen:()=>{}}});export{a as ModalProvider,l as useModalContext};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
interface UseModalFocusScopeOptions {
|
|
3
|
+
open: boolean;
|
|
4
|
+
trapFocus: boolean;
|
|
5
|
+
restoreFocus: boolean;
|
|
6
|
+
topmost: boolean;
|
|
7
|
+
ownerDocument: Document | null;
|
|
8
|
+
surfaceRef: RefObject<HTMLElement>;
|
|
9
|
+
triggerRef: RefObject<Element>;
|
|
10
|
+
}
|
|
11
|
+
export declare const useModalFocusScope: ({ open, trapFocus, restoreFocus, topmost, ownerDocument, surfaceRef, triggerRef, }: UseModalFocusScopeOptions) => void;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useEffectCallback as v,useIsomorphicLayoutEffect as A,useEventListener as y}from"@nild/hooks";import{useRef as h,useEffect as E}from"react";const C=["a[href]","area[href]","button:not([disabled])",'input:not([disabled]):not([type="hidden"])',"select:not([disabled])","textarea:not([disabled])","iframe","summary",'[contenteditable="true"]','[tabindex]:not([tabindex="-1"])'].join(","),w=e=>{const t=e.ownerDocument.defaultView;if(!t)return!e.hidden;const o=t.getComputedStyle(e);return o.display!=="none"&&o.visibility!=="hidden"&&!e.hidden},g=e=>Array.from(e.querySelectorAll(C)).filter(t=>!t.hasAttribute("disabled")&&t.getAttribute("aria-hidden")!=="true"&&t.tabIndex>=0&&w(t)),m=(e,t=!1)=>{const o=g(e).at(t?-1:0)??e;return o.focus(),o},K=(e,t)=>{var o;const c=e!=null&&e.isConnected?e:t!=null&&t.isConnected?t:null;(o=c?.focus)==null||o.call(c)},S=({open:e,trapFocus:t,restoreFocus:o,topmost:c,ownerDocument:u,surfaceRef:a,triggerRef:p})=>{const b=h(null),i=h(e),x=v(n=>{const r=a.current;if(!r||!e||!c||n.key!=="Tab"||!t)return;const s=g(r),l=u?.activeElement;if(s.length===0){n.preventDefault(),r.focus();return}if(!l||!r.contains(l)){n.preventDefault(),m(r,n.shiftKey);return}const d=s[0],f=s.at(-1);n.shiftKey&&l===d?(n.preventDefault(),f?.focus()):!n.shiftKey&&l===f&&(n.preventDefault(),d?.focus())}),D=v(n=>{const r=a.current,s=n.target;!r||!t||!e||!c||!s||r.contains(s)||m(r)});E(()=>{const n=i.current;e&&!n&&(b.current=u?.activeElement),i.current=e},[e,u]),E(()=>{const n=p.current;return()=>{!o||i.current||K(b.current,n)}},[o,p]),A(()=>{if(!e)return;const n=setTimeout(()=>{const r=a.current;if(!r||!c)return;const s=u?.activeElement;(!s||!r.contains(s))&&m(r)},0);return()=>{clearTimeout(n)}},[e,u,a,c]),y(u,"keydown",x),y(u,"focusin",D)};export{S as useModalFocusScope};
|
package/dist/popup/Trigger.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useEffectCallback as u,useEventListener as
|
|
1
|
+
import{useEffectCallback as u,useEventListener as d}from"@nild/hooks";import{mergeRefs as L,cnJoin as N}from"@nild/shared";import{Children as w,isValidElement as y,cloneElement as B}from"react";import{usePopupContext as F}from"./contexts/index.js";import b from"./style/index.js";const f=({children:m})=>{var p;const{actions:r,refs:s,setOpen:t,enter:g,leave:h}=F(),e=w.toArray(m).find(o=>y(o)),v=r.has("click")||r.has("contextMenu")?window:null,M=u(o=>{var l,n;(n=(l=e?.props)==null?void 0:l.onMouseEnter)==null||n.call(l,o),g()}),x=u(o=>{var l,n;(n=(l=e?.props)==null?void 0:l.onMouseLeave)==null||n.call(l,o),h()}),E=u(o=>{var l,n;(n=(l=e?.props)==null?void 0:l.onFocus)==null||n.call(l,o),r.has("focus")&&t(!0)}),k=u(o=>{var l,n;(n=(l=e?.props)==null?void 0:l.onBlur)==null||n.call(l,o),r.has("focus")&&t(!1)});return d(v,"click",o=>{var l,n;const a=o.target,i=(l=s.trigger.current)==null?void 0:l.contains(a),c=(n=s.portal.current)==null?void 0:n.contains(a);i?(r.has("click")&&t(C=>!C),r.has("contextMenu")&&t(!1)):!c&&t(!1)}),d(v,"contextmenu",o=>{var l,n;const a=o.target,i=(l=s.trigger.current)==null?void 0:l.contains(a),c=(n=s.portal.current)==null?void 0:n.contains(a);i?r.has("contextMenu")&&(o.preventDefault(),t(!0)):!c&&t(!1)}),e?B(e,{...e?.props,className:N(b.trigger(),(p=e?.props)==null?void 0:p.className),onMouseEnter:M,onMouseLeave:x,onFocus:E,onBlur:k,ref:L(s.trigger,e.ref)}):null};f.displayName="Popup.Trigger";export{f as default};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import { SelectOptionProps } from './interfaces';
|
|
3
|
+
export declare const isOptionElement: <T>(child: ReactNode) => child is ReactElement<SelectOptionProps<T>>;
|
|
4
|
+
declare const Option: <T>(props: SelectOptionProps<T> & import('react').RefAttributes<HTMLDivElement>) => ReactElement | null;
|
|
5
|
+
export default Option;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsxs as N,jsx as i}from"react/jsx-runtime";import b from"@nild/icons/CheckSmall";import{forwardRefWithGenerics as v,cnMerge as x}from"@nild/shared";import{isValidElement as M}from"react";import s from"./style/index.js";const w=e=>M(e)&&e.type===o,o=v((e,r)=>{const{size:a="medium",label:l,disabled:n=!1,selected:t=!1,active:d=!1,children:c,className:m,onClick:p,onMouseDown:f,onMouseEnter:u,...h}=e;return N("div",{...h,"aria-disabled":n||void 0,"aria-selected":t,className:x(s.option({size:a,disabled:n,active:d}),m),onClick:p,onMouseDown:f,onMouseEnter:u,ref:r,role:"option",children:[i("div",{className:s.optionContent(),children:c??i("span",{className:s.optionLabel(),children:l})}),i("span",{"aria-hidden":"true",className:s.optionIndicator({size:a}),children:t?i(b,{className:"text-brand",size:"1em"}):null})]})});o.displayName="Select.Option";export{o as default,w as isOptionElement};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsxs as J,jsx as m}from"react/jsx-runtime";import{useControllableState as de,useIsomorphicLayoutEffect as pe}from"@nild/hooks";import{Icon as ue}from"@nild/icons";import me from"@nild/icons/Down";import{forwardRefWithGenerics as be,mergeRefs as Q,cnMerge as fe}from"@nild/shared";import{useId as he,useRef as K,useState as ge,useMemo as ve,cloneElement as ye}from"react";import D from"../_shared/utils/merge-handlers/index.js";import xe from"../_shared/utils/register-slots/index.js";import L from"../popup/index.js";import{useSelectNavigation as Ie}from"./hooks/useSelectNavigation.js";import{isOptionElement as Oe}from"./Option.js";import N from"./style/index.js";const je=xe({option:{isMatched:t=>Oe(t),multiple:!0}}),g=t=>Array.isArray(t)?t:[],we=(t,l,s)=>{if(!t)return Object.is(l,s);const n=g(l),i=g(s);return n.length===i.length&&n.every((r,c)=>Object.is(r,i[c]))},ke=(t,l)=>t.some(s=>Object.is(s,l))?t.filter(s=>!Object.is(s,l)):t.concat(l),De=(t,l,s)=>{const{slots:n}=je(t),i=n.option.el,r=[],c=[],v=[],y=l?g(s):[];let x="",d=!0,b=-1;return i.forEach((p,f)=>{var I;const o=p.props,O=l?y.some(j=>Object.is(j,o.value)):Object.is(o.value,s);r.push({key:((I=p.key)==null?void 0:I.toString())??`${n.option.seq[f]}`,selected:O,element:p,props:o}),o.disabled||c.push(f),O&&(d=!1,!o.disabled&&b<0&&(b=f),l?v.push(o.label):x=o.label)}),{options:r,enabledIndices:c,selectedIndex:b,selectionValues:y,selectionText:l?v.join(", "):x,selectionEmpty:d}},U=be((t,l)=>{var s;const{className:n,children:i,"aria-label":r,"aria-labelledby":c,onKeyDown:v,placeholder:y,variant:x="outlined",size:d="medium",block:b=!1,disabled:p=!1,placement:f="bottom-start",offset:I=8,multiple:o=!1,value:O,defaultValue:j,onChange:w,...X}=t,Y=he(),E=K(null),A=K(null),V=K([]),[S,C]=ge(!1),[M,Z]=de(O,o?g(j):j),{options:R,enabledIndices:W,selectedIndex:_,selectionValues:ee,selectionText:oe,selectionEmpty:$}=ve(()=>De(i,o,M),[i,o,M]),h=!p&&W.length>0,u=h&&S,B=()=>h&&C(!0),z=()=>C(!1),q=e=>{we(o,M,e)||(o?w?.(g(e)):w?.(e),Z(()=>e))},G=e=>{const a=R[e];if(!(!a||a.props.disabled)){if(o)return q(ke(ee,a.props.value));q(a.props.value),z(),ie()}},{activeIndex:k,setActiveIndex:te,focusListbox:le,handleTriggerKeyDown:se,handleListboxKeyDown:ae,handleListboxBlur:ne,focusTrigger:ie}=Ie({open:u,selectedIndex:_,enabledIndices:W,triggerRef:E,listboxRef:A,optionRefs:V,onOpen:B,onClose:z,onSelect:G});pe(()=>{!h&&S&&C(!1)},[h,S]);const P=(e,a)=>e.props.id??`${Y}-option-${a}`,F=k>=0?R[k]:void 0,re=u&&F?P(F,k):void 0,ce=(e,a)=>{const H=e.element;return ye(H,{key:e.key,id:P(e,a),size:d,active:k===a,className:e.props.className,onClick:D(e.props.onClick,()=>G(a)),onMouseDown:D(e.props.onMouseDown,T=>T.preventDefault()),onMouseEnter:D(e.props.onMouseEnter,()=>{e.props.disabled||te(a)}),ref:Q(H.ref,T=>{V.current[a]=T}),selected:e.selected})};return J(L,{action:"click",arrowed:!1,disabled:!h,offset:I,open:u,placement:f,onClose:z,onOpen:B,children:[m(L.Trigger,{children:J("button",{...X,"aria-expanded":u,"aria-haspopup":"listbox","aria-label":r,"aria-labelledby":c,className:fe(N.trigger({variant:x,size:d,block:b,disabled:p,open:u}),n),disabled:p,onKeyDown:D(v,se),ref:Q(l,E),type:"button",children:[m("span",{className:N.triggerContent({size:d,placeholder:$}),children:$?y??"":oe}),m("span",{"aria-hidden":"true",className:N.triggerIcon({size:d,open:u}),children:m(ue,{component:me})})]})}),m(L.Portal,{children:m("div",{"aria-activedescendant":re,"aria-label":r,"aria-labelledby":c,"aria-multiselectable":o||void 0,className:N.listbox(),onBlur:ne,onKeyDown:ae,ref:e=>{A.current=e,e&&u&&le()},role:"listbox",style:{minWidth:(s=E.current)==null?void 0:s.offsetWidth},tabIndex:-1,children:R.map(ce)})})]})});U.displayName="Select";export{U as default};
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSelectNavigation } from './useSelectNavigation';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Dispatch, FocusEvent, KeyboardEvent, MutableRefObject, RefObject, SetStateAction } from 'react';
|
|
2
|
+
interface UseSelectNavigationOptions {
|
|
3
|
+
open: boolean;
|
|
4
|
+
selectedIndex: number;
|
|
5
|
+
enabledIndices: number[];
|
|
6
|
+
triggerRef: RefObject<HTMLButtonElement>;
|
|
7
|
+
listboxRef: RefObject<HTMLDivElement>;
|
|
8
|
+
optionRefs: MutableRefObject<(HTMLDivElement | null)[]>;
|
|
9
|
+
onOpen: () => void;
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
onSelect: (index: number) => void;
|
|
12
|
+
}
|
|
13
|
+
interface UseSelectNavigationReturn {
|
|
14
|
+
activeIndex: number;
|
|
15
|
+
setActiveIndex: Dispatch<SetStateAction<number>>;
|
|
16
|
+
focusListbox: () => void;
|
|
17
|
+
handleTriggerKeyDown: (evt: KeyboardEvent<HTMLButtonElement>) => void;
|
|
18
|
+
handleListboxKeyDown: (evt: KeyboardEvent<HTMLDivElement>) => void;
|
|
19
|
+
handleListboxBlur: (evt: FocusEvent<HTMLDivElement>) => void;
|
|
20
|
+
focusTrigger: () => void;
|
|
21
|
+
}
|
|
22
|
+
export declare const useSelectNavigation: ({ open, selectedIndex, enabledIndices, triggerRef, listboxRef, optionRefs, onOpen, onClose, onSelect, }: UseSelectNavigationOptions) => UseSelectNavigationReturn;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useEffectCallback as i,useIsomorphicLayoutEffect as v}from"@nild/hooks";import{useRef as I,useState as L}from"react";const x=n=>{if(typeof window>"u"||!n)return;const s=n.ownerDocument;s.activeElement!==n&&window.requestAnimationFrame(()=>{n.isConnected&&s.activeElement!==n&&n.focus()})},T=({open:n,selectedIndex:s,enabledIndices:t,triggerRef:k,listboxRef:D,optionRefs:g,onOpen:p,onClose:l,onSelect:m})=>{const d=I(!1),[o,f]=L(-1),w=i(()=>x(D.current)),b=i(()=>x(k.current)),a=e=>f(r=>{const c=t.length-1;if(c<0)return-1;if(e==="start")return t[0];if(e==="end")return t[c];const u=t.indexOf(r);if(u===-1)return e===1?t[0]:t[c];const A=Math.min(Math.max(u+e,0),c);return t[A]}),h=i(e=>{if(t.length!==0)switch(e.key){case"ArrowDown":e.preventDefault(),n?a(1):p();break;case"ArrowUp":e.preventDefault(),n?a(-1):p();break;case"Home":n&&(e.preventDefault(),a("start"));break;case"End":n&&(e.preventDefault(),a("end"));break;case"Enter":case" ":e.preventDefault(),n?m(o):p();break;case"Escape":n&&(e.preventDefault(),l(),b());break}}),E=i(e=>{switch(e.key){case"ArrowDown":e.preventDefault(),a(1);break;case"ArrowUp":e.preventDefault(),a(-1);break;case"Home":e.preventDefault(),a("start");break;case"End":e.preventDefault(),a("end");break;case"Enter":case" ":e.preventDefault(),m(o);break;case"Escape":e.preventDefault(),l(),b();break;case"Tab":l();break}}),y=i(e=>{var r,c;const u=e.relatedTarget;(r=k.current)!=null&&r.contains(u)||(c=D.current)!=null&&c.contains(u)||l()});return v(()=>{if(!n){d.current=!1,f(-1);return}const e=s>=0?s:t[0]??-1;f(r=>d.current&&t.includes(r)?r:e),d.current=!0},[t,n,s]),v(()=>{n&&w()},[w,n]),v(()=>{if(!n||o<0||typeof window>"u")return;const e=window.requestAnimationFrame(()=>{var r;(r=g.current[o])==null||r.scrollIntoView({block:"nearest"})});return()=>window.cancelAnimationFrame(e)},[o,n]),{activeIndex:o,setActiveIndex:f,focusTrigger:b,focusListbox:w,handleTriggerKeyDown:h,handleListboxKeyDown:E,handleListboxBlur:y}};export{T as useSelectNavigation};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @category Components
|
|
3
|
+
*/
|
|
4
|
+
declare const Select: (<T>(props: import('./interfaces').SelectProps<T> & import('react').RefAttributes<HTMLButtonElement>) => import('react').ReactElement | null) & {
|
|
5
|
+
Option: <T>(props: import('./interfaces').SelectOptionProps<T> & import('react').RefAttributes<HTMLDivElement>) => import('react').ReactElement | null;
|
|
6
|
+
};
|
|
7
|
+
export type * from './interfaces';
|
|
8
|
+
export default Select;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import t from"./Option.js";import o from"./Select.js";const r=Object.assign(o,{Option:t});export{r as default};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SelectSize, SelectVariant } from '../interfaces';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
trigger: (props?: {
|
|
4
|
+
variant?: SelectVariant;
|
|
5
|
+
size?: SelectSize;
|
|
6
|
+
block?: boolean;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
open?: boolean;
|
|
9
|
+
} | undefined) => string;
|
|
10
|
+
triggerContent: (props?: {
|
|
11
|
+
size?: SelectSize;
|
|
12
|
+
placeholder?: boolean;
|
|
13
|
+
} | undefined) => string;
|
|
14
|
+
triggerIcon: (props?: {
|
|
15
|
+
size?: SelectSize;
|
|
16
|
+
open?: boolean;
|
|
17
|
+
} | undefined) => string;
|
|
18
|
+
listbox: (props?: object | undefined) => string;
|
|
19
|
+
option: (props?: {
|
|
20
|
+
size?: SelectSize;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
active?: boolean;
|
|
23
|
+
} | undefined) => string;
|
|
24
|
+
optionContent: (props?: object | undefined) => string;
|
|
25
|
+
optionLabel: (props?: object | undefined) => string;
|
|
26
|
+
optionIndicator: (props?: {
|
|
27
|
+
size?: SelectSize;
|
|
28
|
+
} | undefined) => string;
|
|
29
|
+
};
|
|
30
|
+
export default _default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{cva as e}from"@nild/shared";import{DISABLED_CLS as t}from"../../_shared/style/index.js";const n=e(["nd-select-trigger","group",["inline-flex","items-center"],"box-border","font-nd","overflow-hidden","text-left","appearance-none","border","transition-colors","outline-none",t],{variants:{variant:{outlined:["bg-transparent","border-main","enabled:hover:border-brand-hover"],filled:["bg-muted","border-subtle"]},size:{small:["h-6","text-sm","rounded-sm"],medium:["h-8","text-md","rounded-md"],large:["h-10","text-lg","rounded-md"]},block:{true:["flex","w-full"],false:""},disabled:{true:"",false:"cursor-pointer"},open:{true:["border-brand","z-1","ring-focused"],false:""}},compoundVariants:[{variant:"filled",disabled:!1,open:!1,className:["enabled:hover:bg-muted-hover","enabled:hover:border-muted"]},{variant:"filled",open:!0,className:["bg-muted-hover"]}]}),r=e(["nd-select-trigger-content","min-w-0","flex-auto","truncate"],{variants:{size:{small:["pl-2","text-sm"],medium:["pl-3","text-md"],large:["pl-4","text-lg"]},placeholder:{true:["text-subtle"],false:["text-main"]}}}),o=e(["nd-select-trigger-icon","shrink-0","inline-flex","items-center","text-muted","transition-transform"],{variants:{size:{small:["px-2","text-sm"],medium:["px-3","text-md"],large:["px-4","text-lg"]},open:{true:["rotate-180"],false:""}}}),l=e(["nd-select-listbox","max-h-60","overflow-auto","overscroll-contain","px-1","py-1","outline-none"]),i=e(["nd-select-option","w-full","flex","items-center","gap-2","rounded-sm","text-left","text-main","select-none","transition-colors"],{variants:{size:{small:["min-h-8","px-2","text-sm"],medium:["min-h-9","px-3","text-md"],large:["min-h-10","px-4","text-lg"]},disabled:{true:["cursor-not-allowed","select-none","text-subtle","opacity-50"],false:["cursor-pointer","hover:bg-muted-hover"]},active:{true:["bg-muted"],false:""}}}),a=e(["nd-select-option-content","min-w-0","flex-auto"]),s=e(["nd-select-option-label","block","truncate"]),d=e(["nd-select-option-indicator","shrink-0","inline-flex","items-center","justify-center"],{variants:{size:{small:["size-3.5","text-sm"],medium:["size-4","text-md"],large:["size-4.5","text-lg"]}}}),m={trigger:n,triggerContent:r,triggerIcon:o,listbox:l,option:i,optionContent:a,optionLabel:s,optionIndicator:d};export{m as default};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nild/components",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.40",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"react": "^18.2.0",
|
|
33
33
|
"react-dom": "^18.2.0",
|
|
34
34
|
"@nild/shared": "0.0.16",
|
|
35
|
-
"@nild/
|
|
36
|
-
"@nild/
|
|
35
|
+
"@nild/hooks": "0.0.18",
|
|
36
|
+
"@nild/icons": "0.0.18"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "vite build --mode PROD",
|