@nild/components 0.0.38 → 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.
Files changed (66) hide show
  1. package/dist/_shared/utils/get-global-state/__tests__/index.test.d.ts +1 -0
  2. package/dist/_shared/utils/get-global-state/index.d.ts +5 -0
  3. package/dist/_shared/utils/get-global-state/index.js +1 -0
  4. package/dist/_shared/utils/get-owner-document/__tests__/index.test.d.ts +1 -0
  5. package/dist/_shared/utils/get-owner-document/index.d.ts +2 -0
  6. package/dist/_shared/utils/get-owner-document/index.js +1 -0
  7. package/dist/_shared/utils/index.d.ts +4 -1
  8. package/dist/_shared/utils/lock-document-scroll/__tests__/index.test.d.ts +1 -0
  9. package/dist/_shared/utils/lock-document-scroll/index.d.ts +2 -0
  10. package/dist/_shared/utils/lock-document-scroll/index.js +1 -0
  11. package/dist/_shared/utils/merge-handlers/index.js +1 -0
  12. package/dist/_shared/utils/merge-props/index.js +1 -0
  13. package/dist/index.d.ts +4 -2
  14. package/dist/index.js +1 -1
  15. package/dist/modal/Body.d.ts +5 -0
  16. package/dist/modal/Body.js +1 -0
  17. package/dist/modal/Close.d.ts +5 -0
  18. package/dist/modal/Close.js +1 -0
  19. package/dist/modal/Footer.d.ts +5 -0
  20. package/dist/modal/Footer.js +1 -0
  21. package/dist/modal/Header.d.ts +5 -0
  22. package/dist/modal/Header.js +1 -0
  23. package/dist/modal/Modal.d.ts +4 -0
  24. package/dist/modal/Modal.js +1 -0
  25. package/dist/modal/Portal.d.ts +5 -0
  26. package/dist/modal/Portal.js +1 -0
  27. package/dist/modal/Trigger.d.ts +5 -0
  28. package/dist/modal/Trigger.js +1 -0
  29. package/dist/modal/__tests__/Modal.test.d.ts +0 -0
  30. package/dist/modal/_shared/__tests__/index.test.d.ts +1 -0
  31. package/dist/modal/_shared/index.d.ts +2 -0
  32. package/dist/modal/_shared/index.js +1 -0
  33. package/dist/modal/_shared/stack.d.ts +7 -0
  34. package/dist/modal/_shared/stack.js +1 -0
  35. package/dist/modal/contexts/index.d.ts +21 -0
  36. package/dist/modal/contexts/index.js +1 -0
  37. package/dist/modal/hooks/index.d.ts +2 -0
  38. package/dist/modal/hooks/useModalFocusScope.d.ts +12 -0
  39. package/dist/modal/hooks/useModalFocusScope.js +1 -0
  40. package/dist/modal/hooks/useModalStack.d.ts +4 -0
  41. package/dist/modal/hooks/useModalStack.js +1 -0
  42. package/dist/modal/index.d.ts +13 -0
  43. package/dist/modal/index.js +1 -0
  44. package/dist/modal/style/index.d.ts +27 -0
  45. package/dist/modal/style/index.js +1 -0
  46. package/dist/popup/Trigger.js +1 -1
  47. package/dist/select/Option.d.ts +5 -0
  48. package/dist/select/Option.js +1 -0
  49. package/dist/select/Select.d.ts +4 -0
  50. package/dist/select/Select.js +1 -0
  51. package/dist/select/__tests__/Select.test.d.ts +0 -0
  52. package/dist/select/hooks/index.d.ts +1 -0
  53. package/dist/select/hooks/useSelectNavigation.d.ts +23 -0
  54. package/dist/select/hooks/useSelectNavigation.js +1 -0
  55. package/dist/select/index.d.ts +8 -0
  56. package/dist/select/index.js +1 -0
  57. package/dist/select/style/index.d.ts +30 -0
  58. package/dist/select/style/index.js +1 -0
  59. package/dist/transition/Transition.js +1 -1
  60. package/dist/transition/__tests__/Transition.test.d.ts +0 -0
  61. package/dist/transition/index.d.ts +1 -1
  62. package/dist/transition/interfaces/index.d.ts +2 -2
  63. package/dist/transition/interfaces/index.js +1 -1
  64. package/dist/transition/style/index.d.ts +2 -2
  65. package/dist/transition/style/index.js +1 -1
  66. package/package.json +1 -1
