@ngrok/mantle 0.70.1 → 0.71.0

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 (161) hide show
  1. package/dist/accordion.d.ts +1 -1
  2. package/dist/alert-dialog.d.ts +341 -94
  3. package/dist/alert-dialog.js.map +1 -1
  4. package/dist/alert.d.ts +3 -3
  5. package/dist/alert.js.map +1 -1
  6. package/dist/anchor-2stEauOz.js.map +1 -1
  7. package/dist/anchor.d.ts +46 -5
  8. package/dist/{as-child-CJ2vTesV.d.ts → as-child-DQHfEmYB.d.ts} +1 -1
  9. package/dist/badge.d.ts +34 -5
  10. package/dist/badge.js.map +1 -1
  11. package/dist/{button-DDK6nEac.d.ts → button-Bq0x5Pv4.d.ts} +6 -6
  12. package/dist/button.d.ts +3 -3
  13. package/dist/card.d.ts +1 -1
  14. package/dist/checkbox.d.ts +1 -1
  15. package/dist/checkbox.js +1 -1
  16. package/dist/code-block.d.ts +3 -3
  17. package/dist/code-block.js +1 -1
  18. package/dist/code-block.js.map +1 -1
  19. package/dist/code-block_highlight-utils.d.ts +1 -1
  20. package/dist/code-block_highlight-utils.js +1 -1
  21. package/dist/code.d.ts +23 -2
  22. package/dist/code.js.map +1 -1
  23. package/dist/color.d.ts +1 -1
  24. package/dist/combobox.d.ts +12 -2
  25. package/dist/combobox.js +1 -1
  26. package/dist/combobox.js.map +1 -1
  27. package/dist/command.d.ts +3 -3
  28. package/dist/command.js +1 -1
  29. package/dist/command.js.map +1 -1
  30. package/dist/compose-refs-DZ3cPi47.js +2 -0
  31. package/dist/compose-refs-DZ3cPi47.js.map +1 -0
  32. package/dist/copy-to-clipboard-DjOD_Mwb.js +2 -0
  33. package/dist/copy-to-clipboard-DjOD_Mwb.js.map +1 -0
  34. package/dist/data-table.d.ts +530 -75
  35. package/dist/data-table.js +1 -1
  36. package/dist/data-table.js.map +1 -1
  37. package/dist/{deep-non-nullable-DwBZzk4x.d.ts → deep-non-nullable-VFm1T3JZ.d.ts} +1 -1
  38. package/dist/description-list.d.ts +1 -1
  39. package/dist/{dialog-MiS_Q-ge.js → dialog-BHzl9eye.js} +1 -1
  40. package/dist/dialog-BHzl9eye.js.map +1 -0
  41. package/dist/dialog.d.ts +8 -3
  42. package/dist/dialog.js +1 -1
  43. package/dist/{direction-ClCocWIf.js → direction-DsB-pD9V.js} +1 -1
  44. package/dist/{direction-ClCocWIf.js.map → direction-DsB-pD9V.js.map} +1 -1
  45. package/dist/{direction-Jk7BkzGo.d.ts → direction-DtBAQn7p.d.ts} +1 -1
  46. package/dist/{dropdown-menu-C9f9Y8Ov.d.ts → dropdown-menu-CzUNYIfA.d.ts} +2 -2
  47. package/dist/{dropdown-menu-Ff97BIJe.js → dropdown-menu-Ducs2SEn.js} +2 -2
  48. package/dist/{dropdown-menu-Ff97BIJe.js.map → dropdown-menu-Ducs2SEn.js.map} +1 -1
  49. package/dist/dropdown-menu.d.ts +1 -1
  50. package/dist/dropdown-menu.js +1 -1
  51. package/dist/empty.d.ts +2 -2
  52. package/dist/flag.d.ts +33 -4
  53. package/dist/flag.js.map +1 -1
  54. package/dist/hooks.d.ts +301 -77
  55. package/dist/hooks.js +1 -1
  56. package/dist/hooks.js.map +1 -1
  57. package/dist/hover-card.d.ts +15 -10
  58. package/dist/hover-card.js.map +1 -1
  59. package/dist/{icon-C0YAAaLZ.d.ts → icon-DKMJm20j.d.ts} +2 -2
  60. package/dist/{icon-button-Cl30yTfu.d.ts → icon-button-BnK4K7YK.d.ts} +3 -3
  61. package/dist/icon.d.ts +3 -3
  62. package/dist/icons.d.ts +3 -3
  63. package/dist/icons.js +1 -1
  64. package/dist/icons.js.map +1 -1
  65. package/dist/{in-view-DsiWfQpY.d.ts → in-view-Da08Bx6l.d.ts} +15 -4
  66. package/dist/{in-view-BXzPPdcl.js → in-view-pia_SVdE.js} +1 -1
  67. package/dist/{in-view-BXzPPdcl.js.map → in-view-pia_SVdE.js.map} +1 -1
  68. package/dist/{index-ddHz7L9f.d.ts → index-C91lxoX9.d.ts} +56 -13
  69. package/dist/{index-DU3SQJ46.d.ts → index-DOJUH34Z.d.ts} +4 -4
  70. package/dist/{index-B6SPk_xb.d.ts → index-DkMUaYsw.d.ts} +1 -1
  71. package/dist/{index-vOSpS5jv.d.ts → index-rtz7SwEq.d.ts} +1 -1
  72. package/dist/input.d.ts +2 -2
  73. package/dist/input.js +1 -1
  74. package/dist/input.js.map +1 -1
  75. package/dist/{is-input-Bh1rQhX3.js → is-input-CUEWaxtA.js} +1 -1
  76. package/dist/{is-input-Bh1rQhX3.js.map → is-input-CUEWaxtA.js.map} +1 -1
  77. package/dist/{kbd-B0wWeV_0.js → kbd-CAVUiqBT.js} +1 -1
  78. package/dist/kbd-CAVUiqBT.js.map +1 -0
  79. package/dist/kbd.d.ts +37 -8
  80. package/dist/kbd.js +1 -1
  81. package/dist/label.d.ts +40 -9
  82. package/dist/label.js.map +1 -1
  83. package/dist/media-object.d.ts +27 -11
  84. package/dist/media-object.js.map +1 -1
  85. package/dist/multi-select.d.ts +187 -36
  86. package/dist/multi-select.js +1 -1
  87. package/dist/multi-select.js.map +1 -1
  88. package/dist/otp-input.d.ts +167 -0
  89. package/dist/otp-input.js +2 -0
  90. package/dist/otp-input.js.map +1 -0
  91. package/dist/pagination.d.ts +3 -3
  92. package/dist/pagination.js +1 -1
  93. package/dist/pagination.js.map +1 -1
  94. package/dist/popover.d.ts +7 -5
  95. package/dist/popover.js.map +1 -1
  96. package/dist/primitive-tXm_8n_t.js.map +1 -1
  97. package/dist/{primitive-DXo0gUqw.d.ts → primitive-tyw4V7Vf.d.ts} +1 -1
  98. package/dist/progress.js.map +1 -1
  99. package/dist/radio-group.d.ts +1 -1
  100. package/dist/radio-group.js +1 -1
  101. package/dist/{resolve-pre-rendered-props-BXv6e6fc.js → resolve-pre-rendered-props-C-kiaLHj.js} +1 -1
  102. package/dist/{resolve-pre-rendered-props-BXv6e6fc.js.map → resolve-pre-rendered-props-C-kiaLHj.js.map} +1 -1
  103. package/dist/{resolve-pre-rendered-props-kcQrtWPt.d.ts → resolve-pre-rendered-props-CNUnH1fU.d.ts} +1 -1
  104. package/dist/sandboxed-on-click.d.ts +1 -1
  105. package/dist/{select-LJmfG--I.js → select-DOgdZO0Q.js} +2 -2
  106. package/dist/select-DOgdZO0Q.js.map +1 -0
  107. package/dist/{select-DNJli9JO.d.ts → select-DZutJxyr.d.ts} +11 -3
  108. package/dist/select.d.ts +1 -1
  109. package/dist/select.js +1 -1
  110. package/dist/{separator-DyOGgFCs.js → separator-DSOIrnhj.js} +1 -1
  111. package/dist/{separator-DyOGgFCs.js.map → separator-DSOIrnhj.js.map} +1 -1
  112. package/dist/separator.d.ts +1 -1
  113. package/dist/separator.js +1 -1
  114. package/dist/sheet.d.ts +7 -3
  115. package/dist/sheet.js.map +1 -1
  116. package/dist/skeleton.d.ts +32 -5
  117. package/dist/skeleton.js.map +1 -1
  118. package/dist/{sort-C_Jbs1dH.js → sort-DzCsa6Qj.js} +2 -2
  119. package/dist/{sort-C_Jbs1dH.js.map → sort-DzCsa6Qj.js.map} +1 -1
  120. package/dist/split-button.d.ts +3 -3
  121. package/dist/split-button.js +1 -1
  122. package/dist/{svg-only-BnnbLx6R.d.ts → svg-only-BtBvFy-N.d.ts} +2 -2
  123. package/dist/{table-4q1UxE7L.d.ts → table-BsNJBKiq.d.ts} +7 -3
  124. package/dist/{table-12T25gGa.js → table-Cl4nlRMR.js} +2 -2
  125. package/dist/{table-12T25gGa.js.map → table-Cl4nlRMR.js.map} +1 -1
  126. package/dist/table.d.ts +1 -1
  127. package/dist/table.js +1 -1
  128. package/dist/tabs.js +1 -1
  129. package/dist/text-area.d.ts +1 -1
  130. package/dist/text-area.js +1 -1
  131. package/dist/theme-provider-BFcnjeME.js.map +1 -1
  132. package/dist/theme.d.ts +2 -2
  133. package/dist/theme.js.map +1 -1
  134. package/dist/{themes-DXb8Tk74.d.ts → themes-DIEYkvNl.d.ts} +1 -1
  135. package/dist/toast.d.ts +3 -3
  136. package/dist/tooltip.d.ts +31 -14
  137. package/dist/tooltip.js.map +1 -1
  138. package/dist/{traffic-policy-file-ChsoQtXQ.js → traffic-policy-file-C6LHYrIU.js} +1 -1
  139. package/dist/{traffic-policy-file-ChsoQtXQ.js.map → traffic-policy-file-C6LHYrIU.js.map} +1 -1
  140. package/dist/{types-BeTbgoJd.d.ts → types-DG0WQLTL.d.ts} +1 -1
  141. package/dist/{types-DEYyl5LX.d.ts → types-DoV0R5Ja.d.ts} +1 -1
  142. package/dist/types.d.ts +5 -5
  143. package/dist/use-copy-to-clipboard-C7vsjJe-.js +2 -0
  144. package/dist/use-copy-to-clipboard-C7vsjJe-.js.map +1 -0
  145. package/dist/use-matches-media-query-CojcYxlA.js.map +1 -1
  146. package/dist/{use-prefers-reduced-motion-BcwST13S.js → use-prefers-reduced-motion-aXfsyo-k.js} +1 -1
  147. package/dist/use-prefers-reduced-motion-aXfsyo-k.js.map +1 -0
  148. package/dist/utils.d.ts +3 -3
  149. package/dist/utils.js +1 -1
  150. package/dist/utils.js.map +1 -1
  151. package/dist/{variant-props-DszdagRm.d.ts → variant-props-DUmSIQK8.d.ts} +2 -2
  152. package/dist/{with-style-props-Dlz3G1tS.d.ts → with-style-props-3iFrBR08.d.ts} +1 -1
  153. package/package.json +12 -7
  154. package/dist/compose-refs-DFIaEnQH.js +0 -2
  155. package/dist/compose-refs-DFIaEnQH.js.map +0 -1
  156. package/dist/dialog-MiS_Q-ge.js.map +0 -1
  157. package/dist/kbd-B0wWeV_0.js.map +0 -1
  158. package/dist/select-LJmfG--I.js.map +0 -1
  159. package/dist/use-copy-to-clipboard-Ds9MsSNU.js +0 -2
  160. package/dist/use-copy-to-clipboard-Ds9MsSNU.js.map +0 -1
  161. package/dist/use-prefers-reduced-motion-BcwST13S.js.map +0 -1