@@ -0,0 +1,5 @@
1
+ export declare enum GlobalStateKey {
2
+ Modal = "@nild/components/modal-global-state"
3
+ }
4
+ declare const getGlobalState: <State>(key: GlobalStateKey | string, createState: () => State) => State;
5
+ export default getGlobalState;
@@ -0,0 +1 @@
1
+ var t=(l=>(l.Modal="@nild/components/modal-global-state",l))(t||{});const n=(l,e)=>{const a=Symbol.for(l),o=globalThis;return a in o||(o[a]=e()),o[a]};export{t as GlobalStateKey,n as default};
@@ -0,0 +1,2 @@
1
+ declare const getOwnerDocument: (...nodes: Array<Node | null | undefined>) => Document | null;
2
+ export default getOwnerDocument;
@@ -0,0 +1 @@
1
+ import{isBrowser as e}from"@nild/shared";const r=(...t)=>{var o;return((o=t.find(n=>n?.ownerDocument))==null?void 0:o.ownerDocument)||(e()?document:null)};export{r as default};
@@ -1,5 +1,8 @@
1
+ import { default as getGlobalState, GlobalStateKey } from './get-global-state';
2
+ import { default as getOwnerDocument } from './get-owner-document';
1
3
  import { default as isPlainChildren } from './is-plain-children';
4
+ import { default as lockDocumentScroll } from './lock-document-scroll';
2
5
  import { default as mergeHandlers } from './merge-handlers';
3
6
  import { default as mergeProps } from './merge-props';
4
7
  import { default as registerSlots } from './register-slots';
5
- export { registerSlots, isPlainChildren, mergeHandlers, mergeProps };
8
+ export { getGlobalState, getOwnerDocument, GlobalStateKey, isPlainChildren, lockDocumentScroll, registerSlots, mergeHandlers, mergeProps, };
@@ -0,0 +1,2 @@
1
+ declare const lockDocumentScroll: (doc: Document) => () => void;
2
+ export default lockDocumentScroll;
@@ -0,0 +1 @@
1
+ import{isBrowser as r}from"@nild/shared";let t=0,n="",i="";const a=e=>{const o=e.defaultView??(r()?window:null);return o?[e.documentElement,e.body].some(d=>{const l=o.getComputedStyle(d),s=l.getPropertyValue("scrollbar-gutter")||l.scrollbarGutter||"";return/\bstable\b/.test(s)}):!1},y=e=>{if(!r())return()=>{};if(t===0){n=e.body.style.overflow,i=e.body.style.paddingRight;const o=Number.parseFloat(window.getComputedStyle(e.body).paddingRight||"0")||0,d=e.documentElement.clientWidth>0?window.innerWidth-e.documentElement.clientWidth:0,l=!a(e);e.body.style.overflow="hidden",l&&d>0&&(e.body.style.paddingRight=`${o+d}px`)}return t+=1,()=>{t=Math.max(0,t-1),t===0&&(e.body.style.overflow=n,e.body.style.paddingRight=i)}};export{y as default};
@@ -0,0 +1 @@
1
+ const n=e=>typeof e=="object"&&e!==null&&"defaultPrevented"in e,r=(...e)=>(...t)=>{const[o]=t;for(const f of e)if(f&&(f(...t),n(o)&&o.defaultPrevented))break};export{r as default};
@@ -0,0 +1 @@
1
+ import{cnMerge as a}from"@nild/shared";import i from"../merge-handlers/index.js";const l=(o,n)=>{const c={...o,...n},f=new Set([...Object.keys(o),...Object.keys(n)]);for(const s of f){if(s==="className"){const t=o.className,e=n.className;(t||e)&&(c.className=a(e,t));continue}if(s==="style"){const t=o.style,e=n.style;(t||e)&&(c.style={...e,...t});continue}if(/^on[A-Z]/.test(s)){const t=o[s],e=n[s];(typeof t=="function"||typeof e=="function")&&(c[s]=i(t,e))}}return c};export{l as default};
package/dist/index.d.ts CHANGED
@@ -2,10 +2,12 @@ import { default as Button } from './button';
2
2
  import { default as Checkbox } from './checkbox';