package/dist/input.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { a as WithInputType, i as WithAutoComplete, n as InputType, o as WithValidation, r as Validation, t as AutoComplete } from "./types-BeTbgoJd.js";
2
- import { a as InputCapture, i as Input, n as PasswordInput, o as InputCaptureProps, r as PasswordInputProps, s as InputProps, t as isInput } from "./index-ddHz7L9f.js";
1
+ import { a as WithInputType, i as WithAutoComplete, n as InputType, o as WithValidation, r as Validation, t as AutoComplete } from "./types-DG0WQLTL.js";
2
+ import { a as InputCapture, i as Input, n as PasswordInput, o as InputCaptureProps, r as PasswordInputProps, s as InputProps, t as isInput } from "./index-C91lxoX9.js";
3
3
  export { AutoComplete, Input, InputCapture, InputCaptureProps, InputProps, InputType, PasswordInput, PasswordInputProps, Validation, WithAutoComplete, WithInputType, WithValidation, isInput };
package/dist/input.js CHANGED
@@ -1,2 +1,2 @@
1
- import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-bWc5yC3-.js";import{t as n}from"./compose-refs-DFIaEnQH.js";import{t as r}from"./use-prefers-reduced-motion-BcwST13S.js";import{t as i}from"./is-input-Bh1rQhX3.js";import{createContext as a,forwardRef as o,useContext as s,useEffect as c,useRef as l,useState as u}from"react";import d from"clsx";import{jsx as f,jsxs as p}from"react/jsx-runtime";import{CheckCircleIcon as m}from"@phosphor-icons/react/CheckCircle";import{WarningIcon as h}from"@phosphor-icons/react/Warning";import{WarningDiamondIcon as g}from"@phosphor-icons/react/WarningDiamond";import{EyeIcon as _}from"@phosphor-icons/react/Eye";import{EyeClosedIcon as v}from"@phosphor-icons/react/EyeClosed";import{flushSync as y}from"react-dom";const b=o(({children:e,className:t,...n},r)=>{let i=!!e,a=l(null);return i?f(C,{className:t,forwardedRef:r,innerRef:a,...n,children:e}):f(C,{...n,className:t,forwardedRef:r,innerRef:a,children:f(x,{...n})})});b.displayName=`Input`;const x=o(({"aria-invalid":t,className:r,validation:i,...a},o)=>{let{"aria-invalid":c,forwardedRef:l,innerRef:u,validation:d,...p}=s(S),m=d??i,h=(typeof m==`function`?m():m)||void 0,g=c??t??m===`error`,_={...p,...a,type:a.type??p.type??`text`};return f(`input`,{"aria-invalid":g,"data-slot":`input-capture`,"data-validation":h,className:e(`placeholder:text-placeholder min-w-0 flex-1 bg-transparent text-left autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] focus:outline-hidden`,r),ref:n(o,l,u),..._})});x.displayName=`InputCapture`;const S=a({validation:void 0,innerRef:{current:null}}),C=({"aria-invalid":t,"aria-disabled":n,"data-slot":r=`input`,children:i,className:a,disabled:o,forwardedRef:s,innerRef:c,style:l,type:u,validation:d,...m})=>{let h=t!=null&&t!==`false`?`error`:typeof d==`function`?d():d;return f(S.Provider,{value:{"aria-invalid":t,"aria-disabled":n,disabled:o,type:u,validation:h,...m,forwardedRef:s,innerRef:c},children:p(`div`,{role:`none`,"data-slot":r,"data-disabled":(o??n)||void 0,"data-validation":h||void 0,className:e(`pointer-coarse:text-base h-9 text-sm`,`bg-form relative flex w-full items-center gap-1.5 rounded-md border px-3 py-2 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-within:outline-hidden focus-within:ring-4`,`data-disabled:opacity-50`,`has-[input:not(:first-child)]:ps-2.5 has-[input:not(:last-child)]:pe-2.5 [&>:not(input)]:shrink-0 [&_svg]:size-5`,`border-form text-strong focus-within:border-accent-600 focus-within:ring-focus-accent`,`data-validation-success:border-success-600 focus-within:data-validation-success:border-success-600 focus-within:data-validation-success:ring-focus-success`,`data-validation-warning:border-warning-600 focus-within:data-validation-warning:border-warning-600 focus-within:data-validation-warning:ring-focus-warning`,`data-validation-error:border-danger-600 focus-within:data-validation-error:border-danger-600 focus-within:data-validation-error:ring-focus-danger`,`autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] has-autofill:bg-blue-50 has-autofill:[-webkit-text-fill-color:var(--text-color-strong)]`,a),onMouseDown:e=>{e.target!==c?.current&&e.preventDefault()},onClick:()=>{c?.current?.focus()},onKeyDown:()=>{c?.current!==document.activeElement&&c?.current?.focus()},style:l,children:[i,f(w,{name:m.name,validation:h})]})})};C.displayName=`InputContainer`;const w=({name:e,validation:n})=>{switch(n){case`error`:return p(`div`,{className:`text-danger-600 order-last select-none`,children:[f(`span`,{className:`sr-only`,children:d(`The value entered for the`,e,`input has failed validation.`)}),f(t,{svg:f(h,{"aria-hidden":!0,weight:`fill`})})]});case`success`:return f(`div`,{className:`text-success-600 order-last select-none`,children:f(t,{svg:f(m,{weight:`fill`})})});case`warning`:return f(`div`,{className:`text-warning-600 order-last select-none`,children:f(t,{svg:f(g,{weight:`fill`})})});default:return null}};w.displayName=`ValidationFeedback`;const T=o(({onValueVisibilityChange:e,showValue:n=!1,...i},a)=>{let[o,s]=u(n),d=o?`text`:`password`,m=o?_:v,h=l(null),g=l(null);return c(()=>{s(n)},[n]),p(b,{"data-slot":`password-input`,type:d,ref:a,...i,children:[f(x,{}),p(`button`,{type:`button`,tabIndex:-1,className:`text-body hover:text-strong ml-1 cursor-pointer bg-inherit p-0`,onClick:()=>{g.current&&=(g.current.cancel(),null);let t=!o;y(()=>{s(t)}),e?.(t);let n=h.current;n&&!r()&&(g.current=n.animate([{transform:`scaleY(0)`},{transform:`scaleY(1)`}],{duration:200,easing:`ease-out`}),g.current.onfinish=()=>{g.current=null})},children:[p(`span`,{className:`sr-only`,children:[`Turn password visibility `,o?`off`:`on`]}),f(t,{ref:h,svg:f(m,{"aria-hidden":!0})})]})]})});T.displayName=`PasswordInput`;export{b as Input,x as InputCapture,T as PasswordInput,i as isInput};
1
+ import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-bWc5yC3-.js";import{t as n}from"./compose-refs-DZ3cPi47.js";import{t as r}from"./use-prefers-reduced-motion-aXfsyo-k.js";import{t as i}from"./is-input-CUEWaxtA.js";import{createContext as a,forwardRef as o,useContext as s,useEffect as c,useRef as l,useState as u}from"react";import d from"clsx";import{jsx as f,jsxs as p}from"react/jsx-runtime";import{CheckCircleIcon as m}from"@phosphor-icons/react/CheckCircle";import{WarningIcon as h}from"@phosphor-icons/react/Warning";import{WarningDiamondIcon as g}from"@phosphor-icons/react/WarningDiamond";import{EyeIcon as _}from"@phosphor-icons/react/Eye";import{EyeClosedIcon as v}from"@phosphor-icons/react/EyeClosed";import{flushSync as y}from"react-dom";const b=o(({children:e,className:t,...n},r)=>{let i=!!e,a=l(null);return i?f(C,{className:t,forwardedRef:r,innerRef:a,...n,children:e}):f(C,{...n,className:t,forwardedRef:r,innerRef:a,children:f(x,{...n})})});b.displayName=`Input`;const x=o(({"aria-invalid":t,className:r,validation:i,...a},o)=>{let{"aria-invalid":c,forwardedRef:l,innerRef:u,validation:d,...p}=s(S),m=d??i,h=(typeof m==`function`?m():m)||void 0,g=c??t??m===`error`,_={...p,...a,type:a.type??p.type??`text`};return f(`input`,{"aria-invalid":g,"data-slot":`input-capture`,"data-validation":h,className:e(`placeholder:text-placeholder min-w-0 flex-1 bg-transparent text-left autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] focus:outline-hidden`,r),ref:n(o,l,u),..._})});x.displayName=`InputCapture`;const S=a({validation:void 0,innerRef:{current:null}}),C=({"aria-invalid":t,"aria-disabled":n,"data-slot":r=`input`,children:i,className:a,disabled:o,forwardedRef:s,innerRef:c,style:l,type:u,validation:d,...m})=>{let h=t!=null&&t!==`false`?`error`:typeof d==`function`?d():d;return f(S.Provider,{value:{"aria-invalid":t,"aria-disabled":n,disabled:o,type:u,validation:h,...m,forwardedRef:s,innerRef:c},children:p(`div`,{role:`none`,"data-slot":r,"data-disabled":(o??n)||void 0,"data-validation":h||void 0,className:e(`pointer-coarse:text-base h-9 text-sm`,`bg-form relative flex w-full items-center gap-1.5 rounded-md border px-3 py-2 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-within:outline-hidden focus-within:ring-4`,`data-disabled:opacity-50`,`has-[input:not(:first-child)]:ps-2.5 has-[input:not(:last-child)]:pe-2.5 [&>:not(input)]:shrink-0 [&_svg]:size-5`,`border-form text-strong focus-within:border-accent-600 focus-within:ring-focus-accent`,`data-validation-success:border-success-600 focus-within:data-validation-success:border-success-600 focus-within:data-validation-success:ring-focus-success`,`data-validation-warning:border-warning-600 focus-within:data-validation-warning:border-warning-600 focus-within:data-validation-warning:ring-focus-warning`,`data-validation-error:border-danger-600 focus-within:data-validation-error:border-danger-600 focus-within:data-validation-error:ring-focus-danger`,`autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] has-autofill:bg-blue-50 has-autofill:[-webkit-text-fill-color:var(--text-color-strong)]`,a),onMouseDown:e=>{e.target!==c?.current&&e.preventDefault()},onClick:()=>{c?.current?.focus()},onKeyDown:()=>{c?.current!==document.activeElement&&c?.current?.focus()},style:l,children:[i,f(w,{name:m.name,validation:h})]})})};C.displayName=`InputContainer`;const w=({name:e,validation:n})=>{switch(n){case`error`:return p(`div`,{className:`text-danger-600 order-last select-none`,children:[f(`span`,{className:`sr-only`,children:d(`The value entered for the`,e,`input has failed validation.`)}),f(t,{svg:f(h,{"aria-hidden":!0,weight:`fill`})})]});case`success`:return f(`div`,{className:`text-success-600 order-last select-none`,children:f(t,{svg:f(m,{weight:`fill`})})});case`warning`:return f(`div`,{className:`text-warning-600 order-last select-none`,children:f(t,{svg:f(g,{weight:`fill`})})});default:return null}};w.displayName=`ValidationFeedback`;const T=o(({onValueVisibilityChange:e,showValue:n=!1,...i},a)=>{let[o,s]=u(n),d=o?`text`:`password`,m=o?_:v,h=l(null),g=l(null);return c(()=>{s(n)},[n]),p(b,{"data-slot":`password-input`,type:d,ref:a,...i,children:[f(x,{}),p(`button`,{type:`button`,tabIndex:-1,className:`text-body hover:text-strong ml-1 cursor-pointer bg-inherit p-0`,onClick:()=>{g.current&&=(g.current.cancel(),null);let t=!o;y(()=>{s(t)}),e?.(t);let n=h.current;n&&!r()&&(g.current=n.animate([{transform:`scaleY(0)`},{transform:`scaleY(1)`}],{duration:200,easing:`ease-out`}),g.current.onfinish=()=>{g.current=null})},children:[p(`span`,{className:`sr-only`,children:[`Turn password visibility `,o?`off`:`on`]}),f(t,{ref:h,svg:f(m,{"aria-hidden":!0})})]})]})});T.displayName=`PasswordInput`;export{b as Input,x as InputCapture,T as PasswordInput,i as isInput};
2
2
  //# sourceMappingURL=input.js.map
package/dist/input.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"input.js","names":["clsx"],"sources":["../src/components/input/input.tsx","../src/components/input/password-input.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckCircleIcon } from \"@phosphor-icons/react/CheckCircle\";\nimport { WarningIcon } from \"@phosphor-icons/react/Warning\";\nimport { WarningDiamondIcon } from \"@phosphor-icons/react/WarningDiamond\";\nimport clsx from \"clsx\";\nimport type {\n\tComponentRef,\n\tForwardedRef,\n\tInputHTMLAttributes,\n\tMutableRefObject,\n\tPropsWithChildren,\n} from \"react\";\nimport { createContext, forwardRef, useContext, useRef } from \"react\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport type { Validation, WithAutoComplete, WithInputType, WithValidation } from \"./types.js\";\n\ntype BaseProps = WithAutoComplete & WithInputType & WithValidation;\n\n/**\n * The props for the `Input` component.\n */\ntype InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps &\n\tPropsWithChildren;\n\n/**\n * Used to create interactive controls for web-based forms in order to accept data from the user.\n * A versatile input element that supports various types, validation states, and can be composed with other elements.\n *\n * @see https://mantle.ngrok.com/components/input\n *\n * @example\n * ```tsx\n * <Input\n * type=\"email\"\n * placeholder=\"Enter your email\"\n * validation=\"success\"\n * />\n * ```\n */\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n\t({ children, className, ...props }, forwardedRef) => {\n\t\tconst hasChildren = Boolean(children);\n\t\tconst innerRef = useRef<ComponentRef<\"input\">>(null);\n\n\t\tif (hasChildren) {\n\t\t\treturn (\n\t\t\t\t<InputContainer\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tforwardedRef={forwardedRef}\n\t\t\t\t\tinnerRef={innerRef}\n\t\t\t\t\t{...props}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</InputContainer>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<InputContainer\n\t\t\t\t{...props}\n\t\t\t\tclassName={className}\n\t\t\t\tforwardedRef={forwardedRef}\n\t\t\t\tinnerRef={innerRef}\n\t\t\t>\n\t\t\t\t<InputCapture {...props} />\n\t\t\t</InputContainer>\n\t\t);\n\t},\n);\nInput.displayName = \"Input\";\n\ntype InputCaptureProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps;\n\n/**\n * The actual <input /> element that captures user input.\n * Used internally by Input component or when you need direct control over the input element.\n *\n * @see https://mantle.ngrok.com/components/input\n *\n * @example\n * ```tsx\n * <Input>\n * <InputCapture />\n * <Icon svg={<SearchIcon />} />\n * </Input>\n * ```\n */\nconst InputCapture = forwardRef<HTMLInputElement, InputCaptureProps>(\n\t({ \"aria-invalid\": _ariaInvalid, className, validation: _validation, ...restProps }, ref) => {\n\t\tconst {\n\t\t\t\"aria-invalid\": ctxAriaInvalid,\n\t\t\tforwardedRef: ctxForwardedRef,\n\t\t\tinnerRef: ctxInnerRef,\n\t\t\tvalidation: ctxValidation,\n\t\t\t...ctx\n\t\t} = useContext(InputContext);\n\n\t\tconst validation = ctxValidation ?? _validation;\n\t\tconst validationValue =\n\t\t\t(typeof validation === \"function\" ? validation() : validation) || undefined;\n\t\tconst ariaInvalid = ctxAriaInvalid ?? _ariaInvalid ?? validation === \"error\";\n\t\tconst props = {\n\t\t\t...ctx,\n\t\t\t...restProps,\n\t\t\ttype: restProps.type ?? ctx.type ?? \"text\",\n\t\t};\n\n\t\treturn (\n\t\t\t<input\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tdata-slot=\"input-capture\"\n\t\t\t\tdata-validation={validationValue}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"placeholder:text-placeholder min-w-0 flex-1 bg-transparent text-left autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] focus:outline-hidden\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={composeRefs(ref, ctxForwardedRef, ctxInnerRef)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nInputCapture.displayName = \"InputCapture\";\n\ntype InputContextType = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps & {\n\t\t/**\n\t\t * inner ref for the input element, controlled by `Input`\n\t\t */\n\t\tinnerRef: MutableRefObject<HTMLInputElement | null>;\n\t\t/**\n\t\t * forwarded ref to the input element, forwarded from `Input` to `InputCapture`\n\t\t */\n\t\tforwardedRef?: ForwardedRef<HTMLInputElement>;\n\t};\n\nconst InputContext = createContext<InputContextType>({\n\tvalidation: undefined,\n\tinnerRef: { current: null },\n});\n\ntype InputContainerProps = InputHTMLAttributes<HTMLInputElement> &\n\tBaseProps & {\n\t\t/**\n\t\t * @private inner ref for the input element, controlled by `Input`\n\t\t */\n\t\tinnerRef: MutableRefObject<HTMLInputElement | null>;\n\t\t/**\n\t\t * @private ref to the input element, forwarded from `Input` to `InputCapture`\n\t\t */\n\t\tforwardedRef: ForwardedRef<HTMLInputElement>;\n\t};\n\n/**\n * The container for the input element.\n */\nconst InputContainer = ({\n\t\"aria-invalid\": _ariaInvalid,\n\t\"aria-disabled\": _ariaDisabled,\n\t\"data-slot\": dataSlot = \"input\",\n\tchildren,\n\tclassName,\n\tdisabled,\n\tforwardedRef,\n\tinnerRef,\n\tstyle,\n\ttype,\n\tvalidation: _validation,\n\t...props\n}: InputContainerProps & { \"data-slot\"?: string }) => {\n\tconst isInvalid = _ariaInvalid != null && _ariaInvalid !== \"false\";\n\tconst validation = isInvalid\n\t\t? \"error\"\n\t\t: typeof _validation === \"function\"\n\t\t\t? _validation()\n\t\t\t: _validation;\n\treturn (\n\t\t<InputContext.Provider\n\t\t\tvalue={{\n\t\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\t\t\"aria-disabled\": _ariaDisabled,\n\t\t\t\tdisabled,\n\t\t\t\ttype,\n\t\t\t\tvalidation,\n\t\t\t\t...props,\n\t\t\t\tforwardedRef,\n\t\t\t\tinnerRef,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\trole=\"none\"\n\t\t\t\tdata-slot={dataSlot}\n\t\t\t\tdata-disabled={(disabled ?? _ariaDisabled) || undefined}\n\t\t\t\tdata-validation={validation || undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"pointer-coarse:text-base h-9 text-sm\",\n\t\t\t\t\t\"bg-form relative flex w-full items-center gap-1.5 rounded-md border px-3 py-2 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-within:outline-hidden focus-within:ring-4\",\n\t\t\t\t\t\"data-disabled:opacity-50\",\n\t\t\t\t\t\"has-[input:not(:first-child)]:ps-2.5 has-[input:not(:last-child)]:pe-2.5 [&>:not(input)]:shrink-0 [&_svg]:size-5\",\n\t\t\t\t\t\"border-form text-strong focus-within:border-accent-600 focus-within:ring-focus-accent\",\n\t\t\t\t\t\"data-validation-success:border-success-600 focus-within:data-validation-success:border-success-600 focus-within:data-validation-success:ring-focus-success\",\n\t\t\t\t\t\"data-validation-warning:border-warning-600 focus-within:data-validation-warning:border-warning-600 focus-within:data-validation-warning:ring-focus-warning\",\n\t\t\t\t\t\"data-validation-error:border-danger-600 focus-within:data-validation-error:border-danger-600 focus-within:data-validation-error:ring-focus-danger\",\n\t\t\t\t\t\"autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] has-autofill:bg-blue-50 has-autofill:[-webkit-text-fill-color:var(--text-color-strong)]\", // Autofill styling on the input itself and any children with autofill styling\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonMouseDown={(event) => {\n\t\t\t\t\t// Prevent mousedown on non-input children (icons, buttons, etc.) from\n\t\t\t\t\t// blurring the input, which would cause the focus ring to flicker.\n\t\t\t\t\tif (event.target !== innerRef?.current) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tinnerRef?.current?.focus();\n\t\t\t\t}}\n\t\t\t\tonKeyDown={() => {\n\t\t\t\t\tif (innerRef?.current !== document.activeElement) {\n\t\t\t\t\t\tinnerRef?.current?.focus();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<ValidationFeedback name={props.name} validation={validation} />\n\t\t\t</div>\n\t\t</InputContext.Provider>\n\t);\n};\nInputContainer.displayName = \"InputContainer\";\n\nexport { Input, InputCapture };\nexport type { InputProps, InputCaptureProps };\n\nconst ValidationFeedback = ({\n\tname,\n\tvalidation,\n}: {\n\tname?: string;\n\tvalidation: Validation | undefined;\n}) => {\n\tswitch (validation) {\n\t\tcase \"error\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-danger-600 order-last select-none\">\n\t\t\t\t\t<span className=\"sr-only\">\n\t\t\t\t\t\t{clsx(\"The value entered for the\", name, \"input has failed validation.\")}\n\t\t\t\t\t</span>\n\t\t\t\t\t<Icon svg={<WarningIcon aria-hidden weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tcase \"success\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-success-600 order-last select-none\">\n\t\t\t\t\t<Icon svg={<CheckCircleIcon weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tcase \"warning\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-warning-600 order-last select-none\">\n\t\t\t\t\t<Icon svg={<WarningDiamondIcon weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\nValidationFeedback.displayName = \"ValidationFeedback\";\n","\"use client\";\n\nimport { EyeIcon } from \"@phosphor-icons/react/Eye\";\nimport { EyeClosedIcon } from \"@phosphor-icons/react/EyeClosed\";\nimport { forwardRef, useEffect, useRef, useState } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { getPrefersReducedMotion } from \"../../hooks/use-prefers-reduced-motion.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport { Input, InputCapture } from \"./input.js\";\nimport type { InputType, WithAutoComplete, WithValidation } from \"./types.js\";\n\ntype PasswordInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tWithValidation &\n\tWithAutoComplete & {\n\t\t/**\n\t\t * Callback for when the visibility of the password value changes.\n\t\t */\n\t\tonValueVisibilityChange?: (visible: boolean) => void;\n\t\t/**\n\t\t * Show/hide the password value as a controlled state.\n\t\t * @default false\n\t\t */\n\t\tshowValue?: boolean;\n\t};\n\ntype PasswordInputType = Extract<InputType, \"text\" | \"password\">;\n\n/**\n * A specialized input component for password entry with a toggle button to show/hide the password value.\n * Provides enhanced security UX by allowing users to verify their input while maintaining privacy.\n *\n * @see https://mantle.ngrok.com/components/input\n *\n * @example\n * ```tsx\n * <PasswordInput\n * placeholder=\"Enter your password\"\n * showValue={false}\n * onValueVisibilityChange={(visible) => console.log('Password visible:', visible)}\n * />\n * ```\n */\nconst PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n\t({ onValueVisibilityChange, showValue = false, ...props }, ref) => {\n\t\tconst [showPassword, setShowPassword] = useState<boolean>(showValue);\n\t\tconst type: PasswordInputType = showPassword ? \"text\" : \"password\";\n\t\tconst EyeCon = showPassword ? EyeIcon : EyeClosedIcon;\n\t\tconst iconRef = useRef<SVGSVGElement>(null);\n\t\tconst animationRef = useRef<Animation | null>(null);\n\n\t\tuseEffect(() => {\n\t\t\tsetShowPassword(showValue);\n\t\t}, [showValue]);\n\n\t\treturn (\n\t\t\t<Input data-slot=\"password-input\" type={type} ref={ref} {...props}>\n\t\t\t\t<InputCapture />\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\tclassName=\"text-body hover:text-strong ml-1 cursor-pointer bg-inherit p-0\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t// Cancel any in-flight animation so rapid clicks are never blocked\n\t\t\t\t\t\tif (animationRef.current) {\n\t\t\t\t\t\t\tanimationRef.current.cancel();\n\t\t\t\t\t\t\tanimationRef.current = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Flush synchronously so React commits the new icon to the DOM before we animate\n\t\t\t\t\t\tconst nextShowPassword = !showPassword;\n\t\t\t\t\t\tflushSync(() => {\n\t\t\t\t\t\t\tsetShowPassword(nextShowPassword);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tonValueVisibilityChange?.(nextShowPassword);\n\n\t\t\t\t\t\tconst icon = iconRef.current;\n\t\t\t\t\t\tif (icon && !getPrefersReducedMotion()) {\n\t\t\t\t\t\t\tanimationRef.current = icon.animate(\n\t\t\t\t\t\t\t\t[{ transform: \"scaleY(0)\" }, { transform: \"scaleY(1)\" }],\n\t\t\t\t\t\t\t\t{ duration: 200, easing: \"ease-out\" },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tanimationRef.current.onfinish = () => {\n\t\t\t\t\t\t\t\tanimationRef.current = null;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"sr-only\">Turn password visibility {showPassword ? \"off\" : \"on\"}</span>\n\t\t\t\t\t<Icon ref={iconRef} svg={<EyeCon aria-hidden />} />\n\t\t\t\t</button>\n\t\t\t</Input>\n\t\t);\n\t},\n);\nPasswordInput.displayName = \"PasswordInput\";\n\nexport { PasswordInput };\nexport type { PasswordInputProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"input.js","names":["clsx"],"sources":["../src/components/input/input.tsx","../src/components/input/password-input.tsx"],"sourcesContent":["\"use client\";\n\nimport { CheckCircleIcon } from \"@phosphor-icons/react/CheckCircle\";\nimport { WarningIcon } from \"@phosphor-icons/react/Warning\";\nimport { WarningDiamondIcon } from \"@phosphor-icons/react/WarningDiamond\";\nimport clsx from \"clsx\";\nimport type {\n\tComponentRef,\n\tForwardedRef,\n\tInputHTMLAttributes,\n\tMutableRefObject,\n\tPropsWithChildren,\n} from \"react\";\nimport { createContext, forwardRef, useContext, useRef } from \"react\";\nimport { composeRefs } from \"../../utils/compose-refs/compose-refs.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport type { Validation, WithAutoComplete, WithInputType, WithValidation } from \"./types.js\";\n\ntype BaseProps = WithAutoComplete & WithInputType & WithValidation;\n\n/**\n * The props for the `Input` component.\n */\ntype InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps &\n\tPropsWithChildren;\n\n/**\n * Used to create interactive controls for web-based forms in order to accept data from the user.\n * A versatile input element that supports various types, validation states, and can be composed with other elements.\n *\n * @see https://mantle.ngrok.com/components/input\n *\n * @example\n * ```tsx\n * <Input\n * type=\"email\"\n * placeholder=\"Enter your email\"\n * validation=\"success\"\n * />\n * ```\n */\nconst Input = forwardRef<HTMLInputElement, InputProps>(\n\t({ children, className, ...props }, forwardedRef) => {\n\t\tconst hasChildren = Boolean(children);\n\t\tconst innerRef = useRef<ComponentRef<\"input\">>(null);\n\n\t\tif (hasChildren) {\n\t\t\treturn (\n\t\t\t\t<InputContainer\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tforwardedRef={forwardedRef}\n\t\t\t\t\tinnerRef={innerRef}\n\t\t\t\t\t{...props}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</InputContainer>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<InputContainer\n\t\t\t\t{...props}\n\t\t\t\tclassName={className}\n\t\t\t\tforwardedRef={forwardedRef}\n\t\t\t\tinnerRef={innerRef}\n\t\t\t>\n\t\t\t\t<InputCapture {...props} />\n\t\t\t</InputContainer>\n\t\t);\n\t},\n);\nInput.displayName = \"Input\";\n\ntype InputCaptureProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps;\n\n/**\n * The actual <input /> element that captures user input.\n * Used internally by Input component or when you need direct control over the input element.\n *\n * @see https://mantle.ngrok.com/components/input\n *\n * @example\n * ```tsx\n * <Input>\n * <InputCapture />\n * <Icon svg={<SearchIcon />} />\n * </Input>\n * ```\n */\nconst InputCapture = forwardRef<HTMLInputElement, InputCaptureProps>(\n\t({ \"aria-invalid\": _ariaInvalid, className, validation: _validation, ...restProps }, ref) => {\n\t\tconst {\n\t\t\t\"aria-invalid\": ctxAriaInvalid,\n\t\t\tforwardedRef: ctxForwardedRef,\n\t\t\tinnerRef: ctxInnerRef,\n\t\t\tvalidation: ctxValidation,\n\t\t\t...ctx\n\t\t} = useContext(InputContext);\n\n\t\tconst validation = ctxValidation ?? _validation;\n\t\tconst validationValue =\n\t\t\t(typeof validation === \"function\" ? validation() : validation) || undefined;\n\t\tconst ariaInvalid = ctxAriaInvalid ?? _ariaInvalid ?? validation === \"error\";\n\t\tconst props = {\n\t\t\t...ctx,\n\t\t\t...restProps,\n\t\t\ttype: restProps.type ?? ctx.type ?? \"text\",\n\t\t};\n\n\t\treturn (\n\t\t\t<input\n\t\t\t\taria-invalid={ariaInvalid}\n\t\t\t\tdata-slot=\"input-capture\"\n\t\t\t\tdata-validation={validationValue}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"placeholder:text-placeholder min-w-0 flex-1 bg-transparent text-left autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] focus:outline-hidden\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tref={composeRefs(ref, ctxForwardedRef, ctxInnerRef)}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t);\n\t},\n);\nInputCapture.displayName = \"InputCapture\";\n\ntype InputContextType = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tBaseProps & {\n\t\t/**\n\t\t * inner ref for the input element, controlled by `Input`\n\t\t */\n\t\tinnerRef: MutableRefObject<HTMLInputElement | null>;\n\t\t/**\n\t\t * forwarded ref to the input element, forwarded from `Input` to `InputCapture`\n\t\t */\n\t\tforwardedRef?: ForwardedRef<HTMLInputElement>;\n\t};\n\nconst InputContext = createContext<InputContextType>({\n\tvalidation: undefined,\n\tinnerRef: { current: null },\n});\n\ntype InputContainerProps = InputHTMLAttributes<HTMLInputElement> &\n\tBaseProps & {\n\t\t/**\n\t\t * @private inner ref for the input element, controlled by `Input`\n\t\t */\n\t\tinnerRef: MutableRefObject<HTMLInputElement | null>;\n\t\t/**\n\t\t * @private ref to the input element, forwarded from `Input` to `InputCapture`\n\t\t */\n\t\tforwardedRef: ForwardedRef<HTMLInputElement>;\n\t};\n\n/**\n * The container for the input element.\n */\nconst InputContainer = ({\n\t\"aria-invalid\": _ariaInvalid,\n\t\"aria-disabled\": _ariaDisabled,\n\t\"data-slot\": dataSlot = \"input\",\n\tchildren,\n\tclassName,\n\tdisabled,\n\tforwardedRef,\n\tinnerRef,\n\tstyle,\n\ttype,\n\tvalidation: _validation,\n\t...props\n}: InputContainerProps & { \"data-slot\"?: string }) => {\n\tconst isInvalid = _ariaInvalid != null && _ariaInvalid !== \"false\";\n\tconst validation = isInvalid\n\t\t? \"error\"\n\t\t: typeof _validation === \"function\"\n\t\t\t? _validation()\n\t\t\t: _validation;\n\treturn (\n\t\t<InputContext.Provider\n\t\t\tvalue={{\n\t\t\t\t\"aria-invalid\": _ariaInvalid,\n\t\t\t\t\"aria-disabled\": _ariaDisabled,\n\t\t\t\tdisabled,\n\t\t\t\ttype,\n\t\t\t\tvalidation,\n\t\t\t\t...props,\n\t\t\t\tforwardedRef,\n\t\t\t\tinnerRef,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\trole=\"none\"\n\t\t\t\tdata-slot={dataSlot}\n\t\t\t\tdata-disabled={(disabled ?? _ariaDisabled) || undefined}\n\t\t\t\tdata-validation={validation || undefined}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"pointer-coarse:text-base h-9 text-sm\",\n\t\t\t\t\t\"bg-form relative flex w-full items-center gap-1.5 rounded-md border px-3 py-2 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-within:outline-hidden focus-within:ring-4\",\n\t\t\t\t\t\"data-disabled:opacity-50\",\n\t\t\t\t\t\"has-[input:not(:first-child)]:ps-2.5 has-[input:not(:last-child)]:pe-2.5 [&>:not(input)]:shrink-0 [&_svg]:size-5\",\n\t\t\t\t\t\"border-form text-strong focus-within:border-accent-600 focus-within:ring-focus-accent\",\n\t\t\t\t\t\"data-validation-success:border-success-600 focus-within:data-validation-success:border-success-600 focus-within:data-validation-success:ring-focus-success\",\n\t\t\t\t\t\"data-validation-warning:border-warning-600 focus-within:data-validation-warning:border-warning-600 focus-within:data-validation-warning:ring-focus-warning\",\n\t\t\t\t\t\"data-validation-error:border-danger-600 focus-within:data-validation-error:border-danger-600 focus-within:data-validation-error:ring-focus-danger\",\n\t\t\t\t\t\"autofill:shadow-[inset_0_0_0px_1000px_var(--color-blue-50)] has-autofill:bg-blue-50 has-autofill:[-webkit-text-fill-color:var(--text-color-strong)]\", // Autofill styling on the input itself and any children with autofill styling\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonMouseDown={(event) => {\n\t\t\t\t\t// Prevent mousedown on non-input children (icons, buttons, etc.) from\n\t\t\t\t\t// blurring the input, which would cause the focus ring to flicker.\n\t\t\t\t\tif (event.target !== innerRef?.current) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tonClick={() => {\n\t\t\t\t\tinnerRef?.current?.focus();\n\t\t\t\t}}\n\t\t\t\tonKeyDown={() => {\n\t\t\t\t\tif (innerRef?.current !== document.activeElement) {\n\t\t\t\t\t\tinnerRef?.current?.focus();\n\t\t\t\t\t}\n\t\t\t\t}}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t<ValidationFeedback name={props.name} validation={validation} />\n\t\t\t</div>\n\t\t</InputContext.Provider>\n\t);\n};\nInputContainer.displayName = \"InputContainer\";\n\nexport { Input, InputCapture };\nexport type { InputProps, InputCaptureProps };\n\nconst ValidationFeedback = ({\n\tname,\n\tvalidation,\n}: {\n\tname?: string;\n\tvalidation: Validation | undefined;\n}) => {\n\tswitch (validation) {\n\t\tcase \"error\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-danger-600 order-last select-none\">\n\t\t\t\t\t<span className=\"sr-only\">\n\t\t\t\t\t\t{clsx(\"The value entered for the\", name, \"input has failed validation.\")}\n\t\t\t\t\t</span>\n\t\t\t\t\t<Icon svg={<WarningIcon aria-hidden weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tcase \"success\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-success-600 order-last select-none\">\n\t\t\t\t\t<Icon svg={<CheckCircleIcon weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tcase \"warning\":\n\t\t\treturn (\n\t\t\t\t<div className=\"text-warning-600 order-last select-none\">\n\t\t\t\t\t<Icon svg={<WarningDiamondIcon weight=\"fill\" />} />\n\t\t\t\t</div>\n\t\t\t);\n\t\tdefault:\n\t\t\treturn null;\n\t}\n};\nValidationFeedback.displayName = \"ValidationFeedback\";\n","\"use client\";\n\nimport { EyeIcon } from \"@phosphor-icons/react/Eye\";\nimport { EyeClosedIcon } from \"@phosphor-icons/react/EyeClosed\";\nimport { forwardRef, useEffect, useRef, useState } from \"react\";\nimport type { InputHTMLAttributes } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { getPrefersReducedMotion } from \"../../hooks/use-prefers-reduced-motion.js\";\nimport { Icon } from \"../icon/icon.js\";\nimport { Input, InputCapture } from \"./input.js\";\nimport type { InputType, WithAutoComplete, WithValidation } from \"./types.js\";\n\ntype PasswordInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, \"autoComplete\" | \"type\"> &\n\tWithValidation &\n\tWithAutoComplete & {\n\t\t/**\n\t\t * Callback for when the visibility of the password value changes.\n\t\t */\n\t\tonValueVisibilityChange?: (visible: boolean) => void;\n\t\t/**\n\t\t * Show/hide the password value as a controlled state.\n\t\t * @default false\n\t\t */\n\t\tshowValue?: boolean;\n\t};\n\ntype PasswordInputType = Extract<InputType, \"text\" | \"password\">;\n\n/**\n * An input optimized for password and other sensitive-value entry. Renders a\n * native `<input type=\"password\">` with a built-in trailing button that\n * toggles between hidden (`••••`) and revealed (`text`) display.\n *\n * **When to use**\n * - Password fields on login, signup, and reset flows.\n * - One-time tokens, recovery codes, or secrets the user needs to type\n * accurately and may want to verify visually before submitting.\n *\n * **When not to use**\n * - For values that are never sensitive — use a plain {@link https://mantle.ngrok.com/components/input Input}.\n * - For controls where the toggle would be confusing (e.g. masked input\n * formatting like phone numbers).\n *\n * **Visibility state.** The toggle is uncontrolled by default. Pass\n * `showValue` to control the visibility from the outside (useful when one\n * UI control toggles multiple password fields), and `onValueVisibilityChange`\n * to be notified when the user toggles via the built-in button.\n *\n * **Accessibility.** Always pair with a {@link https://mantle.ngrok.com/components/label Label}.\n * The toggle button has its own accessible name announcing the current\n * state. The input keeps `autocomplete=\"current-password\"` /\n * `\"new-password\"` semantics — set `autoComplete` explicitly per flow.\n *\n * **Browser password managers.** When revealed, the input switches to\n * `type=\"text\"` — some password managers may pause autofill in this state,\n * which is the intended security tradeoff.\n *\n * @see https://mantle.ngrok.com/components/password-input\n *\n * @example\n * ```tsx\n * import { PasswordInput } from \"@ngrok/mantle/input\";\n * import { Label } from \"@ngrok/mantle/label\";\n * import { useState } from \"react\";\n *\n * // Basic — uncontrolled visibility.\n * <Label className=\"grid gap-1\">\n * <span>Password</span>\n * <PasswordInput name=\"password\" autoComplete=\"current-password\" />\n * </Label>\n *\n * // Validation state.\n * <PasswordInput validation=\"error\" />\n *\n * // Controlled visibility — one toggle reveals multiple fields.\n * function PasswordPair() {\n * const [show, setShow] = useState(false);\n * return (\n * <>\n * <PasswordInput showValue={show} onValueVisibilityChange={setShow} />\n * <PasswordInput showValue={show} onValueVisibilityChange={setShow} />\n * </>\n * );\n * }\n * ```\n */\nconst PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n\t({ onValueVisibilityChange, showValue = false, ...props }, ref) => {\n\t\tconst [showPassword, setShowPassword] = useState<boolean>(showValue);\n\t\tconst type: PasswordInputType = showPassword ? \"text\" : \"password\";\n\t\tconst EyeCon = showPassword ? EyeIcon : EyeClosedIcon;\n\t\tconst iconRef = useRef<SVGSVGElement>(null);\n\t\tconst animationRef = useRef<Animation | null>(null);\n\n\t\tuseEffect(() => {\n\t\t\tsetShowPassword(showValue);\n\t\t}, [showValue]);\n\n\t\treturn (\n\t\t\t<Input data-slot=\"password-input\" type={type} ref={ref} {...props}>\n\t\t\t\t<InputCapture />\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\tclassName=\"text-body hover:text-strong ml-1 cursor-pointer bg-inherit p-0\"\n\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t// Cancel any in-flight animation so rapid clicks are never blocked\n\t\t\t\t\t\tif (animationRef.current) {\n\t\t\t\t\t\t\tanimationRef.current.cancel();\n\t\t\t\t\t\t\tanimationRef.current = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Flush synchronously so React commits the new icon to the DOM before we animate\n\t\t\t\t\t\tconst nextShowPassword = !showPassword;\n\t\t\t\t\t\tflushSync(() => {\n\t\t\t\t\t\t\tsetShowPassword(nextShowPassword);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tonValueVisibilityChange?.(nextShowPassword);\n\n\t\t\t\t\t\tconst icon = iconRef.current;\n\t\t\t\t\t\tif (icon && !getPrefersReducedMotion()) {\n\t\t\t\t\t\t\tanimationRef.current = icon.animate(\n\t\t\t\t\t\t\t\t[{ transform: \"scaleY(0)\" }, { transform: \"scaleY(1)\" }],\n\t\t\t\t\t\t\t\t{ duration: 200, easing: \"ease-out\" },\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tanimationRef.current.onfinish = () => {\n\t\t\t\t\t\t\t\tanimationRef.current = null;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<span className=\"sr-only\">Turn password visibility {showPassword ? \"off\" : \"on\"}</span>\n\t\t\t\t\t<Icon ref={iconRef} svg={<EyeCon aria-hidden />} />\n\t\t\t\t</button>\n\t\t\t</Input>\n\t\t);\n\t},\n);\nPasswordInput.displayName = \"PasswordInput\";\n\nexport { PasswordInput };\nexport type { PasswordInputProps };\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
1
  function e(e){return e!=null&&e instanceof HTMLInputElement}export{e as t};