3
3
  import { default as Divider } from './divider';
4
4
  import { default as Input } from './input';
5
+ import { default as Modal } from './modal';
5
6
  import { default as Popover } from './popover';
6
7
  import { default as Radio } from './radio';
8
+ import { default as Select } from './select';
7
9
  import { default as Switch } from './switch';
8
10
  import { default as Tooltip } from './tooltip';
9
- import { default as Transition } from './transition';
11
+ import { default as Transition, TransitionStatus } from './transition';
10
12
  import { default as Typography } from './typography';
11
- export { Button, Checkbox, Divider, Popover, Radio, Switch, Tooltip, Transition, Typography, Input };
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"./popover/index.js";import{default as f}from"./radio/index.js";import{default as m}from"./switch/index.js";import{default as i}from"./tooltip/index.js";import{default as p}from"./transition/Transition.js";import{default as e}from"./typography/index.js";/* empty css */export{a as Button,o as Checkbox,t as Divider,r as Input,s as Popover,f as Radio,m as Switch,i as Tooltip,p as Transition,e as Typography};
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};
@@ -0,0 +1,5 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { BodyProps } from './interfaces';
3
+ export declare const isBodyElement: (child: ReactNode) => child is ReactElement<BodyProps>;
4
+ declare const Body: import('react').ForwardRefExoticComponent<BodyProps & import('react').RefAttributes<HTMLDivElement>>;
5
+ export default Body;
@@ -0,0 +1 @@
1
+ import{jsx as m}from"react/jsx-runtime";import{cnMerge as d}from"@nild/shared";import{forwardRef as i,isValidElement as l}from"react";import t from"./style/index.js";const f=a=>l(a)&&a.type===e,e=i(({className:a,children:r,...s},o)=>m("div",{...s,className:d(t.body(),a),ref:o,children:r}));e.displayName="Modal.Body";export{e as default,f as isBodyElement};
@@ -0,0 +1,5 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { CloseProps } from './interfaces';
3
+ export declare const isCloseElement: (child: ReactNode) => child is ReactElement<CloseProps>;
4
+ declare const Close: import('react').ForwardRefExoticComponent<import('../button').ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
5
+ export default Close;
@@ -0,0 +1 @@
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};
@@ -0,0 +1,5 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { FooterProps } from './interfaces';
3
+ export declare const isFooterElement: (child: ReactNode) => child is ReactElement<FooterProps>;
4
+ declare const Footer: import('react').ForwardRefExoticComponent<FooterProps & import('react').RefAttributes<HTMLDivElement>>;
5
+ export default Footer;
@@ -0,0 +1 @@
1
+ import{jsx as m}from"react/jsx-runtime";import{cnMerge as t}from"@nild/shared";import{forwardRef as i,isValidElement as f}from"react";import l from"./style/index.js";const d=e=>f(e)&&e.type===r,r=i(({className:e,children:a,...o},s)=>m("div",{...o,className:t(l.footer(),e),ref:s,children:a}));r.displayName="Modal.Footer";export{r as default,d as isFooterElement};
@@ -0,0 +1,5 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { HeaderProps } from './interfaces';
3
+ export declare const isHeaderElement: (child: ReactNode) => child is ReactElement<HeaderProps>;
4
+ declare const Header: import('react').ForwardRefExoticComponent<HeaderProps & import('react').RefAttributes<HTMLDivElement>>;
5
+ export default Header;
@@ -0,0 +1 @@
1
+ import{jsx as d}from"react/jsx-runtime";import{cnMerge as i}from"@nild/shared";import{forwardRef as o,isValidElement as l}from"react";import t from"./style/index.js";const f=e=>l(e)&&e.type===a,a=o(({className:e,children:r,...s},m)=>d("div",{...s,className:i(t.header(),e),ref:m,children:r}));a.displayName="Modal.Header";export{a as default,f as isHeaderElement};
@@ -0,0 +1,4 @@
1
+ import { FC } from 'react';
2
+ import { ModalProps } from './interfaces';
3
+ declare const Modal: FC<ModalProps>;
4
+ export default Modal;
@@ -0,0 +1 @@
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};
@@ -0,0 +1,5 @@
1
+ import { ReactElement } from 'react';
2
+ import { PortalProps } from './interfaces';
3
+ export declare const isPortalElement: (child: unknown) => child is ReactElement<PortalProps>;
4
+ declare const Portal: import('react').ForwardRefExoticComponent<PortalProps & import('react').RefAttributes<HTMLDivElement>>;
5
+ export default Portal;
@@ -0,0 +1 @@
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};
@@ -0,0 +1,5 @@
1
+ import { FC, ReactElement } from 'react';
2
+ import { TriggerProps } from './interfaces';
3
+ export declare const isTriggerElement: (child: unknown) => child is ReactElement<TriggerProps>;
4
+ declare const Trigger: FC<TriggerProps>;
5
+ export default Trigger;
@@ -0,0 +1 @@
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};
File without changes
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ import { ModalPlacement, ModalVariant } from '../interfaces';
2
+ export declare const resolvePlacement: (variant: ModalVariant, placement?: ModalPlacement) => ModalPlacement;
@@ -0,0 +1 @@
1
+ const r=(t,e)=>t==="drawer"?e&&e!=="center"?e:"right":"center";export{r as resolvePlacement};
@@ -0,0 +1,7 @@
1
+ export declare const EMPTY_MODAL_STACK: readonly symbol[];
2
+ export interface ModalStackStore {
3
+ getSnapshot: () => readonly symbol[];
4
+ mount: (token: symbol) => VoidFunction;
5
+ subscribe: (listener: VoidFunction) => VoidFunction;
6
+ }
7
+ export declare const getModalStackStore: (ownerDocument: Document) => ModalStackStore;
@@ -0,0 +1 @@
1
+ import c,{GlobalStateKey as i}from"../../_shared/utils/get-global-state/index.js";import"@nild/shared";import"react";const a=[],l=()=>{const t=[],o=new Set;let s=a;const n=()=>{s=[...t],o.forEach(e=>{e()})};return{getSnapshot:()=>s,mount:e=>(t.includes(e)||(t.push(e),n()),()=>{const r=t.indexOf(e);r!==-1&&(t.splice(r,1),n())}),subscribe:e=>(o.add(e),()=>{o.delete(e)})}},p=t=>{const o=c(i.Modal,()=>new WeakMap),s=o.get(t);if(s)return s;const n=l();return o.set(t,n),n};export{a as EMPTY_MODAL_STACK,p as getModalStackStore};
@@ -0,0 +1,21 @@
1
+ import { Dispatch, RefObject, SetStateAction } from 'react';
2
+ import { ModalAccessibility, ModalPlacement, ModalSize, ModalVariant } from '../interfaces';
3
+ export interface ModalContextValue {
4
+ open: boolean;
5
+ variant: ModalVariant;
6
+ placement: ModalPlacement;
7
+ size: ModalSize;
8
+ disabled: boolean;
9
+ closeOnEscape: boolean;
10
+ closeOnOverlayClick: boolean;
11
+ trapFocus: boolean;
12
+ restoreFocus: boolean;
13
+ lockScroll: boolean;
14
+ accessibility: ModalAccessibility;
15
+ refs: {
16
+ trigger: RefObject<Element>;
17
+ };
18
+ updateOpen: Dispatch<SetStateAction<boolean>>;
19
+ }
20
+ declare const ModalProvider: import('react').Provider<ModalContextValue>, useModalContext: () => ModalContextValue;
21
+ export { ModalProvider, useModalContext };
@@ -0,0 +1 @@
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,2 @@
1
+ export { useModalStack } from './useModalStack';
2
+ export { useModalFocusScope } from './useModalFocusScope';
@@ -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};
@@ -0,0 +1,4 @@
1
+ export declare const useModalStack: (ownerDocument: Document | null, present: boolean) => {
2
+ zIndex: number;
3
+ topmost: boolean;
4
+ };
@@ -0,0 +1 @@
1
+ import{useRef as l,useEffect as m,useSyncExternalStore as S}from"react";import{getModalStackStore as d,EMPTY_MODAL_STACK as u}from"../_shared/stack.js";const f=40,i=(e,o)=>{const r=l(Symbol("modal")),t=e?d(e):null;m(()=>{if(!(!o||!t))return t.mount(r.current)},[o,t]);const n=S(c=>t?.subscribe(c)??(()=>{}),()=>t?.getSnapshot()??u,()=>u),s=n.indexOf(r.current),a=n.at(-1)===r.current;return{zIndex:f+(s===-1?0:s),topmost:a}};export{i as useModalStack};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @category Components
3
+ */
4
+ declare const Modal: import('react').FC<import('./interfaces').ModalProps> & {
5
+ Trigger: import('react').FC<import('./interfaces').TriggerProps>;
6
+ Portal: import('react').ForwardRefExoticComponent<import('./interfaces').PortalProps & import('react').RefAttributes<HTMLDivElement>>;
7
+ Header: import('react').ForwardRefExoticComponent<import('./interfaces').HeaderProps & import('react').RefAttributes<HTMLDivElement>>;
8
+ Body: import('react').ForwardRefExoticComponent<import('./interfaces').BodyProps & import('react').RefAttributes<HTMLDivElement>>;
9
+ Footer: import('react').ForwardRefExoticComponent<import('./interfaces').FooterProps & import('react').RefAttributes<HTMLDivElement>>;
10
+ Close: import('react').ForwardRefExoticComponent<import('../button').ButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
11
+ };
12
+ export type * from './interfaces';
13
+ export default Modal;
@@ -0,0 +1 @@
1
+ import o from"./Body.js";import r from"./Close.js";import m from"./Footer.js";import t from"./Header.js";import i from"./Modal.js";import e from"./Portal.js";import f from"./Trigger.js";const p=Object.assign(i,{Trigger:f,Portal:e,Header:t,Body:o,Footer:m,Close:r});export{p as default};
@@ -0,0 +1,27 @@
1
+ import { TransitionStatus } from '../../transition/interfaces';
2
+ import { ModalPlacement, ModalSize, ModalVariant } from '../interfaces';
3
+ declare const _default: {
4
+ trigger: (props?: object | undefined) => string;
5
+ portal: (props?: {
6
+ placement: ModalPlacement;
7
+ } | undefined) => string;
8
+ overlay: (props?: object | undefined) => string;
9
+ overlayMotion: (props?: {
10
+ status: TransitionStatus;
11
+ } | undefined) => string;
12
+ surfaceMotion: (props?: {
13
+ status: TransitionStatus;
14
+ variant: ModalVariant;
15
+ placement: ModalPlacement;
16
+ } | undefined) => string;
17
+ header: (props?: object | undefined) => string;
18
+ body: (props?: object | undefined) => string;
19
+ footer: (props?: object | undefined) => string;
20
+ close: (props?: object | undefined) => string;
21
+ surface: (props?: {
22
+ variant: ModalVariant;
23
+ placement: ModalPlacement;
24
+ size: ModalSize;
25
+ } | undefined) => string;
26
+ };
27
+ export default _default;
@@ -0,0 +1 @@
1
+ import{cva as e}from"@nild/shared";import{TransitionStatus as a}from"../../transition/interfaces/index.js";const t=[a.UNMOUNTED,a.ENTERING,a.EXITING,a.EXITED],r=e(["nd-modal-trigger"]),s=e(["nd-modal-portal","fixed","inset-0","flex","pointer-events-auto"],{variants:{placement:{center:["items-center","justify-center","p-4"],left:["items-stretch","justify-start"],right:["items-stretch","justify-end"],top:["items-start","justify-center"],bottom:["items-end","justify-center"]}}}),l=e(["nd-modal-overlay","absolute","inset-0","transition-opacity","duration-[var(--default-transition-duration)]","ease-out","bg-[color-mix(in_oklch,var(--background-color-page-inverse)_18%,transparent)]"]),n=e([],{variants:{status:{[a.UNMOUNTED]:"",[a.ENTERING]:"",[a.ENTERED]:"",[a.EXITING]:"",[a.EXITED]:""}},compoundVariants:[{status:t,className:"opacity-0"},{status:a.ENTERED,className:"opacity-100"}]}),o=e(["nd-modal-header","shrink-0","px-6","pt-6","pb-4","pr-16","text-lg","font-semibold"]),i=e(["nd-modal-body","min-h-0","flex-auto","overflow-auto","px-6","pb-6"]),m=e(["nd-modal-footer","shrink-0","flex","justify-end","gap-3","border-t","border-subtle","px-6","py-4"]),c=e(["nd-modal-close","absolute","top-4","right-6","z-1"]),d=e(["nd-modal-surface","relative","pointer-events-auto","flex","min-h-0","flex-col","overflow-hidden","bg-panel","text-main","shadow-2xl","outline-none","transition-[opacity,translate,scale]","duration-[var(--default-transition-duration)]","ease-out"],{variants:{variant:{dialog:"",drawer:""},placement:{center:["w-full","max-h-[calc(100vh-2rem)]"],left:["h-full","max-h-screen"],right:["h-full","max-h-screen"],top:["w-full","max-w-screen"],bottom:["w-full","max-w-screen"]},size:{small:"",medium:"",large:"",full:""}},compoundVariants:[{variant:"dialog",placement:"center",size:"small",className:["max-w-96","rounded-xl"]},{variant:"dialog",placement:"center",size:"medium",className:["max-w-[36rem]","rounded-xl"]},{variant:"dialog",placement:"center",size:"large",className:["max-w-[48rem]","rounded-xl"]},{variant:"dialog",placement:"center",size:"full",className:["h-[calc(100vh-2rem)]","w-[calc(100vw-2rem)]","max-w-none","rounded-xl"]},{variant:"drawer",placement:["left","right"],size:"small",className:"w-80"},{variant:"drawer",placement:["left","right"],size:"medium",className:"w-[28rem]"},{variant:"drawer",placement:["left","right"],size:"large",className:"w-[36rem]"},{variant:"drawer",placement:["left","right"],size:"full",className:"w-screen"},{variant:"drawer",placement:["top","bottom"],size:"small",className:"h-64"},{variant:"drawer",placement:["top","bottom"],size:"medium",className:"h-96"},{variant:"drawer",placement:["top","bottom"],size:"large",className:"h-[32rem]"},{variant:"drawer",placement:["top","bottom"],size:"full",className:"h-screen"}]}),u=e([],{variants:{status:{[a.UNMOUNTED]:"",[a.ENTERING]:"",[a.ENTERED]:"",[a.EXITING]:"",[a.EXITED]:""},variant:{dialog:"",drawer:""},placement:{center:"",left:"",right:"",top:"",bottom:""}},compoundVariants:[{status:t,variant:"dialog",className:["opacity-0","scale-95"]},{status:a.ENTERED,variant:"dialog",className:["opacity-100","scale-100"]},{status:t,variant:"drawer",placement:"left",className:"-translate-x-full"},{status:a.ENTERED,variant:"drawer",placement:"left",className:"translate-x-0"},{status:t,variant:"drawer",placement:"right",className:"translate-x-full"},{status:a.ENTERED,variant:"drawer",placement:"right",className:"translate-x-0"},{status:t,variant:"drawer",placement:"top",className:"-translate-y-full"},{status:a.ENTERED,variant:"drawer",placement:"top",className:"translate-y-0"},{status:t,variant:"drawer",placement:"bottom",className:"translate-y-full"},{status:a.ENTERED,variant:"drawer",placement:"bottom",className:"translate-y-0"}]}),p={trigger:r,portal:s,overlay:l,overlayMotion:n,surfaceMotion:u,header:o,body:i,footer:m,close:c,surface:d};export{p as default};
@@ -1 +1 @@
1
- import{useEffectCallback as u,useEventListener as m}from"@nild/hooks";import{mergeRefs as N,cnJoin as w}from"@nild/shared";import{Children as y,isValidElement as B,cloneElement as F}from"react";import{usePopupContext as P}from"./contexts/index.js";import b from"./style/index.js";const f=({children:g})=>{var p,v;const{actions:r,refs:a,setOpen:s,enter:h,leave:x}=P(),o=y.toArray(g).find(e=>B(e)),d=r.has("click")||r.has("contextMenu")?window:null,E=u(e=>{var l,n;(n=(l=o?.props)==null?void 0:l.onMouseEnter)==null||n.call(l,e),h()}),M=u(e=>{var l,n;(n=(l=o?.props)==null?void 0:l.onMouseLeave)==null||n.call(l,e),x()}),k=u(e=>{var l,n;(n=(l=o?.props)==null?void 0:l.onFocus)==null||n.call(l,e),r.has("focus")&&s(!0)}),C=u(e=>{var l,n;(n=(l=o?.props)==null?void 0:l.onBlur)==null||n.call(l,e),r.has("focus")&&s(!1)});return m(d,"click",e=>{var l,n;const t=e.target,i=(l=a.trigger.current)==null?void 0:l.contains(t),c=(n=a.portal.current)==null?void 0:n.contains(t);i?(r.has("click")&&s(L=>!L),r.has("contextMenu")&&s(!1)):!c&&s(!1)}),m(d,"contextmenu",e=>{var l,n;const t=e.target,i=(l=a.trigger.current)==null?void 0:l.contains(t),c=(n=a.portal.current)==null?void 0:n.contains(t);i?r.has("contextMenu")&&(e.preventDefault(),s(!0)):!c&&s(!1)}),o?F(o,{...o?.props,className:w(b.trigger(),(p=o?.props)==null?void 0:p.className),onMouseEnter:E,onMouseLeave:M,onFocus:k,onBlur:C,ref:N(a.trigger,(v=o?.props)==null?void 0:v.ref)}):null};f.displayName="Popup.Trigger";export{f as default};
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,4 @@
1
+ import { ReactElement, RefAttributes } from 'react';
2
+ import { SelectProps } from './interfaces';
3
+ declare const Select: <T>(props: SelectProps<T> & RefAttributes<HTMLButtonElement>) => ReactElement | null;
4
+ export default Select;
@@ -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};
@@ -1 +1 @@
1
- import{useEffectCallback as N}from"@nild/hooks";import{cnMerge as R}from"@nild/shared";import{Children as X,isValidElement as M,useState as O,useRef as m,useEffect as D,cloneElement as b}from"react";import{Status as r}from"./interfaces/index.js";import G from"./style/index.js";const I=({className:U,children:f,visible:i=!0})=>{const s=X.toArray(f).find(o=>M(o)),a=s?i?r.ENTERED:r.EXITED:r.UNMOUNTED,[t,E]=O(a),e=m(),n=m(s);n.current=t===r.UNMOUNTED?s:s??n.current;const c=N(o=>{u();let T=!0;const l=()=>{T&&(T=!1,e.current=void 0,o?.())};l.cancel=()=>{T=!1},e.current=l}),d=N(()=>{e.current&&(e.current(),e.current=void 0)}),u=N(()=>{e.current&&(e.current.cancel(),e.current=void 0)}),p=N(()=>{a===r.UNMOUNTED&&t===r.EXITED&&E(r.UNMOUNTED)});return D(()=>{d()},[t]),D(()=>{switch(a){case r.ENTERED:t!==r.ENTERING&&t!==r.ENTERED&&(t===r.UNMOUNTED?E(r.EXITED):(u(),E(r.ENTERING),c(()=>{c(()=>{E(r.ENTERED)}),e.current&&setTimeout(e.current,0)})));break;case r.EXITED:(t===r.ENTERING||t===r.ENTERED)&&(u(),E(r.EXITING),c(()=>{c(()=>{E(r.EXITED)}),e.current&&setTimeout(e.current,0)}));break;case r.UNMOUNTED:default:t!==r.EXITED&&t!==r.UNMOUNTED&&(u(),E(r.EXITING),c(()=>{c(()=>{E(r.EXITED)}),e.current&&setTimeout(e.current,0)}));break}},[i,a,t]),n.current?b(n.current,{...n.current.props,className:R(n.current.props.className,G.transition({status:t}),U),onTransitionEnd:p}):null};I.displayName="Transition";export{I as default};
1
+ import{cnMerge as M,isFunction as I}from"@nild/shared";import{useState as O,useRef as U,useEffect as f,cloneElement as G,Children as v,isValidElement as g}from"react";import h from"../_shared/utils/merge-handlers/index.js";import{TransitionStatus as r}from"./interfaces/index.js";import S from"./style/index.js";const d=(e,s)=>{const c=I(e)?e(s):e;return v.toArray(c).find(t=>g(t))},R=({className:e,children:s,visible:c=!0})=>{const[t,N]=O(()=>{const n=c?r.ENTERED:r.EXITED;return d(s,n)?n:r.UNMOUNTED}),i=d(s,t),T=i?c?r.ENTERED:r.EXITED:r.UNMOUNTED,E=U(),u=U(i);u.current=t===r.UNMOUNTED?i:i??u.current;const l=()=>{var n;(n=E.current)==null||n.cancel(),E.current=void 0},m=n=>{l();let o=!0;const p=()=>{o&&(o=!1,E.current=void 0,n())};p.cancel=()=>{o=!1},E.current=p},D=(n,o)=>{l(),N(n),m(()=>{m(()=>{N(o)}),E.current&&setTimeout(E.current,0)})},X=n=>{n&&n.target!==n.currentTarget||T===r.UNMOUNTED&&t===r.EXITED&&N(r.UNMOUNTED)};if(f(()=>{E.current&&(E.current(),E.current=void 0)},[t]),f(()=>{if(T===r.ENTERED){t===r.UNMOUNTED?N(r.EXITED):t!==r.ENTERING&&t!==r.ENTERED&&D(r.ENTERING,r.ENTERED);return}if(T===r.EXITED){(t===r.ENTERING||t===r.ENTERED)&&D(r.EXITING,r.EXITED);return}t!==r.EXITED&&t!==r.UNMOUNTED&&D(r.EXITING,r.EXITED)},[T,t]),!u.current)return null;const a=u.current;return G(a,{...a.props,className:I(s)?a.props.className:M(a.props.className,S.transition({status:t}),e),onTransitionEnd:h(a.props.onTransitionEnd,X)})};R.displayName="Transition";export{R as default};
File without changes
@@ -1,3 +1,3 @@
1
1
  import { default as Transition } from './Transition';