2
- //# sourceMappingURL=is-input-Bh1rQhX3.js.map
2
+ //# sourceMappingURL=is-input-CUEWaxtA.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"is-input-Bh1rQhX3.js","names":[],"sources":["../src/components/input/is-input.ts"],"sourcesContent":["/**\n * Type guard for an HTMLInputElement.\n *\n * @example\n * ```tsx\n * function handleElement(element: HTMLElement) {\n * if (isInput(element)) {\n * // TypeScript now knows element is HTMLInputElement\n * element.value = \"new value\";\n * element.focus();\n * }\n * }\n * ```\n */\nexport function isInput(value: unknown): value is HTMLInputElement {\n\treturn value != null && value instanceof HTMLInputElement;\n}\n"],"mappings":"AAcA,SAAgB,EAAQ,EAA2C,CAClE,OAAO,GAAS,MAAQ,aAAiB"}
1
+ {"version":3,"file":"is-input-CUEWaxtA.js","names":[],"sources":["../src/components/input/is-input.ts"],"sourcesContent":["/**\n * Type guard for an HTMLInputElement.\n *\n * @example\n * ```tsx\n * function handleElement(element: HTMLElement) {\n * if (isInput(element)) {\n * // TypeScript now knows element is HTMLInputElement\n * element.value = \"new value\";\n * element.focus();\n * }\n * }\n * ```\n */\nexport function isInput(value: unknown): value is HTMLInputElement {\n\treturn value != null && value instanceof HTMLInputElement;\n}\n"],"mappings":"AAcA,SAAgB,EAAQ,EAA2C,CAClE,OAAO,GAAS,MAAQ,aAAiB"}
@@ -1,2 +1,2 @@
1
1
  import{t as e}from"./cx-D1HYnpvA.js";import{jsx as t}from"react/jsx-runtime";function n({children:n,className:r,...i}){return t(`kbd`,{"data-slot":`kbd`,className:e(`[font-kerning:normal] [font-variant-ligatures:common-ligatures_contextual]`,`appearance-none tabular-nums inline-grid place-items-center size-5 bg-neutral-500/15 px-1 rounded text-mono leading-none font-mono`,r),...i,children:n})}export{n as t};