2
- export type * from './interfaces';
2
+ export * from './interfaces';
3
3
  export default Transition;
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from 'react';
2
- export declare enum Status {
2
+ export declare enum TransitionStatus {
3
3
  UNMOUNTED = "unmounted",
4
4
  ENTERING = "entering",
5
5
  ENTERED = "entered",
@@ -8,6 +8,6 @@ export declare enum Status {
8
8
  }
9
9
  export interface TransitionProps {
10
10
  className?: string;
11
- children?: ReactNode;
11
+ children?: ReactNode | ((status: TransitionStatus) => ReactNode);
12
12
  visible?: boolean;
13
13
  }
@@ -1 +1 @@
1
- var t=(E=>(E.UNMOUNTED="unmounted",E.ENTERING="entering",E.ENTERED="entered",E.EXITING="exiting",E.EXITED="exited",E))(t||{});export{t as Status};
1
+ var t=(E=>(E.UNMOUNTED="unmounted",E.ENTERING="entering",E.ENTERED="entered",E.EXITING="exiting",E.EXITED="exited",E))(t||{});export{t as TransitionStatus};
@@ -1,7 +1,7 @@
1
- import { Status } from '../interfaces';
1
+ import { TransitionStatus } from '../interfaces';
2
2
  declare const _default: {
3
3
  transition: (props?: {
4
- status: Status;
4
+ status: TransitionStatus;
5
5
  } | undefined) => string;
6
6
  };
7
7
  export default _default;
@@ -1 +1 @@
1
- import{cva as a}from"@nild/shared";import{Status as t}from"../interfaces/index.js";const i=a(["transition-[opacity,visibility]"],{compoundVariants:[{status:t.ENTERED,className:["opacity-100","visible"]},{status:[t.UNMOUNTED,t.ENTERING,t.EXITING,t.EXITED],className:["opacity-0","invisible"]}]}),s={transition:i};export{s as default};
1
+ import{cva as t}from"@nild/shared";import{TransitionStatus as i}from"../interfaces/index.js";const a=t(["transition-[opacity,visibility]"],{compoundVariants:[{status:i.ENTERED,className:["opacity-100","visible"]},{status:[i.UNMOUNTED,i.ENTERING,i.EXITING,i.EXITED],className:["opacity-0","invisible"]}]}),s={transition:a};export{s 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.38",
4
+ "version": "0.0.40",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
7
7
  "exports": {