2
- //# sourceMappingURL=kbd-B0wWeV_0.js.map
2
+ //# sourceMappingURL=kbd-CAVUiqBT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kbd-CAVUiqBT.js","names":[],"sources":["../src/components/kbd/kbd.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A square, centered keyboard \"key\" chip for rendering shortcut hints —\n * \"K\", \"⌘\", \"⌃\", \"Enter\". Renders a native `<kbd>` element so screen\n * readers announce it as keyboard input. Sized so letters and modifier\n * symbols share a consistent visual height, width, and baseline.\n *\n * **When to use**\n * - Documenting keyboard shortcuts in copy or tooltips.\n * - Inside menu items and command palettes alongside the action label.\n * - Inline with prose: \"Press `Kbd K` to open search.\"\n *\n * **When not to use**\n * - For arbitrary monospace text — use {@link https://mantle.ngrok.com/components/code Code}.\n * - For chord-style multi-key shortcuts as a single chip — render multiple\n * `<Kbd>` elements separated by `+` text instead.\n *\n * **Accessibility.** Symbol-only glyphs (`⌘`, `⌃`, `↵`) are not announced\n * meaningfully by screen readers. Provide an accessible name via\n * `aria-label` on the `<Kbd>` or include a visually-hidden label inside,\n * and mark the visible glyph `aria-hidden`.\n *\n * @see https://mantle.ngrok.com/components/kbd\n *\n * @example\n * ```tsx\n * import { Kbd } from \"@ngrok/mantle/kbd\";\n *\n * // Letter key.\n * <Kbd>K</Kbd>\n *\n * // Chord — render each key separately.\n * <span>\n * <Kbd aria-label=\"Command\">⌘</Kbd> + <Kbd>K</Kbd>\n * </span>\n *\n * // Symbol with sr-only label.\n * <Kbd>\n * <span className=\"sr-only\">Enter</span>\n * <span aria-hidden>↵</span>\n * </Kbd>\n * ```\n */\nfunction Kbd({ children, className, ...props }: ComponentProps<\"kbd\">) {\n\treturn (\n\t\t<kbd\n\t\t\tdata-slot=\"kbd\"\n\t\t\tclassName={cx(\n\t\t\t\t\"[font-kerning:normal] [font-variant-ligatures:common-ligatures_contextual]\",\n\t\t\t\t\"appearance-none tabular-nums inline-grid place-items-center size-5 bg-neutral-500/15 px-1 rounded text-mono leading-none font-mono\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</kbd>\n\t);\n}\n\nexport {\n\t//,\n\tKbd,\n};\n"],"mappings":"6EA6CA,SAAS,EAAI,CAAE,WAAU,YAAW,GAAG,GAAgC,CACtE,OACC,EAAC,MAAD,CACC,YAAU,MACV,UAAW,EACV,6EACA,qIACA,EACA,CACD,GAAI,EAEH,WACI,CAAA"}
package/dist/kbd.d.ts CHANGED
@@ -3,17 +3,46 @@ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/kbd/kbd.d.ts
5
5
  /**
6
- * A square, centered keyboard key chip for rendering shortcut hints
7
- * (e.g., "K", "⌘", "⌃"). Designed so every key—letters and modifiers—shares
8
- * the same visual height/width and baseline. Renders a native `<kbd>` element.
6
+ * A square, centered keyboard "key" chip for rendering shortcut hints
7
+ * "K", "⌘", "⌃", "Enter". Renders a native `<kbd>` element so screen
8
+ * readers announce it as keyboard input. Sized so letters and modifier
9
+ * symbols share a consistent visual height, width, and baseline.
9
10
  *
10
- * Accessibility:
11
- * - When showing a symbol (⌘/⌃), provide an accessible name via `aria-label`
12
- * or include an sr-only label inside. The visible glyph may be marked
13
- * `aria-hidden`.
11
+ * **When to use**
12
+ * - Documenting keyboard shortcuts in copy or tooltips.
13
+ * - Inside menu items and command palettes alongside the action label.
14
+ * - Inline with prose: "Press `Kbd K` to open search."
14
15
  *
15
- * @example Basic letter key
16
+ * **When not to use**
17
+ * - For arbitrary monospace text — use {@link https://mantle.ngrok.com/components/code Code}.
18
+ * - For chord-style multi-key shortcuts as a single chip — render multiple
19
+ * `<Kbd>` elements separated by `+` text instead.
20
+ *
21
+ * **Accessibility.** Symbol-only glyphs (`⌘`, `⌃`, `↵`) are not announced
22
+ * meaningfully by screen readers. Provide an accessible name via
23
+ * `aria-label` on the `<Kbd>` or include a visually-hidden label inside,
24
+ * and mark the visible glyph `aria-hidden`.
25
+ *
26
+ * @see https://mantle.ngrok.com/components/kbd
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * import { Kbd } from "@ngrok/mantle/kbd";
31
+ *
32
+ * // Letter key.
16
33
  * <Kbd>K</Kbd>
34
+ *
35
+ * // Chord — render each key separately.
36
+ * <span>
37
+ * <Kbd aria-label="Command">⌘</Kbd> + <Kbd>K</Kbd>
38
+ * </span>
39
+ *
40
+ * // Symbol with sr-only label.
41
+ * <Kbd>
42
+ * <span className="sr-only">Enter</span>
43
+ * <span aria-hidden>↵</span>
44
+ * </Kbd>
45
+ * ```
17
46
  */
18
47
  declare function Kbd({
19
48
  children,
package/dist/kbd.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./kbd-B0wWeV_0.js";export{e as Kbd};
1
+ import{t as e}from"./kbd-CAVUiqBT.js";export{e as Kbd};
package/dist/label.d.ts CHANGED
@@ -2,23 +2,54 @@ import * as _$react from "react";
2
2
 
3
3
  //#region src/components/label/label.d.ts
4
4
  /**
5
- * A Label represents a caption for an item in a user interface. It is used to
6
- * provide a description or title for a form control, such as an input field,
7
- * checkbox, radio button, etc. The label is typically displayed next to the
8
- * form control and helps users understand its purpose.
5
+ * A caption for a form control input, checkbox, radio, switch, select.
6
+ * Renders a native `<label>`. Pair every form control with a `Label` so the
7
+ * control has an accessible name, clicks on the label focus the control, and
8
+ * screen readers announce the field correctly.
9
+ *
10
+ * **When to use**
11
+ * - Every visible form control. Always.
12
+ * - Above or beside an input to describe it ("Email", "API key").
13
+ * - Wrapping a checkbox or radio next to its descriptive text.
14
+ *
15
+ * **When not to use**
16
+ * - For static UI text that isn't labeling a control — use a heading or
17
+ * plain `<p>`/`<span>`.
18
+ * - As a substitute for `aria-label` on non-`<input>` widgets that don't
19
+ * support `<label for>` association.
20
+ *
21
+ * **Two ways to associate.** Either wrap the control inside the `<Label>`
22
+ * (implicit association — simplest) or set `htmlFor` to the control's `id`
23
+ * (explicit — required when the control isn't a child).
24
+ *
25
+ * **Disabled state.** Pass `disabled` to render the label in a disabled
26
+ * style. Typically you'll want this to mirror the underlying control's
27
+ * disabled state so the visual treatment stays consistent.
9
28
  *
10
29
  * @see https://mantle.ngrok.com/components/label
11
30
  *
12
31
  * @example
13
32
  * ```tsx
14
- * <Label htmlFor="name">
15
- * Name: <Input type="text" id="name" />
33
+ * import { Label } from "@ngrok/mantle/label";
34
+ * import { Input } from "@ngrok/mantle/input";
35
+ *
36
+ * // Implicit — control nested inside the label.
37
+ * <Label className="grid gap-1">
38
+ * <span>Email</span>
39
+ * <Input type="email" name="email" />
16
40
  * </Label>
17
41
  *
18
- * <div className="flex items-center gap-2">
19
- * <Label htmlFor="name-2">Name:</Label>
20
- * <Input type="text" id="name-2" />
42
+ * // Explicit htmlFor matches the control's id.
43
+ * <div className="grid gap-1">
44
+ * <Label htmlFor="api-key">API key</Label>
45
+ * <Input id="api-key" name="apiKey" />
21
46
  * </div>
47
+ *
48
+ * // Inline label for a checkbox.
49
+ * <Label className="flex items-center gap-2">
50
+ * <Checkbox name="terms" />
51
+ * <span>I agree to the terms</span>
52
+ * </Label>
22
53
  * ```
23
54
  */
24
55
  declare const Label: _$react.ForwardRefExoticComponent<Omit<_$react.DetailedHTMLProps<_$react.LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>, "ref"> & {
package/dist/label.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"label.js","names":[],"sources":["../src/components/label/label.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype LabelProps = ComponentPropsWithoutRef<\"label\"> & {\n\t/**\n\t * If set, the label will appear disabled.\n\t */\n\tdisabled?: boolean;\n};\n\n/**\n * A Label represents a caption for an item in a user interface. It is used to\n * provide a description or title for a form control, such as an input field,\n * checkbox, radio button, etc. The label is typically displayed next to the\n * form control and helps users understand its purpose.\n *\n * @see https://mantle.ngrok.com/components/label\n *\n * @example\n * ```tsx\n * <Label htmlFor=\"name\">\n * Name: <Input type=\"text\" id=\"name\" />\n * </Label>\n *\n * <div className=\"flex items-center gap-2\">\n * <Label htmlFor=\"name-2\">Name:</Label>\n * <Input type=\"text\" id=\"name-2\" />\n * </div>\n * ```\n */\nconst Label = forwardRef<ComponentRef<\"label\">, LabelProps>(\n\t(\n\t\t{ \"aria-disabled\": _ariaDisabled, children, className, disabled, onMouseDown, ...props },\n\t\tref,\n\t) => (\n\t\t// biome-ignore lint/a11y/noLabelWithoutControl: this is a composable label component\n\t\t<label\n\t\t\taria-disabled={disabled ?? _ariaDisabled}\n\t\t\tdata-slot=\"label\"\n\t\t\tclassName={cx(\n\t\t\t\t\"text-strong cursor-pointer text-sm peer-disabled:cursor-default has-disabled:cursor-default aria-disabled:cursor-default font-sans\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tonMouseDown={(event) => {\n\t\t\t\t// only prevent text selection if clicking inside the label itself\n\t\t\t\tconst target = event.target as HTMLElement;\n\t\t\t\tif (target.closest(\"button, input, select, textarea\")) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tonMouseDown?.(event);\n\n\t\t\t\t// prevent text selection when double clicking label\n\t\t\t\tif (!event.defaultPrevented && event.detail > 1) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</label>\n\t),\n);\nLabel.displayName = \"Label\";\n\nexport {\n\t//\n\tLabel,\n};\n"],"mappings":"gHA+BA,MAAM,EAAQ,GAEZ,CAAE,gBAAiB,EAAe,WAAU,YAAW,WAAU,cAAa,GAAG,GACjF,IAGA,EAAC,QAAD,CACC,gBAAe,GAAY,EAC3B,YAAU,QACV,UAAW,EACV,qIACA,EACA,CACD,YAAc,GAAU,CAER,EAAM,OACV,QAAQ,kCAAkC,GAIrD,IAAc,EAAM,CAGhB,CAAC,EAAM,kBAAoB,EAAM,OAAS,GAC7C,EAAM,gBAAgB,GAGnB,MACL,GAAI,EAEH,WACM,CAAA,CAET,CACD,EAAM,YAAc"}
1
+ {"version":3,"file":"label.js","names":[],"sources":["../src/components/label/label.tsx"],"sourcesContent":["import { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\ntype LabelProps = ComponentPropsWithoutRef<\"label\"> & {\n\t/**\n\t * If set, the label will appear disabled.\n\t */\n\tdisabled?: boolean;\n};\n\n/**\n * A caption for a form control input, checkbox, radio, switch, select.\n * Renders a native `<label>`. Pair every form control with a `Label` so the\n * control has an accessible name, clicks on the label focus the control, and\n * screen readers announce the field correctly.\n *\n * **When to use**\n * - Every visible form control. Always.\n * - Above or beside an input to describe it (\"Email\", \"API key\").\n * - Wrapping a checkbox or radio next to its descriptive text.\n *\n * **When not to use**\n * - For static UI text that isn't labeling a control — use a heading or\n * plain `<p>`/`<span>`.\n * - As a substitute for `aria-label` on non-`<input>` widgets that don't\n * support `<label for>` association.\n *\n * **Two ways to associate.** Either wrap the control inside the `<Label>`\n * (implicit association — simplest) or set `htmlFor` to the control's `id`\n * (explicit — required when the control isn't a child).\n *\n * **Disabled state.** Pass `disabled` to render the label in a disabled\n * style. Typically you'll want this to mirror the underlying control's\n * disabled state so the visual treatment stays consistent.\n *\n * @see https://mantle.ngrok.com/components/label\n *\n * @example\n * ```tsx\n * import { Label } from \"@ngrok/mantle/label\";\n * import { Input } from \"@ngrok/mantle/input\";\n *\n * // Implicit — control nested inside the label.\n * <Label className=\"grid gap-1\">\n * <span>Email</span>\n * <Input type=\"email\" name=\"email\" />\n * </Label>\n *\n * // Explicit — htmlFor matches the control's id.\n * <div className=\"grid gap-1\">\n * <Label htmlFor=\"api-key\">API key</Label>\n * <Input id=\"api-key\" name=\"apiKey\" />\n * </div>\n *\n * // Inline label for a checkbox.\n * <Label className=\"flex items-center gap-2\">\n * <Checkbox name=\"terms\" />\n * <span>I agree to the terms</span>\n * </Label>\n * ```\n */\nconst Label = forwardRef<ComponentRef<\"label\">, LabelProps>(\n\t(\n\t\t{ \"aria-disabled\": _ariaDisabled, children, className, disabled, onMouseDown, ...props },\n\t\tref,\n\t) => (\n\t\t// biome-ignore lint/a11y/noLabelWithoutControl: this is a composable label component\n\t\t<label\n\t\t\taria-disabled={disabled ?? _ariaDisabled}\n\t\t\tdata-slot=\"label\"\n\t\t\tclassName={cx(\n\t\t\t\t\"text-strong cursor-pointer text-sm peer-disabled:cursor-default has-disabled:cursor-default aria-disabled:cursor-default font-sans\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tonMouseDown={(event) => {\n\t\t\t\t// only prevent text selection if clicking inside the label itself\n\t\t\t\tconst target = event.target as HTMLElement;\n\t\t\t\tif (target.closest(\"button, input, select, textarea\")) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tonMouseDown?.(event);\n\n\t\t\t\t// prevent text selection when double clicking label\n\t\t\t\tif (!event.defaultPrevented && event.detail > 1) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</label>\n\t),\n);\nLabel.displayName = \"Label\";\n\nexport {\n\t//\n\tLabel,\n};\n"],"mappings":"gHA8DA,MAAM,EAAQ,GAEZ,CAAE,gBAAiB,EAAe,WAAU,YAAW,WAAU,cAAa,GAAG,GACjF,IAGA,EAAC,QAAD,CACC,gBAAe,GAAY,EAC3B,YAAU,QACV,UAAW,EACV,qIACA,EACA,CACD,YAAc,GAAU,CAER,EAAM,OACV,QAAQ,kCAAkC,GAIrD,IAAc,EAAM,CAGhB,CAAC,EAAM,kBAAoB,EAAM,OAAS,GAC7C,EAAM,gBAAgB,GAGnB,MACL,GAAI,EAEH,WACM,CAAA,CAET,CACD,EAAM,YAAc"}
@@ -1,21 +1,34 @@
1
- import { t as WithAsChild } from "./as-child-CJ2vTesV.js";
1
+ import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
2
2
  import * as _$react from "react";
3
3
  import { ComponentProps } from "react";
4
4
 
5
5
  //#region src/components/media-object/media-object.d.ts
6
6
  type Props = ComponentProps<"div"> & WithAsChild;
7
7
  /**
8
- * The media object is an image/icon (media) to the left, with descriptive
9
- * content (title and subtitle/description) to the right. This is the root
10
- * component of the media object.
8
+ * A small, reusable layout primitive for "image/icon on one side,
9
+ * descriptive content on the other" the foundational
10
+ * {@link https://www.stubbornella.org/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code/ "media object" pattern}.
11
+ * Use it to compose avatars-with-text, icons-with-copy, thumbnails-with-titles,
12
+ * and similar two-up rows without re-implementing flexbox each time.
11
13
  *
12
- * Change the spacing between the media and content by passing a `gap-*` class.
13
- * The default gap is `gap-4`.
14
+ * **When to use**
15
+ * - Comment threads (avatar + name + body).
16
+ * - Compact list items (icon + label + secondary text).
17
+ * - Notification rows.
18
+ * - Feature lists, profile cards, attachment previews.
14
19
  *
15
- * Use flexbox utilities to change the alignment of the media and content.
20
+ * **When not to use**
21
+ * - For complex multi-region layouts — reach for {@link https://mantle.ngrok.com/components/card Card} or build a bespoke flex/grid.
22
+ * - When the media is purely decorative and adds no information — drop it
23
+ * and use a plain block.
16
24
  *
17
- * Compose the media object with the `MediaObject.Media` and `MediaObject.Content`
18
- * components as direct children.
25
+ * **Spacing & alignment.** Default gap is `gap-4`; override by passing a
26
+ * different `gap-*` class to `MediaObject.Root`. Use standard flex
27
+ * utilities (`items-start`, `items-center`, etc.) to align media and
28
+ * content vertically.
29
+ *
30
+ * **Polymorphism.** Each part accepts `asChild` for swapping the rendered
31
+ * element (e.g. render `Root` as an `<a>` to make the whole row clickable).
19
32
  *
20
33
  * @see https://mantle.ngrok.com/components/media-object
21
34
  *
@@ -29,12 +42,15 @@ type Props = ComponentProps<"div"> & WithAsChild;
29
42
  *
30
43
  * @example
31
44
  * ```tsx
45
+ * import { MediaObject } from "@ngrok/mantle/media-object";
46
+ *
32
47
  * <MediaObject.Root>
33
48
  * <MediaObject.Media>
34
- * <ExampleMedia />
49
+ * <Avatar src={user.avatarUrl} alt="" />
35
50
  * </MediaObject.Media>
36
51
  * <MediaObject.Content>
37
- * <p>Ea culpa id id ea minim labore.</p>
52
+ * <p className="font-medium">{user.name}</p>
53
+ * <p className="text-muted text-sm">{comment}</p>
38
54
  * </MediaObject.Content>
39
55
  * </MediaObject.Root>
40
56
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"media-object.js","names":[],"sources":["../src/components/media-object/media-object.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { forwardRef } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype Props = ComponentProps<\"div\"> & WithAsChild;\n\n/**\n * The media object is an image/icon (media) to the left, with descriptive\n * content (title and subtitle/description) to the right. This is the root\n * component of the media object.\n */\nconst Root = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object\"\n\t\t\t\tclassName={cx(\"flex gap-4\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nRoot.displayName = \"MediaObject\";\n\n/**\n * The container for an image or icon to display in the media slot of the media object.\n */\nconst Media = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object-media\"\n\t\t\t\tclassName={cx(\"shrink-0 leading-none\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nMedia.displayName = \"MediaObjectMedia\";\n\n/**\n * The container for the content slot of a media object.\n */\nconst Content = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object-content\"\n\t\t\t\tclassName={cx(\"min-w-0 flex-1\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nContent.displayName = \"MediaObject.Content\";\n\n/**\n * The media object is an image/icon (media) to the left, with descriptive\n * content (title and subtitle/description) to the right. This is the root\n * component of the media object.\n *\n * Change the spacing between the media and content by passing a `gap-*` class.\n * The default gap is `gap-4`.\n *\n * Use flexbox utilities to change the alignment of the media and content.\n *\n * Compose the media object with the `MediaObject.Media` and `MediaObject.Content`\n * components as direct children.\n *\n * @see https://mantle.ngrok.com/components/media-object\n *\n * @example\n * Composition:\n * ```\n * MediaObject.Root\n * ├── MediaObject.Media\n * └── MediaObject.Content\n * ```\n *\n * @example\n * ```tsx\n * <MediaObject.Root>\n * <MediaObject.Media>\n * <ExampleMedia />\n * </MediaObject.Media>\n * <MediaObject.Content>\n * <p>Ea culpa id id ea minim labore.</p>\n * </MediaObject.Content>\n * </MediaObject.Root>\n * ```\n */\nconst MediaObject = {\n\t/**\n\t * The media object is an image/icon (media) to the left, with descriptive\n\t * content (title and subtitle/description) to the right. This is the root\n\t * component of the media object.\n\t *\n\t * Change the spacing between the media and content by passing a `gap-*` class.\n\t * The default gap is `gap-4`.\n\t *\n\t * Use flexbox utilities to change the alignment of the media and content.\n\t *\n\t * Compose the media object with the `MediaObject.Media` and `MediaObject.Content`\n\t * components as direct children.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The container for an image or icon to display in the media slot of the media object.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectmedia\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tMedia,\n\t/**\n\t * The container for the content slot of a media object.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tContent,\n} as const;\n\nexport {\n\t//,\n\tMediaObject,\n};\n"],"mappings":"kJAaA,MAAM,EAAO,GACX,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,eACV,UAAW,EAAG,aAAc,EAAU,CAC/B,QAEN,WACU,CAAA,CAGd,CACD,EAAK,YAAc,cAKnB,MAAM,EAAQ,GACZ,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,qBACV,UAAW,EAAG,wBAAyB,EAAU,CAC1C,QAEN,WACU,CAAA,CAGd,CACD,EAAM,YAAc,mBAKpB,MAAM,EAAU,GACd,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,uBACV,UAAW,EAAG,iBAAkB,EAAU,CACnC,QAEN,WACU,CAAA,CAGd,CACD,EAAQ,YAAc,sBAqCtB,MAAM,EAAc,CA4BnB,OAkBA,QAkBA,UACA"}
1
+ {"version":3,"file":"media-object.js","names":[],"sources":["../src/components/media-object/media-object.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { forwardRef } from \"react\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype Props = ComponentProps<\"div\"> & WithAsChild;\n\n/**\n * The media object is an image/icon (media) to the left, with descriptive\n * content (title and subtitle/description) to the right. This is the root\n * component of the media object.\n */\nconst Root = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object\"\n\t\t\t\tclassName={cx(\"flex gap-4\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nRoot.displayName = \"MediaObject\";\n\n/**\n * The container for an image or icon to display in the media slot of the media object.\n */\nconst Media = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object-media\"\n\t\t\t\tclassName={cx(\"shrink-0 leading-none\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nMedia.displayName = \"MediaObjectMedia\";\n\n/**\n * The container for the content slot of a media object.\n */\nconst Content = forwardRef<HTMLDivElement, Props>(\n\t({ asChild = false, className, children, style }, ref) => {\n\t\tconst Component = asChild ? Slot : \"div\";\n\n\t\treturn (\n\t\t\t<Component\n\t\t\t\tref={ref}\n\t\t\t\tdata-slot=\"media-object-content\"\n\t\t\t\tclassName={cx(\"min-w-0 flex-1\", className)}\n\t\t\t\tstyle={style}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</Component>\n\t\t);\n\t},\n);\nContent.displayName = \"MediaObject.Content\";\n\n/**\n * A small, reusable layout primitive for \"image/icon on one side,\n * descriptive content on the other\" — the foundational\n * {@link https://www.stubbornella.org/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code/ \"media object\" pattern}.\n * Use it to compose avatars-with-text, icons-with-copy, thumbnails-with-titles,\n * and similar two-up rows without re-implementing flexbox each time.\n *\n * **When to use**\n * - Comment threads (avatar + name + body).\n * - Compact list items (icon + label + secondary text).\n * - Notification rows.\n * - Feature lists, profile cards, attachment previews.\n *\n * **When not to use**\n * - For complex multi-region layouts — reach for {@link https://mantle.ngrok.com/components/card Card} or build a bespoke flex/grid.\n * - When the media is purely decorative and adds no information — drop it\n * and use a plain block.\n *\n * **Spacing & alignment.** Default gap is `gap-4`; override by passing a\n * different `gap-*` class to `MediaObject.Root`. Use standard flex\n * utilities (`items-start`, `items-center`, etc.) to align media and\n * content vertically.\n *\n * **Polymorphism.** Each part accepts `asChild` for swapping the rendered\n * element (e.g. render `Root` as an `<a>` to make the whole row clickable).\n *\n * @see https://mantle.ngrok.com/components/media-object\n *\n * @example\n * Composition:\n * ```\n * MediaObject.Root\n * ├── MediaObject.Media\n * └── MediaObject.Content\n * ```\n *\n * @example\n * ```tsx\n * import { MediaObject } from \"@ngrok/mantle/media-object\";\n *\n * <MediaObject.Root>\n * <MediaObject.Media>\n * <Avatar src={user.avatarUrl} alt=\"\" />\n * </MediaObject.Media>\n * <MediaObject.Content>\n * <p className=\"font-medium\">{user.name}</p>\n * <p className=\"text-muted text-sm\">{comment}</p>\n * </MediaObject.Content>\n * </MediaObject.Root>\n * ```\n */\nconst MediaObject = {\n\t/**\n\t * The media object is an image/icon (media) to the left, with descriptive\n\t * content (title and subtitle/description) to the right. This is the root\n\t * component of the media object.\n\t *\n\t * Change the spacing between the media and content by passing a `gap-*` class.\n\t * The default gap is `gap-4`.\n\t *\n\t * Use flexbox utilities to change the alignment of the media and content.\n\t *\n\t * Compose the media object with the `MediaObject.Media` and `MediaObject.Content`\n\t * components as direct children.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * The container for an image or icon to display in the media slot of the media object.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectmedia\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tMedia,\n\t/**\n\t * The container for the content slot of a media object.\n\t *\n\t * @see https://mantle.ngrok.com/components/media-object#mediaobjectcontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <MediaObject.Root>\n\t * <MediaObject.Media>\n\t * <ExampleMedia />\n\t * </MediaObject.Media>\n\t * <MediaObject.Content>\n\t * <p>Ea culpa id id ea minim labore.</p>\n\t * </MediaObject.Content>\n\t * </MediaObject.Root>\n\t * ```\n\t */\n\tContent,\n} as const;\n\nexport {\n\t//,\n\tMediaObject,\n};\n"],"mappings":"kJAaA,MAAM,EAAO,GACX,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,eACV,UAAW,EAAG,aAAc,EAAU,CAC/B,QAEN,WACU,CAAA,CAGd,CACD,EAAK,YAAc,cAKnB,MAAM,EAAQ,GACZ,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,qBACV,UAAW,EAAG,wBAAyB,EAAU,CAC1C,QAEN,WACU,CAAA,CAGd,CACD,EAAM,YAAc,mBAKpB,MAAM,EAAU,GACd,CAAE,UAAU,GAAO,YAAW,WAAU,SAAS,IAIhD,EAHiB,EAAU,EAAO,MAGlC,CACM,MACL,YAAU,uBACV,UAAW,EAAG,iBAAkB,EAAU,CACnC,QAEN,WACU,CAAA,CAGd,CACD,EAAQ,YAAc,sBAqDtB,MAAM,EAAc,CA4BnB,OAkBA,QAkBA,UACA"}