@ngrok/mantle 0.70.0 → 0.70.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion.d.ts +2 -2
- package/dist/accordion.js +1 -1
- package/dist/accordion.js.map +1 -1
- package/dist/alert-dialog.d.ts +6 -6
- package/dist/alert-dialog.js +1 -1
- package/dist/alert-dialog.js.map +1 -1
- package/dist/alert.d.ts +3 -3
- package/dist/alert.js +1 -1
- package/dist/alert.js.map +1 -1
- package/dist/anchor-2stEauOz.js +2 -0
- package/dist/anchor-2stEauOz.js.map +1 -0
- package/dist/anchor.d.ts +1 -1
- package/dist/anchor.js +1 -1
- package/dist/{as-child-CJ2vTesV.d.ts → as-child-DQHfEmYB.d.ts} +1 -1
- package/dist/badge.d.ts +2 -2
- package/dist/badge.js +1 -1
- package/dist/badge.js.map +1 -1
- package/dist/{button-DDK6nEac.d.ts → button-BMgAxAwM.d.ts} +3 -3
- package/dist/{button-BKykcpgJ.js → button-GokecthL.js} +2 -2
- package/dist/{button-BKykcpgJ.js.map → button-GokecthL.js.map} +1 -1
- package/dist/button-POMJ-20y.js +2 -0
- package/dist/button-POMJ-20y.js.map +1 -0
- package/dist/button.d.ts +3 -3
- package/dist/button.js +1 -1
- package/dist/calendar.js +1 -1
- package/dist/calendar.js.map +1 -1
- package/dist/card.d.ts +1 -1
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/checkbox.d.ts +2 -2
- package/dist/checkbox.js +1 -1
- package/dist/checkbox.js.map +1 -1
- package/dist/code-block.d.ts +3 -3
- package/dist/code-block.js +1 -1
- package/dist/code-block.js.map +1 -1
- package/dist/code-block_highlight-utils.d.ts +1 -1
- package/dist/code-block_highlight-utils.js +1 -1
- package/dist/code.d.ts +2 -2
- package/dist/code.js +1 -1
- package/dist/code.js.map +1 -1
- package/dist/color.d.ts +1 -1
- package/dist/combobox.d.ts +2 -2
- package/dist/combobox.js +1 -1
- package/dist/combobox.js.map +1 -1
- package/dist/command.d.ts +4 -4
- package/dist/command.js +1 -1
- package/dist/command.js.map +1 -1
- package/dist/compose-refs-DZ3cPi47.js +2 -0
- package/dist/compose-refs-DZ3cPi47.js.map +1 -0
- package/dist/copy-to-clipboard-DjOD_Mwb.js +2 -0
- package/dist/copy-to-clipboard-DjOD_Mwb.js.map +1 -0
- package/dist/data-table.d.ts +246 -72
- package/dist/data-table.js +1 -1
- package/dist/data-table.js.map +1 -1
- package/dist/{deep-non-nullable-DwBZzk4x.d.ts → deep-non-nullable-VFm1T3JZ.d.ts} +1 -1
- package/dist/description-list.d.ts +1 -1
- package/dist/description-list.js +1 -1
- package/dist/description-list.js.map +1 -1
- package/dist/dialog-BHzl9eye.js +2 -0
- package/dist/dialog-BHzl9eye.js.map +1 -0
- package/dist/dialog.d.ts +4 -4
- package/dist/dialog.js +1 -1
- package/dist/{direction-ClCocWIf.js → direction-DsB-pD9V.js} +1 -1
- package/dist/{direction-ClCocWIf.js.map → direction-DsB-pD9V.js.map} +1 -1
- package/dist/{direction-Jk7BkzGo.d.ts → direction-DtBAQn7p.d.ts} +1 -1
- package/dist/{dropdown-menu-BwQDoun1.d.ts → dropdown-menu-CzUNYIfA.d.ts} +3 -3
- package/dist/dropdown-menu-Ducs2SEn.js +2 -0
- package/dist/dropdown-menu-Ducs2SEn.js.map +1 -0
- package/dist/dropdown-menu.d.ts +1 -1
- package/dist/dropdown-menu.js +1 -1
- package/dist/empty.d.ts +6 -4
- package/dist/empty.js +1 -1
- package/dist/empty.js.map +1 -1
- package/dist/flag.js +1 -1
- package/dist/flag.js.map +1 -1
- package/dist/hooks.d.ts +5 -6
- package/dist/hooks.js +1 -1
- package/dist/hover-card.d.ts +9 -1
- package/dist/hover-card.js +1 -1
- package/dist/hover-card.js.map +1 -1
- package/dist/{icon-C7Dje_lR.d.ts → icon-DKMJm20j.d.ts} +2 -2
- package/dist/icon-bWc5yC3-.js +2 -0
- package/dist/{icon-BMH0fD_b.js.map → icon-bWc5yC3-.js.map} +1 -1
- package/dist/{icon-button-Cl30yTfu.d.ts → icon-button-BnK4K7YK.d.ts} +3 -3
- package/dist/{icon-button-CxxVPiKp.js → icon-button-ZKN0sRIJ.js} +2 -2
- package/dist/{icon-button-CxxVPiKp.js.map → icon-button-ZKN0sRIJ.js.map} +1 -1
- package/dist/icon.d.ts +3 -3
- package/dist/icon.js +1 -1
- package/dist/icons.d.ts +3 -3
- package/dist/icons.js +1 -1
- package/dist/{in-view-DsiWfQpY.d.ts → in-view-Da08Bx6l.d.ts} +15 -4
- package/dist/{in-view-BXzPPdcl.js → in-view-pia_SVdE.js} +1 -1
- package/dist/{in-view-BXzPPdcl.js.map → in-view-pia_SVdE.js.map} +1 -1
- package/dist/{index-A354MgUP.d.ts → index-DMAkXvFI.d.ts} +5 -5
- package/dist/{index-DFBA9X1i.d.ts → index-DOJUH34Z.d.ts} +4 -3
- package/dist/{index-B6SPk_xb.d.ts → index-DkMUaYsw.d.ts} +1 -1
- package/dist/{index-vOSpS5jv.d.ts → index-rtz7SwEq.d.ts} +1 -1
- package/dist/input.d.ts +2 -2
- package/dist/input.js +1 -1
- package/dist/input.js.map +1 -1
- package/dist/{is-input-Bh1rQhX3.js → is-input-CUEWaxtA.js} +1 -1
- package/dist/{is-input-Bh1rQhX3.js.map → is-input-CUEWaxtA.js.map} +1 -1
- package/dist/kbd-CAVUiqBT.js +2 -0
- package/dist/{kbd-GS-e4ICt.js.map → kbd-CAVUiqBT.js.map} +1 -1
- package/dist/kbd.js +1 -1
- package/dist/label.js +1 -1
- package/dist/label.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/media-object.d.ts +1 -1
- package/dist/media-object.js +1 -1
- package/dist/media-object.js.map +1 -1
- package/dist/multi-select.d.ts +2 -2
- package/dist/multi-select.js +1 -1
- package/dist/pagination.d.ts +3 -3
- package/dist/pagination.js +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/popover.d.ts +12 -0
- package/dist/popover.js +1 -1
- package/dist/popover.js.map +1 -1
- package/dist/{primitive-pggbsddf.js → primitive-tXm_8n_t.js} +2 -2
- package/dist/{primitive-pggbsddf.js.map → primitive-tXm_8n_t.js.map} +1 -1
- package/dist/{primitive-DXo0gUqw.d.ts → primitive-tyw4V7Vf.d.ts} +1 -1
- package/dist/progress.js +1 -1
- package/dist/progress.js.map +1 -1
- package/dist/radio-group.d.ts +1 -1
- package/dist/radio-group.js +1 -1
- package/dist/radio-group.js.map +1 -1
- package/dist/{resolve-pre-rendered-props-BXv6e6fc.js → resolve-pre-rendered-props-C-kiaLHj.js} +1 -1
- package/dist/{resolve-pre-rendered-props-BXv6e6fc.js.map → resolve-pre-rendered-props-C-kiaLHj.js.map} +1 -1
- package/dist/{resolve-pre-rendered-props-kcQrtWPt.d.ts → resolve-pre-rendered-props-x-52gvQ1.d.ts} +2 -2
- package/dist/sandboxed-on-click.d.ts +1 -1
- package/dist/{select-DNJli9JO.d.ts → select-BjpP51vO.d.ts} +3 -3
- package/dist/select-DOgdZO0Q.js +2 -0
- package/dist/select-DOgdZO0Q.js.map +1 -0
- package/dist/select.d.ts +1 -1
- package/dist/select.js +1 -1
- package/dist/separator-DSOIrnhj.js +2 -0
- package/dist/separator-DSOIrnhj.js.map +1 -0
- package/dist/separator.d.ts +1 -1
- package/dist/separator.js +1 -1
- package/dist/sheet.d.ts +2 -2
- package/dist/sheet.js +1 -1
- package/dist/sheet.js.map +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/skeleton.js.map +1 -1
- package/dist/skip-to-main-link.js +1 -1
- package/dist/skip-to-main-link.js.map +1 -1
- package/dist/{sort-C_Jbs1dH.js → sort-DzCsa6Qj.js} +2 -2
- package/dist/{sort-C_Jbs1dH.js.map → sort-DzCsa6Qj.js.map} +1 -1
- package/dist/split-button.d.ts +3 -3
- package/dist/split-button.js +1 -1
- package/dist/{svg-only-DnZldAY9.js → svg-only-7gYlsX8f.js} +2 -2
- package/dist/{svg-only-DnZldAY9.js.map → svg-only-7gYlsX8f.js.map} +1 -1
- package/dist/{svg-only-B-xzpaiu.d.ts → svg-only-BtBvFy-N.d.ts} +2 -2
- package/dist/switch.js +1 -1
- package/dist/switch.js.map +1 -1
- package/dist/{table-4q1UxE7L.d.ts → table--DsTqaWO.d.ts} +1 -1
- package/dist/table-Cl4nlRMR.js +2 -0
- package/dist/table-Cl4nlRMR.js.map +1 -0
- package/dist/table.d.ts +1 -1
- package/dist/table.js +1 -1
- package/dist/tabs.js +1 -1
- package/dist/tabs.js.map +1 -1
- package/dist/text-area.d.ts +1 -1
- package/dist/text-area.js +1 -1
- package/dist/text-area.js.map +1 -1
- package/dist/theme.d.ts +1 -1
- package/dist/{themes-DXb8Tk74.d.ts → themes-DIEYkvNl.d.ts} +1 -1
- package/dist/toast-CGnquSKO.js +2 -0
- package/dist/toast-CGnquSKO.js.map +1 -0
- package/dist/toast.d.ts +3 -3
- package/dist/toast.js +1 -1
- package/dist/tooltip.d.ts +9 -2
- package/dist/tooltip.js.map +1 -1
- package/dist/{traffic-policy-file-ChsoQtXQ.js → traffic-policy-file-C6LHYrIU.js} +1 -1
- package/dist/{traffic-policy-file-ChsoQtXQ.js.map → traffic-policy-file-C6LHYrIU.js.map} +1 -1
- package/dist/{types-BeTbgoJd.d.ts → types-DG0WQLTL.d.ts} +1 -1
- package/dist/types-DoV0R5Ja.d.ts +30 -0
- package/dist/types.d.ts +5 -5
- package/dist/use-copy-to-clipboard-C7vsjJe-.js +2 -0
- package/dist/use-copy-to-clipboard-C7vsjJe-.js.map +1 -0
- package/dist/{use-prefers-reduced-motion-BcwST13S.js → use-prefers-reduced-motion-aXfsyo-k.js} +1 -1
- package/dist/{use-prefers-reduced-motion-BcwST13S.js.map → use-prefers-reduced-motion-aXfsyo-k.js.map} +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/{variant-props-DszdagRm.d.ts → variant-props-DUmSIQK8.d.ts} +2 -2
- package/dist/{with-style-props-Dlz3G1tS.d.ts → with-style-props-3iFrBR08.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/anchor-BtIZueBA.js +0 -2
- package/dist/anchor-BtIZueBA.js.map +0 -1
- package/dist/button-DdrxOnUb.js +0 -2
- package/dist/button-DdrxOnUb.js.map +0 -1
- package/dist/compose-refs-DFIaEnQH.js +0 -2
- package/dist/compose-refs-DFIaEnQH.js.map +0 -1
- package/dist/dialog-Cw3E0Wr9.js +0 -2
- package/dist/dialog-Cw3E0Wr9.js.map +0 -1
- package/dist/dropdown-menu-Bfi9ODPB.js +0 -2
- package/dist/dropdown-menu-Bfi9ODPB.js.map +0 -1
- package/dist/icon-BMH0fD_b.js +0 -2
- package/dist/kbd-GS-e4ICt.js +0 -2
- package/dist/select-BPzMl3gm.js +0 -2
- package/dist/select-BPzMl3gm.js.map +0 -1
- package/dist/separator-Yk9hMn8E.js +0 -2
- package/dist/separator-Yk9hMn8E.js.map +0 -1
- package/dist/table-BMGcRJlk.js +0 -2
- package/dist/table-BMGcRJlk.js.map +0 -1
- package/dist/toast-BhAyUXKL.js +0 -2
- package/dist/toast-BhAyUXKL.js.map +0 -1
- package/dist/types-zKzi66a6.d.ts +0 -9
- package/dist/use-copy-to-clipboard-Ds9MsSNU.js +0 -2
- package/dist/use-copy-to-clipboard-Ds9MsSNU.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { t as
|
|
1
|
+
import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
|
|
2
|
+
import { t as VariantProps } from "./variant-props-DUmSIQK8.js";
|
|
2
3
|
import * as _$react from "react";
|
|
3
4
|
import { ComponentProps } from "react";
|
|
4
5
|
import * as _$class_variance_authority_types0 from "class-variance-authority/types";
|
|
@@ -8,7 +9,7 @@ declare const buttonGroupVariants: (props?: ({
|
|
|
8
9
|
appearance?: "ghost" | "outlined" | "panel" | null | undefined;
|
|
9
10
|
} & _$class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
10
11
|
type ButtonGroupVariants = VariantProps<typeof buttonGroupVariants>;
|
|
11
|
-
type ButtonGroupProps = ComponentProps<"div"> & ButtonGroupVariants;
|
|
12
|
+
type ButtonGroupProps = ComponentProps<"div"> & ButtonGroupVariants & WithAsChild;
|
|
12
13
|
/**
|
|
13
14
|
* A contained group of related buttons.
|
|
14
15
|
*
|
|
@@ -26,4 +27,4 @@ type ButtonGroupProps = ComponentProps<"div"> & ButtonGroupVariants;
|
|
|
26
27
|
declare const ButtonGroup: _$react.ForwardRefExoticComponent<Omit<ButtonGroupProps, "ref"> & _$react.RefAttributes<HTMLDivElement>>;
|
|
27
28
|
//#endregion
|
|
28
29
|
export { ButtonGroupProps as n, ButtonGroup as t };
|
|
29
|
-
//# sourceMappingURL=index-
|
|
30
|
+
//# sourceMappingURL=index-DOJUH34Z.d.ts.map
|
|
@@ -37,4 +37,4 @@ type Color = (typeof colors)[number];
|
|
|
37
37
|
declare const isColor: (value: unknown) => value is Color;
|
|
38
38
|
//#endregion
|
|
39
39
|
export { functionalColors as a, isNamedColor as c, colors as i, namedColors as l, FunctionalColor as n, isColor as o, NamedColor as r, isFunctionalColor as s, Color as t };
|
|
40
|
-
//# sourceMappingURL=index-
|
|
40
|
+
//# sourceMappingURL=index-DkMUaYsw.d.ts.map
|
|
@@ -44,4 +44,4 @@ type CssProperties = CSSProperties & Record<CssVariableName, string | number>;
|
|
|
44
44
|
declare const $cssProperties: <T extends CssProperties = CssProperties>(input: T) => CSSProperties;
|
|
45
45
|
//#endregion
|
|
46
46
|
export { parseBooleanish as i, CssProperties as n, Booleanish as r, $cssProperties as t };
|
|
47
|
-
//# sourceMappingURL=index-
|
|
47
|
+
//# sourceMappingURL=index-rtz7SwEq.d.ts.map
|
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-
|
|
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-
|
|
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-DMAkXvFI.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-
|
|
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-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\tchildren,\n\tclassName,\n\tdisabled,\n\tforwardedRef,\n\tinnerRef,\n\tstyle,\n\ttype,\n\tvalidation: _validation,\n\t...props\n}: InputContainerProps) => {\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-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 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 * 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,2 +1,2 @@
|
|
|
1
1
|
function e(e){return e!=null&&e instanceof HTMLInputElement}export{e as t};
|
|
2
|
-
//# sourceMappingURL=is-input-
|
|
2
|
+
//# sourceMappingURL=is-input-CUEWaxtA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-input-
|
|
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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
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-CAVUiqBT.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kbd-
|
|
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 * (e.g., \"K\", \"⌘\", \"⌃\"). Designed so every key—letters and modifiers—shares\n * the same visual height/width and baseline. Renders a native `<kbd>` element.\n *\n * Accessibility:\n * - When showing a symbol (⌘/⌃), provide an accessible name via `aria-label`\n * or include an sr-only label inside. The visible glyph may be marked\n * `aria-hidden`.\n *\n * @example Basic letter key\n * <Kbd>K</Kbd>\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":"6EAgBA,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.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./kbd-
|
|
1
|
+
import{t as e}from"./kbd-CAVUiqBT.js";export{e as Kbd};
|
package/dist/label.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{forwardRef as t}from"react";import{jsx as n}from"react/jsx-runtime";const r=t(({"aria-disabled":t,children:r,className:i,disabled:a,onMouseDown:o,...s},c)=>n(`label`,{"aria-disabled":a??t,className:e(`text-strong cursor-pointer text-sm peer-disabled:cursor-default has-disabled:cursor-default aria-disabled:cursor-default font-sans`,i),onMouseDown:e=>{e.target.closest(`button, input, select, textarea`)||(o?.(e),!e.defaultPrevented&&e.detail>1&&e.preventDefault())},ref:c,...s,children:r}));r.displayName=`Label`;export{r as Label};
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{forwardRef as t}from"react";import{jsx as n}from"react/jsx-runtime";const r=t(({"aria-disabled":t,children:r,className:i,disabled:a,onMouseDown:o,...s},c)=>n(`label`,{"aria-disabled":a??t,"data-slot":`label`,className:e(`text-strong cursor-pointer text-sm peer-disabled:cursor-default has-disabled:cursor-default aria-disabled:cursor-default font-sans`,i),onMouseDown:e=>{e.target.closest(`button, input, select, textarea`)||(o?.(e),!e.defaultPrevented&&e.detail>1&&e.preventDefault())},ref:c,...s,children:r}));r.displayName=`Label`;export{r as Label};
|
|
2
2
|
//# sourceMappingURL=label.js.map
|
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\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,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 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"}
|
package/dist/main.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{jsx as t}from"react/jsx-runtime";const n=({className:n,...r})=>t(`main`,{...r,id:`main`,tabIndex:-1,className:e(`focus:outline-hidden`,n)});n.displayName=`Main`;export{n as Main};
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{jsx as t}from"react/jsx-runtime";const n=({className:n,...r})=>t(`main`,{...r,"data-slot":`main`,id:`main`,tabIndex:-1,className:e(`focus:outline-hidden`,n)});n.displayName=`Main`;export{n as Main};
|
|
2
2
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","names":[],"sources":["../src/components/main/main.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A focusable `<main>` landmark for the page's primary content. Renders with\n * `id=\"main\"` and `tabIndex={-1}` so a skip link (or any programmatic focus\n * call) can send keyboard users directly to the main content without exposing\n * a visible focus ring on the region itself (`focus:outline-hidden`).\n *\n * Pair with the `<SkipToMainLink>` component at the top of the document.\n *\n * @see https://mantle.ngrok.com/components/main\n *\n * @example\n * ```tsx\n * <SkipToMainLink />\n * <Header />\n * <Main>\n * <h1>Page title</h1>\n * </Main>\n * ```\n */\nconst Main = ({ className, ...props }: ComponentProps<\"main\">) => {\n\treturn (\n\t\t<main
|
|
1
|
+
{"version":3,"file":"main.js","names":[],"sources":["../src/components/main/main.tsx"],"sourcesContent":["import type { ComponentProps } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A focusable `<main>` landmark for the page's primary content. Renders with\n * `id=\"main\"` and `tabIndex={-1}` so a skip link (or any programmatic focus\n * call) can send keyboard users directly to the main content without exposing\n * a visible focus ring on the region itself (`focus:outline-hidden`).\n *\n * Pair with the `<SkipToMainLink>` component at the top of the document.\n *\n * @see https://mantle.ngrok.com/components/main\n *\n * @example\n * ```tsx\n * <SkipToMainLink />\n * <Header />\n * <Main>\n * <h1>Page title</h1>\n * </Main>\n * ```\n */\nconst Main = ({ className, ...props }: ComponentProps<\"main\">) => {\n\treturn (\n\t\t<main\n\t\t\t{...props}\n\t\t\tdata-slot=\"main\"\n\t\t\tid=\"main\"\n\t\t\ttabIndex={-1}\n\t\t\tclassName={cx(\"focus:outline-hidden\", className)}\n\t\t/>\n\t);\n};\nMain.displayName = \"Main\";\n\nexport {\n\t//,\n\tMain,\n};\n"],"mappings":"6EAsBA,MAAM,GAAQ,CAAE,YAAW,GAAG,KAE5B,EAAC,OAAD,CACC,GAAI,EACJ,YAAU,OACV,GAAG,OACH,SAAU,GACV,UAAW,EAAG,uBAAwB,EAAU,CAC/C,CAAA,CAGJ,EAAK,YAAc"}
|
package/dist/media-object.d.ts
CHANGED
package/dist/media-object.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./slot-D_ZUrdEW.js";import{forwardRef as n}from"react";import{jsx as r}from"react/jsx-runtime";const i=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,className:e(`flex gap-4`,i),style:o,children:a}));i.displayName=`MediaObject`;const a=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,className:e(`shrink-0 leading-none`,i),style:o,children:a}));a.displayName=`MediaObjectMedia`;const o=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,className:e(`min-w-0 flex-1`,i),style:o,children:a}));o.displayName=`MediaObject.Content`;const s={Root:i,Media:a,Content:o};export{s as MediaObject};
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./slot-D_ZUrdEW.js";import{forwardRef as n}from"react";import{jsx as r}from"react/jsx-runtime";const i=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,"data-slot":`media-object`,className:e(`flex gap-4`,i),style:o,children:a}));i.displayName=`MediaObject`;const a=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,"data-slot":`media-object-media`,className:e(`shrink-0 leading-none`,i),style:o,children:a}));a.displayName=`MediaObjectMedia`;const o=n(({asChild:n=!1,className:i,children:a,style:o},s)=>r(n?t:`div`,{ref:s,"data-slot":`media-object-content`,className:e(`min-w-0 flex-1`,i),style:o,children:a}));o.displayName=`MediaObject.Content`;const s={Root:i,Media:a,Content:o};export{s as MediaObject};
|
|
2
2
|
//# sourceMappingURL=media-object.js.map
|
package/dist/media-object.js.map
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/multi-select.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as WithAsChild } from "./as-child-
|
|
2
|
-
import { o as WithValidation } from "./types-
|
|
1
|
+
import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
|
|
2
|
+
import { o as WithValidation } from "./types-DG0WQLTL.js";
|
|
3
3
|
import * as _$react from "react";
|
|
4
4
|
import { ComponentProps, ReactNode } from "react";
|
|
5
5
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
package/dist/multi-select.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-BMH0fD_b.js";import{t as n}from"./slot-D_ZUrdEW.js";import{t as r}from"./compose-refs-DFIaEnQH.js";import{n as i}from"./separator-Yk9hMn8E.js";import{t as a}from"./use-prefers-reduced-motion-BcwST13S.js";import{createContext as o,forwardRef as s,useCallback as c,useContext as l,useEffect as u,useMemo as d,useRef as f}from"react";import{Fragment as p,jsx as m,jsxs as h}from"react/jsx-runtime";import{XIcon as g}from"@phosphor-icons/react/X";import{CheckIcon as _}from"@phosphor-icons/react/Check";import*as v from"@ariakit/react";import{LockIcon as y}from"@phosphor-icons/react/Lock";const b=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`),x=[],S=o({current:null}),C=o({current:[]}),w=o({onInputKeyDownRef:{current:void 0},inputRef:{current:null}}),T=({children:e,defaultSelectedValue:t=[],...n})=>{let r=f(null),i=f(void 0),a=f(null),o=f([]),s=d(()=>({onInputKeyDownRef:i,inputRef:a}),[]);return m(S.Provider,{value:r,children:m(w.Provider,{value:s,children:m(C.Provider,{value:o,children:m(v.ComboboxProvider,{defaultSelectedValue:t,...n,children:e})})})})};T.displayName=`MultiSelect`;const E=s(({"aria-invalid":t,className:n,children:i,onKeyDown:a,onMouseDown:o,validation:s,...c},u)=>{let d=l(S),{inputRef:f}=l(w),p=v.useComboboxContext(),h=t!=null&&t!==`false`?`error`:typeof s==`function`?s():s;return m(`div`,{role:`group`,"data-slot":`multi-select-trigger`,className:e(`cursor-text select-none font-sans text-sm`,`border-form bg-form text-strong flex min-h-9 w-full flex-wrap items-center gap-1 rounded-md border px-3 py-1 has-[[data-slot=multi-select-tag]]:px-1`,`has-focus:outline-hidden has-focus-within:ring-4 has-aria-expanded:ring-4`,`has-focus-within:border-accent-600 has-focus-within:ring-focus-accent has-aria-expanded:border-accent-600 has-aria-expanded:ring-focus-accent`,`data-validation-success:border-success-600 data-validation-success:has-focus-within:border-success-600 data-validation-success:has-focus-within:ring-focus-success data-validation-success:has-aria-expanded:border-success-600 data-validation-success:has-aria-expanded:ring-focus-success`,`data-validation-warning:border-warning-600 data-validation-warning:has-focus-within:border-warning-600 data-validation-warning:has-focus-within:ring-focus-warning data-validation-warning:has-aria-expanded:border-warning-600 data-validation-warning:has-aria-expanded:ring-focus-warning`,`data-validation-error:border-danger-600 data-validation-error:has-focus-within:border-danger-600 data-validation-error:has-focus-within:ring-focus-danger data-validation-error:has-aria-expanded:border-danger-600 data-validation-error:has-aria-expanded:ring-focus-danger`,n),"data-validation":h||void 0,onKeyDown:e=>{e.key===`Escape`&&p?.getState().open&&(e.preventDefault(),p.hide()),a?.(e)},onMouseDown:e=>{e.target instanceof HTMLElement&&!e.target.closest(`button, input, [role='option']`)&&(e.preventDefault(),f.current?.focus()),o?.(e)},ref:r(d,u),...c,children:i})});E.displayName=`MultiSelectTrigger`;const D=s(({className:n,value:i,onRemove:a,locked:o=!1,onKeyDown:s,...c},l)=>{let u=f(null);return h(`span`,{ref:r(u,l),role:`option`,"aria-selected":!0,tabIndex:-1,"data-slot":`multi-select-tag`,"data-locked":o||void 0,className:e(`cursor-default bg-neutral-500/10 border border-neutral-500/20 rounded-xs text-strong inline-flex items-center gap-1 pl-2 pr-0.5 py-0.5 text-sm font-normal`,`focus-visible:outline-hidden focus-visible:border-accent-600/50 focus-visible:ring-3 focus-visible:ring-focus-accent`,n),onKeyDown:e=>{if(o&&(e.key===`Backspace`||e.key===`Delete`)){e.preventDefault(),z(e.currentTarget);return}s?.(e)},...c,children:[i,m(`button`,{type:`button`,"aria-label":`Remove ${i}`,tabIndex:-1,"aria-disabled":o||void 0,className:e(`cursor-pointer text-strong/40 hover:bg-neutral-500/15 hover:text-strong rounded-xs p-0.5`,`aria-disabled:cursor-default aria-disabled:hover:bg-transparent aria-disabled:hover:text-strong/40`),onClick:e=>{if(e.stopPropagation(),o){let e=u.current;e&&z(e);return}a?.()},onMouseDown:e=>{e.preventDefault()},children:m(t,{svg:o?m(y,{}):m(g,{weight:`bold`}),className:`size-4`})})]})});D.displayName=`MultiSelectTag`;const O=({children:e,lockedValues:t=[]})=>{let n=v.useComboboxContext(),r=v.useStoreState(n,`selectedValue`),i=(b(r)?r:void 0)??x,a=f(i);a.current=i;let o=l(C);o.current=t;let s=d(()=>new Set(t),[t]),c=f(new Map),{onInputKeyDownRef:h,inputRef:g}=l(w),_=f(new Set);u(()=>()=>{_.current.forEach(cancelAnimationFrame)},[]);let y=e=>{let t;t=requestAnimationFrame(()=>{_.current.delete(t),e()}),_.current.add(t)},S=e=>{if(n){let t=n.getState().selectedValue;if(!b(t))return;n.setSelectedValue(t.filter(t=>t!==e))}},T=e=>{let t=a.current[e];if(t==null)return;let r=c.current.get(t);r&&(r.focus(),n?.show())},E=()=>{g.current?.focus()},O=(e,t)=>{let n=i[t];switch(e.key){case`ArrowLeft`:e.preventDefault(),t>0&&T(t-1);break;case`ArrowRight`:e.preventDefault(),t<i.length-1?T(t+1):E();break;case`Backspace`:case`Delete`:if(e.preventDefault(),n!=null){if(s.has(n)){let e=c.current.get(n);e&&z(e);break}if(S(n),e.key===`Backspace`)if(t>0){let e=t-1;y(()=>T(e))}else y(()=>{a.current.length>0?T(0):E()});else y(()=>{t<a.current.length?T(t):E()})}break;case`ArrowUp`:case`ArrowDown`:e.preventDefault(),E(),g.current?.dispatchEvent(new KeyboardEvent(`keydown`,{key:e.key,bubbles:!0,cancelable:!0,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,altKey:e.altKey}));break;default:e.key.length===1&&!e.ctrlKey&&!e.metaKey&&E();break}};return h.current=e=>{if(e.key===`ArrowLeft`&&e.currentTarget.selectionStart===0&&e.currentTarget.selectionEnd===0&&i.length>0){e.preventDefault(),T(i.length-1);return}if(e.key===`Backspace`&&e.currentTarget.value===``&&i.length>0){let e=i[i.length-1];if(e!=null)if(o.current.includes(e)){let t=c.current.get(e);t&&z(t)}else S(e)}},m(p,{children:i.map((t,n)=>{let r={value:t,locked:s.has(t),onRemove:()=>{if(s.has(t)){let e=c.current.get(t);e&&z(e);return}S(t)},ref:e=>{e?c.current.set(t,e):c.current.delete(t)},onKeyDown:e=>O(e,n),onClick:()=>T(n)};return e?e(r):m(D,{...r},t)})})};O.displayName=`MultiSelectTagValues`;const k=s(({className:t,onBlur:n,onChange:i,onFocus:a,onKeyDown:o,onValueChange:s,placeholder:c,...u},d)=>{let f=v.useComboboxContext(),{onInputKeyDownRef:p,inputRef:h}=l(w),g=v.useStoreState(f,`selectedValue`),_=((b(g)?g:void 0)?.length??0)>0;return m(v.Combobox,{autoSelect:!0,"data-slot":`multi-select-input`,className:e(`pointer-coarse:text-base min-w-20 flex-1 select-text border-0 bg-transparent text-sm outline-hidden`,`placeholder:select-none placeholder:text-placeholder`,t),onChange:e=>{s?.(e.target.value),i?.(e)},onKeyDown:e=>{p.current?.(e),o?.(e)},onBlur:e=>{e.relatedTarget instanceof HTMLElement&&e.relatedTarget.closest(`[data-slot="multi-select-tag"]`)&&f?.show(),n?.(e)},onFocus:e=>{f?.show(),a?.(e)},placeholder:_?void 0:c,ref:r(h,d),...u})});k.displayName=`MultiSelectInput`;const A=s(({asChild:t=!1,backdrop:r=!1,children:i,className:a,modal:o=!0,portalElement:s,sameWidth:u=!0,unmountOnHide:d=!0,...f},p)=>{let h=l(S),g=c(()=>h.current?.getBoundingClientRect()??null,[h]),_=c(e=>typeof s==`function`?s(e):s??h.current?.closest(`[data-mantle-modal-content]`)??e.ownerDocument.body,[s,h]),y=c(e=>!(e.target instanceof Node&&h.current?.contains(e.target)),[h]);return m(v.ComboboxPopover,{"data-slot":`multi-select-content`,className:e(`border-popover bg-popover relative z-50 max-h-96 min-w-32 scrollbar overflow-y-scroll overflow-x-hidden overscroll-y-none rounded-md border shadow-md pt-1 pb-1 has-data-content-footer:pb-0 font-sans flex flex-col gap-px focus:outline-hidden`,a),backdrop:r,getAnchorRect:g,gutter:4,hideOnInteractOutside:y,modal:o,portalElement:_,ref:p,render:t?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,sameWidth:u,unmountOnHide:d,...f,children:i})});A.displayName=`MultiSelectContent`;const j=s(({asChild:r=!1,children:i,className:a,focusOnHover:o=!0,value:s,onClick:c,...u},d)=>{let f=l(C),p=s!=null&&f.current.includes(s);return h(v.ComboboxItem,{"data-slot":`multi-select-item`,className:e(`relative mx-1 cursor-pointer rounded-md pl-2 pr-8 py-1.5 text-strong text-sm font-normal flex min-w-0 items-center gap-2`,`[[role=option]+&]:mt-px`,`data-active-item:bg-active-menu-item`,`aria-disabled:opacity-50`,`aria-selected:bg-selected-menu-item aria-selected:data-active-item:bg-active-selected-menu-item`,a),focusOnHover:o,onClick:e=>{if(p){e.preventDefault();return}c?.(e)},ref:d,render:r?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,resetValueOnSelect:!0,value:s,...u,children:[i,m(v.ComboboxItemCheck,{className:`absolute right-2 flex h-3.5 w-3.5 items-center justify-center`,children:m(t,{svg:m(_,{weight:`bold`}),className:`size-4 text-accent-600`})})]})});j.displayName=`MultiSelectItem`;const M=s(({asChild:e=!1,children:t,...r},i)=>m(v.ComboboxGroup,{"data-slot":`multi-select-group`,className:`mx-1`,ref:i,render:e?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,...r,children:t}));M.displayName=`MultiSelectGroup`;const N=s(({asChild:t=!1,children:r,className:i,...a},o)=>m(v.ComboboxGroupLabel,{"data-slot":`multi-select-group-label`,className:e(`text-muted px-2 py-1 text-xs font-medium`,i),ref:o,render:t?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,...a,children:r}));N.displayName=`MultiSelectGroupLabel`;const P=s(({className:t,children:n,...r},i)=>m(`p`,{"data-slot":`multi-select-group-description`,className:e(`text-muted px-2 pb-1 text-xs`,t),ref:i,...r,children:n}));P.displayName=`MultiSelectGroupDescription`;const F=s(({className:t,...n},r)=>m(i,{"data-slot":`multi-select-separator`,ref:r,className:e(`my-1 w-auto`,t),...n}));F.displayName=`MultiSelectSeparator`;const I=s(({className:t,children:n,...r},i)=>m(`div`,{"data-slot":`multi-select-empty`,className:e(`mx-1 text-muted px-2 py-6 text-center text-sm`,t),ref:i,role:`presentation`,...r,children:n}));I.displayName=`MultiSelectEmpty`;const L=s(({className:t,children:n,...r},i)=>m(`div`,{ref:i,"data-slot":`multi-select-content-footer`,"data-content-footer":!0,className:e(`bg-popover sticky bottom-0 border-t border-popover`,t),...r,children:n}));L.displayName=`MultiSelectContentFooter`;const R={Root:T,Trigger:E,TagValues:O,Input:k,Tag:D,Content:A,ContentFooter:L,Item:j,Group:M,GroupLabel:N,GroupDescription:P,Separator:F,Empty:I};function z(e){a()||e.animate([{transform:`translateX(0)`},{transform:`translateX(-4px)`},{transform:`translateX(4px)`},{transform:`translateX(-4px)`},{transform:`translateX(4px)`},{transform:`translateX(0)`}],{duration:300,easing:`ease-in-out`})}export{R as MultiSelect};
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./icon-bWc5yC3-.js";import{t as n}from"./slot-D_ZUrdEW.js";import{t as r}from"./compose-refs-DZ3cPi47.js";import{n as i}from"./separator-DSOIrnhj.js";import{t as a}from"./use-prefers-reduced-motion-aXfsyo-k.js";import{createContext as o,forwardRef as s,useCallback as c,useContext as l,useEffect as u,useMemo as d,useRef as f}from"react";import{Fragment as p,jsx as m,jsxs as h}from"react/jsx-runtime";import{XIcon as g}from"@phosphor-icons/react/X";import{CheckIcon as _}from"@phosphor-icons/react/Check";import*as v from"@ariakit/react";import{LockIcon as y}from"@phosphor-icons/react/Lock";const b=e=>Array.isArray(e)&&e.every(e=>typeof e==`string`),x=[],S=o({current:null}),C=o({current:[]}),w=o({onInputKeyDownRef:{current:void 0},inputRef:{current:null}}),T=({children:e,defaultSelectedValue:t=[],...n})=>{let r=f(null),i=f(void 0),a=f(null),o=f([]),s=d(()=>({onInputKeyDownRef:i,inputRef:a}),[]);return m(S.Provider,{value:r,children:m(w.Provider,{value:s,children:m(C.Provider,{value:o,children:m(v.ComboboxProvider,{defaultSelectedValue:t,...n,children:e})})})})};T.displayName=`MultiSelect`;const E=s(({"aria-invalid":t,className:n,children:i,onKeyDown:a,onMouseDown:o,validation:s,...c},u)=>{let d=l(S),{inputRef:f}=l(w),p=v.useComboboxContext(),h=t!=null&&t!==`false`?`error`:typeof s==`function`?s():s;return m(`div`,{role:`group`,"data-slot":`multi-select-trigger`,className:e(`cursor-text select-none font-sans text-sm`,`border-form bg-form text-strong flex min-h-9 w-full flex-wrap items-center gap-1 rounded-md border px-3 py-1 has-[[data-slot=multi-select-tag]]:px-1`,`has-focus:outline-hidden has-focus-within:ring-4 has-aria-expanded:ring-4`,`has-focus-within:border-accent-600 has-focus-within:ring-focus-accent has-aria-expanded:border-accent-600 has-aria-expanded:ring-focus-accent`,`data-validation-success:border-success-600 data-validation-success:has-focus-within:border-success-600 data-validation-success:has-focus-within:ring-focus-success data-validation-success:has-aria-expanded:border-success-600 data-validation-success:has-aria-expanded:ring-focus-success`,`data-validation-warning:border-warning-600 data-validation-warning:has-focus-within:border-warning-600 data-validation-warning:has-focus-within:ring-focus-warning data-validation-warning:has-aria-expanded:border-warning-600 data-validation-warning:has-aria-expanded:ring-focus-warning`,`data-validation-error:border-danger-600 data-validation-error:has-focus-within:border-danger-600 data-validation-error:has-focus-within:ring-focus-danger data-validation-error:has-aria-expanded:border-danger-600 data-validation-error:has-aria-expanded:ring-focus-danger`,n),"data-validation":h||void 0,onKeyDown:e=>{e.key===`Escape`&&p?.getState().open&&(e.preventDefault(),p.hide()),a?.(e)},onMouseDown:e=>{e.target instanceof HTMLElement&&!e.target.closest(`button, input, [role='option']`)&&(e.preventDefault(),f.current?.focus()),o?.(e)},ref:r(d,u),...c,children:i})});E.displayName=`MultiSelectTrigger`;const D=s(({className:n,value:i,onRemove:a,locked:o=!1,onKeyDown:s,...c},l)=>{let u=f(null);return h(`span`,{ref:r(u,l),role:`option`,"aria-selected":!0,tabIndex:-1,"data-slot":`multi-select-tag`,"data-locked":o||void 0,className:e(`cursor-default bg-neutral-500/10 border border-neutral-500/20 rounded-xs text-strong inline-flex items-center gap-1 pl-2 pr-0.5 py-0.5 text-sm font-normal`,`focus-visible:outline-hidden focus-visible:border-accent-600/50 focus-visible:ring-3 focus-visible:ring-focus-accent`,n),onKeyDown:e=>{if(o&&(e.key===`Backspace`||e.key===`Delete`)){e.preventDefault(),z(e.currentTarget);return}s?.(e)},...c,children:[i,m(`button`,{type:`button`,"aria-label":`Remove ${i}`,tabIndex:-1,"aria-disabled":o||void 0,className:e(`cursor-pointer text-strong/40 hover:bg-neutral-500/15 hover:text-strong rounded-xs p-0.5`,`aria-disabled:cursor-default aria-disabled:hover:bg-transparent aria-disabled:hover:text-strong/40`),onClick:e=>{if(e.stopPropagation(),o){let e=u.current;e&&z(e);return}a?.()},onMouseDown:e=>{e.preventDefault()},children:m(t,{svg:o?m(y,{}):m(g,{weight:`bold`}),className:`size-4`})})]})});D.displayName=`MultiSelectTag`;const O=({children:e,lockedValues:t=[]})=>{let n=v.useComboboxContext(),r=v.useStoreState(n,`selectedValue`),i=(b(r)?r:void 0)??x,a=f(i);a.current=i;let o=l(C);o.current=t;let s=d(()=>new Set(t),[t]),c=f(new Map),{onInputKeyDownRef:h,inputRef:g}=l(w),_=f(new Set);u(()=>()=>{_.current.forEach(cancelAnimationFrame)},[]);let y=e=>{let t;t=requestAnimationFrame(()=>{_.current.delete(t),e()}),_.current.add(t)},S=e=>{if(n){let t=n.getState().selectedValue;if(!b(t))return;n.setSelectedValue(t.filter(t=>t!==e))}},T=e=>{let t=a.current[e];if(t==null)return;let r=c.current.get(t);r&&(r.focus(),n?.show())},E=()=>{g.current?.focus()},O=(e,t)=>{let n=i[t];switch(e.key){case`ArrowLeft`:e.preventDefault(),t>0&&T(t-1);break;case`ArrowRight`:e.preventDefault(),t<i.length-1?T(t+1):E();break;case`Backspace`:case`Delete`:if(e.preventDefault(),n!=null){if(s.has(n)){let e=c.current.get(n);e&&z(e);break}if(S(n),e.key===`Backspace`)if(t>0){let e=t-1;y(()=>T(e))}else y(()=>{a.current.length>0?T(0):E()});else y(()=>{t<a.current.length?T(t):E()})}break;case`ArrowUp`:case`ArrowDown`:e.preventDefault(),E(),g.current?.dispatchEvent(new KeyboardEvent(`keydown`,{key:e.key,bubbles:!0,cancelable:!0,shiftKey:e.shiftKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey,altKey:e.altKey}));break;default:e.key.length===1&&!e.ctrlKey&&!e.metaKey&&E();break}};return h.current=e=>{if(e.key===`ArrowLeft`&&e.currentTarget.selectionStart===0&&e.currentTarget.selectionEnd===0&&i.length>0){e.preventDefault(),T(i.length-1);return}if(e.key===`Backspace`&&e.currentTarget.value===``&&i.length>0){let e=i[i.length-1];if(e!=null)if(o.current.includes(e)){let t=c.current.get(e);t&&z(t)}else S(e)}},m(p,{children:i.map((t,n)=>{let r={value:t,locked:s.has(t),onRemove:()=>{if(s.has(t)){let e=c.current.get(t);e&&z(e);return}S(t)},ref:e=>{e?c.current.set(t,e):c.current.delete(t)},onKeyDown:e=>O(e,n),onClick:()=>T(n)};return e?e(r):m(D,{...r},t)})})};O.displayName=`MultiSelectTagValues`;const k=s(({className:t,onBlur:n,onChange:i,onFocus:a,onKeyDown:o,onValueChange:s,placeholder:c,...u},d)=>{let f=v.useComboboxContext(),{onInputKeyDownRef:p,inputRef:h}=l(w),g=v.useStoreState(f,`selectedValue`),_=((b(g)?g:void 0)?.length??0)>0;return m(v.Combobox,{autoSelect:!0,"data-slot":`multi-select-input`,className:e(`pointer-coarse:text-base min-w-20 flex-1 select-text border-0 bg-transparent text-sm outline-hidden`,`placeholder:select-none placeholder:text-placeholder`,t),onChange:e=>{s?.(e.target.value),i?.(e)},onKeyDown:e=>{p.current?.(e),o?.(e)},onBlur:e=>{e.relatedTarget instanceof HTMLElement&&e.relatedTarget.closest(`[data-slot="multi-select-tag"]`)&&f?.show(),n?.(e)},onFocus:e=>{f?.show(),a?.(e)},placeholder:_?void 0:c,ref:r(h,d),...u})});k.displayName=`MultiSelectInput`;const A=s(({asChild:t=!1,backdrop:r=!1,children:i,className:a,modal:o=!0,portalElement:s,sameWidth:u=!0,unmountOnHide:d=!0,...f},p)=>{let h=l(S),g=c(()=>h.current?.getBoundingClientRect()??null,[h]),_=c(e=>typeof s==`function`?s(e):s??h.current?.closest(`[data-mantle-modal-content]`)??e.ownerDocument.body,[s,h]),y=c(e=>!(e.target instanceof Node&&h.current?.contains(e.target)),[h]);return m(v.ComboboxPopover,{"data-slot":`multi-select-content`,className:e(`border-popover bg-popover relative z-50 max-h-96 min-w-32 scrollbar overflow-y-scroll overflow-x-hidden overscroll-y-none rounded-md border shadow-md pt-1 pb-1 has-data-content-footer:pb-0 font-sans flex flex-col gap-px focus:outline-hidden`,a),backdrop:r,getAnchorRect:g,gutter:4,hideOnInteractOutside:y,modal:o,portalElement:_,ref:p,render:t?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,sameWidth:u,unmountOnHide:d,...f,children:i})});A.displayName=`MultiSelectContent`;const j=s(({asChild:r=!1,children:i,className:a,focusOnHover:o=!0,value:s,onClick:c,...u},d)=>{let f=l(C),p=s!=null&&f.current.includes(s);return h(v.ComboboxItem,{"data-slot":`multi-select-item`,className:e(`relative mx-1 cursor-pointer rounded-md pl-2 pr-8 py-1.5 text-strong text-sm font-normal flex min-w-0 items-center gap-2`,`[[role=option]+&]:mt-px`,`data-active-item:bg-active-menu-item`,`aria-disabled:opacity-50`,`aria-selected:bg-selected-menu-item aria-selected:data-active-item:bg-active-selected-menu-item`,a),focusOnHover:o,onClick:e=>{if(p){e.preventDefault();return}c?.(e)},ref:d,render:r?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,resetValueOnSelect:!0,value:s,...u,children:[i,m(v.ComboboxItemCheck,{className:`absolute right-2 flex h-3.5 w-3.5 items-center justify-center`,children:m(t,{svg:m(_,{weight:`bold`}),className:`size-4 text-accent-600`})})]})});j.displayName=`MultiSelectItem`;const M=s(({asChild:e=!1,children:t,...r},i)=>m(v.ComboboxGroup,{"data-slot":`multi-select-group`,className:`mx-1`,ref:i,render:e?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,...r,children:t}));M.displayName=`MultiSelectGroup`;const N=s(({asChild:t=!1,children:r,className:i,...a},o)=>m(v.ComboboxGroupLabel,{"data-slot":`multi-select-group-label`,className:e(`text-muted px-2 py-1 text-xs font-medium`,i),ref:o,render:t?({ref:e,...t})=>m(n,{ref:e,...t}):void 0,...a,children:r}));N.displayName=`MultiSelectGroupLabel`;const P=s(({className:t,children:n,...r},i)=>m(`p`,{"data-slot":`multi-select-group-description`,className:e(`text-muted px-2 pb-1 text-xs`,t),ref:i,...r,children:n}));P.displayName=`MultiSelectGroupDescription`;const F=s(({className:t,...n},r)=>m(i,{"data-slot":`multi-select-separator`,ref:r,className:e(`my-1 w-auto`,t),...n}));F.displayName=`MultiSelectSeparator`;const I=s(({className:t,children:n,...r},i)=>m(`div`,{"data-slot":`multi-select-empty`,className:e(`mx-1 text-muted px-2 py-6 text-center text-sm`,t),ref:i,role:`presentation`,...r,children:n}));I.displayName=`MultiSelectEmpty`;const L=s(({className:t,children:n,...r},i)=>m(`div`,{ref:i,"data-slot":`multi-select-content-footer`,"data-content-footer":!0,className:e(`bg-popover sticky bottom-0 border-t border-popover`,t),...r,children:n}));L.displayName=`MultiSelectContentFooter`;const R={Root:T,Trigger:E,TagValues:O,Input:k,Tag:D,Content:A,ContentFooter:L,Item:j,Group:M,GroupLabel:N,GroupDescription:P,Separator:F,Empty:I};function z(e){a()||e.animate([{transform:`translateX(0)`},{transform:`translateX(-4px)`},{transform:`translateX(4px)`},{transform:`translateX(-4px)`},{transform:`translateX(4px)`},{transform:`translateX(0)`}],{duration:300,easing:`ease-in-out`})}export{R as MultiSelect};
|
|
2
2
|
//# sourceMappingURL=multi-select.js.map
|
package/dist/pagination.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { t as WithAsChild } from "./as-child-
|
|
2
|
-
import { t as ButtonGroup } from "./index-
|
|
3
|
-
import { t as Select } from "./select-
|
|
1
|
+
import { t as WithAsChild } from "./as-child-DQHfEmYB.js";
|
|
2
|
+
import { t as ButtonGroup } from "./index-DOJUH34Z.js";
|
|
3
|
+
import { t as Select } from "./select-BjpP51vO.js";
|
|
4
4
|
import * as _$react from "react";
|
|
5
5
|
import { ComponentProps } from "react";
|
|
6
6
|
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
package/dist/pagination.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./slot-D_ZUrdEW.js";import{t as n}from"./icon-button-
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{t}from"./slot-D_ZUrdEW.js";import{t as n}from"./icon-button-ZKN0sRIJ.js";import{t as r}from"./button-POMJ-20y.js";import{n as i}from"./separator-DSOIrnhj.js";import{t as a}from"./select-DOgdZO0Q.js";import{createContext as o,forwardRef as s,useContext as c,useEffect as l,useState as u}from"react";import d from"tiny-invariant";import{jsx as f,jsxs as p}from"react/jsx-runtime";import{CaretLeftIcon as m}from"@phosphor-icons/react/CaretLeft";import{CaretRightIcon as h}from"@phosphor-icons/react/CaretRight";const g=o(void 0),_=s(({className:t,children:n,defaultPageSize:r,...i},a)=>{let[o,s]=u(r);return f(g.Provider,{value:{defaultPageSize:r,pageSize:o,setPageSize:s},children:f(`div`,{"data-slot":`cursor-pagination`,className:e(`inline-flex items-center justify-between gap-2`,t),ref:a,...i,children:n})})});_.displayName=`CursorPagination`;const v=s(({hasNextPage:e,hasPreviousPage:t,onNextPage:a,onPreviousPage:o,...s},c)=>p(r,{"data-slot":`cursor-pagination-buttons`,appearance:`panel`,ref:c,...s,children:[f(n,{"data-slot":`cursor-pagination-previous`,appearance:`ghost`,disabled:!t,icon:f(m,{}),label:`Previous page`,onClick:o,size:`sm`,type:`button`}),f(i,{"data-slot":`cursor-pagination-separator`,orientation:`vertical`,className:`min-h-5`}),f(n,{"data-slot":`cursor-pagination-next`,appearance:`ghost`,disabled:!e,icon:f(h,{}),label:`Next page`,onClick:a,size:`sm`,type:`button`})]}));v.displayName=`CursorButtons`;const y=[5,10,20,50,100],b=s(({className:t,pageSizes:n=y,onChangePageSize:r,...i},o)=>{let s=c(g);return d(s,`CursorPageSizeSelect must be used as a child of a CursorPagination component`),d(n.includes(s.defaultPageSize),`CursorPagination.defaultPageSize must be included in CursorPageSizeSelect.pageSizes`),d(n.includes(s.pageSize),`CursorPagination.pageSize must be included in CursorPageSizeSelect.pageSizes`),p(a.Root,{defaultValue:`${s.pageSize}`,onValueChange:e=>{let t=Number.parseInt(e,10);Number.isNaN(t)&&(t=s.defaultPageSize),s.setPageSize(t),r?.(t)},children:[f(a.Trigger,{ref:o,"data-slot":`cursor-pagination-page-size-select`,className:e(`w-auto min-w-36`,t),value:s.pageSize,...i,children:f(a.Value,{})}),f(a.Content,{width:`trigger`,children:n.map(e=>p(a.Item,{value:`${e}`,children:[e,` per page`]},e))})]})});b.displayName=`CursorPageSizeSelect`;function x({asChild:n=!1,className:r,...i}){let a=c(g);return d(a,`CursorPageSizeValue must be used as a child of a CursorPagination component`),p(n?t:`span`,{"data-slot":`cursor-pagination-page-size-value`,className:e(`text-muted text-sm font-normal`,r),...i,children:[a.pageSize,` per page`]})}x.displayName=`CursorPageSizeValue`;const S={Root:_,Buttons:v,PageSizeSelect:b,PageSizeValue:x};function C({listSize:e,pageSize:t}){let[n,r]=u(1),[i,a]=u(t);l(()=>{a(t),r(1)},[t]),l(()=>{r(1)},[e]);let o=Math.ceil(e/i),s=(n-1)*i,c=n>1,d=n<o;function f(e){r(Math.max(1,Math.min(e,o)))}function p(){d&&r(e=>Math.min(e+1,o))}function m(){c&&r(e=>Math.max(e-1,1))}function h(e){a(e),r(1)}function g(){r(o)}function _(){r(1)}return{currentPage:n,goToFirstPage:_,goToLastPage:g,goToPage:f,hasNextPage:d,hasPreviousPage:c,nextPage:p,offset:s,pageSize:i,previousPage:m,setPageSize:h,totalPages:o}}function w(e,t){return e.slice(t.offset,t.offset+t.pageSize)}export{S as CursorPagination,w as getOffsetPaginatedSlice,C as useOffsetPagination};
|
|
2
2
|
//# sourceMappingURL=pagination.js.map
|
package/dist/pagination.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","names":[],"sources":["../src/components/pagination/cursor-pagination.tsx","../src/components/pagination/use-offset-pagination.tsx"],"sourcesContent":["\"use client\";\n\nimport { CaretLeftIcon } from \"@phosphor-icons/react/CaretLeft\";\nimport { CaretRightIcon } from \"@phosphor-icons/react/CaretRight\";\nimport {\n\ttype ComponentProps,\n\ttype ComponentRef,\n\tcreateContext,\n\tforwardRef,\n\tuseContext,\n\tuseState,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { ButtonGroup, IconButton } from \"../button/index.js\";\nimport { Select } from \"../select/select.js\";\nimport { Separator } from \"../separator/separator.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype CursorPaginationContextValue = {\n\t/**\n\t * The default number of items per page.\n\t */\n\tdefaultPageSize: number;\n\t/**\n\t * The current number of items per page.\n\t */\n\tpageSize: number;\n\t/**\n\t * A function to set the number of items per page.\n\t */\n\tsetPageSize: (value: number) => void;\n};\n\nconst CursorPaginationContext = createContext<CursorPaginationContextValue | undefined>(undefined);\n\ntype CursorPaginationProps = ComponentProps<\"div\"> & {\n\t/**\n\t * The default number of items per page.\n\t */\n\tdefaultPageSize: number;\n};\n\n/**\n * A pagination component for use with cursor-based pagination.\n *\n * Cursor-based pagination is a way of loading data in chunks by using a cursor\n * from the last item on the current page to know where to start the next set,\n * making sure nothing is missed or repeated. Like a linked list, but for chunks\n * of data. It doesn't let you jump to a specific page or know how many total pages\n * there are, but it's more efficient for large or real-time data sets.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationroot\n *\n * @example\n * ```tsx\n * <CursorPagination defaultPageSize={10}>\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={handleNext}\n * onPreviousPage={handlePrevious}\n * />\n * <CursorPagination.PageSizeSelect />\n * </CursorPagination>\n * ```\n */\nconst Root = forwardRef<HTMLDivElement, CursorPaginationProps>(\n\t({ className, children, defaultPageSize, ...props }, ref) => {\n\t\tconst [pageSize, setPageSize] = useState<number>(defaultPageSize);\n\n\t\treturn (\n\t\t\t<CursorPaginationContext.Provider value={{ defaultPageSize, pageSize, setPageSize }}>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cx(\"inline-flex items-center justify-between gap-2\", className)}\n\t\t\t\t\tref={ref}\n\t\t\t\t\t{...props}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</CursorPaginationContext.Provider>\n\t\t);\n\t},\n);\nRoot.displayName = \"CursorPagination\";\n\ntype CursorButtonsProps = Omit<ComponentProps<typeof ButtonGroup>, \"appearance\"> & {\n\t/**\n\t * Whether there is a next page of data to load.\n\t */\n\thasNextPage: boolean;\n\t/**\n\t * Whether there is a previous page of data to load.\n\t */\n\thasPreviousPage: boolean;\n\t/**\n\t * A callback that is called when the next page button is clicked.\n\t */\n\tonNextPage?: () => void;\n\t/**\n\t * A callback that is called when the previous page button is clicked.\n\t */\n\tonPreviousPage?: () => void;\n};\n\n/**\n * A pair of buttons for navigating between pages of data when using cursor-based pagination.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationbuttons\n *\n * @example\n * ```tsx\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={() => loadNextPage()}\n * onPreviousPage={() => loadPreviousPage()}\n * />\n * ```\n */\nconst Buttons = forwardRef<ComponentRef<typeof ButtonGroup>, CursorButtonsProps>(\n\t({ hasNextPage, hasPreviousPage, onNextPage, onPreviousPage, ...props }, ref) => {\n\t\t// TODO(cody): this _feels_ like a good spot for left and right arrow keys to navigate between pages when focused on the buttons\n\n\t\treturn (\n\t\t\t<ButtonGroup appearance=\"panel\" ref={ref} {...props}>\n\t\t\t\t<IconButton\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tdisabled={!hasPreviousPage}\n\t\t\t\t\ticon={<CaretLeftIcon />}\n\t\t\t\t\tlabel=\"Previous page\"\n\t\t\t\t\tonClick={onPreviousPage}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t/>\n\t\t\t\t<Separator orientation=\"vertical\" className=\"min-h-5\" />\n\t\t\t\t<IconButton\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tdisabled={!hasNextPage}\n\t\t\t\t\ticon={<CaretRightIcon />}\n\t\t\t\t\tlabel=\"Next page\"\n\t\t\t\t\tonClick={onNextPage}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t/>\n\t\t\t</ButtonGroup>\n\t\t);\n\t},\n);\nButtons.displayName = \"CursorButtons\";\n\nconst defaultPageSizes = [5, 10, 20, 50, 100] as const;\n\ntype CursorPageSizeSelectProps = Omit<ComponentProps<typeof Select.Trigger>, \"children\"> & {\n\t/**\n\t * A list of page sizes to choose from. The default page size must be included in this list.\n\t */\n\tpageSizes?: typeof defaultPageSizes | readonly number[];\n\t/**\n\t * A callback that is called when the page size is changed.\n\t */\n\tonChangePageSize?: (value: number) => void;\n};\n\n/**\n * A select input for changing the number of items per page when using cursor-based pagination.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizeselect\n *\n * @example\n * ```tsx\n * <CursorPagination.PageSizeSelect\n * pageSizes={[10, 20, 50, 100]}\n * onChangePageSize={(size) => console.log('Page size changed to:', size)}\n * />\n * ```\n */\nconst PageSizeSelect = forwardRef<ComponentRef<typeof Select.Trigger>, CursorPageSizeSelectProps>(\n\t({ className, pageSizes = defaultPageSizes, onChangePageSize, ...rest }, ref) => {\n\t\tconst ctx = useContext(CursorPaginationContext);\n\n\t\tinvariant(ctx, \"CursorPageSizeSelect must be used as a child of a CursorPagination component\");\n\n\t\tinvariant(\n\t\t\tpageSizes.includes(ctx.defaultPageSize),\n\t\t\t\"CursorPagination.defaultPageSize must be included in CursorPageSizeSelect.pageSizes\",\n\t\t);\n\n\t\tinvariant(\n\t\t\tpageSizes.includes(ctx.pageSize),\n\t\t\t\"CursorPagination.pageSize must be included in CursorPageSizeSelect.pageSizes\",\n\t\t);\n\n\t\treturn (\n\t\t\t<Select.Root\n\t\t\t\tdefaultValue={`${ctx.pageSize}`}\n\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\tlet newPageSize = Number.parseInt(value, 10);\n\t\t\t\t\tif (Number.isNaN(newPageSize)) {\n\t\t\t\t\t\tnewPageSize = ctx.defaultPageSize;\n\t\t\t\t\t}\n\t\t\t\t\tctx.setPageSize(newPageSize);\n\t\t\t\t\tonChangePageSize?.(newPageSize);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<Select.Trigger\n\t\t\t\t\tref={ref}\n\t\t\t\t\tclassName={cx(\"w-auto min-w-36\", className)}\n\t\t\t\t\tvalue={ctx.pageSize}\n\t\t\t\t\t{...rest}\n\t\t\t\t>\n\t\t\t\t\t<Select.Value />\n\t\t\t\t</Select.Trigger>\n\t\t\t\t<Select.Content width=\"trigger\">\n\t\t\t\t\t{pageSizes.map((size) => (\n\t\t\t\t\t\t<Select.Item key={size} value={`${size}`}>\n\t\t\t\t\t\t\t{size} per page\n\t\t\t\t\t\t</Select.Item>\n\t\t\t\t\t))}\n\t\t\t\t</Select.Content>\n\t\t\t</Select.Root>\n\t\t);\n\t},\n);\nPageSizeSelect.displayName = \"CursorPageSizeSelect\";\n\ntype CursorPageSizeValueProps = Omit<ComponentProps<\"span\">, \"children\"> & WithAsChild;\n\n/**\n * Displays the current page size when using cursor-based pagination as a read-only value.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizevalue\n *\n * @example\n * ```tsx\n * <div className=\"flex items-center gap-2\">\n * <span>Items per page:</span>\n * <CursorPagination.PageSizeValue />\n * </div>\n * ```\n */\nfunction PageSizeValue({ asChild = false, className, ...props }: CursorPageSizeValueProps) {\n\tconst ctx = useContext(CursorPaginationContext);\n\n\tinvariant(ctx, \"CursorPageSizeValue must be used as a child of a CursorPagination component\");\n\n\tconst Component = asChild ? Slot : \"span\";\n\n\treturn (\n\t\t<Component className={cx(\"text-muted text-sm font-normal\", className)} {...props}>\n\t\t\t{ctx.pageSize} per page\n\t\t</Component>\n\t);\n}\nPageSizeValue.displayName = \"CursorPageSizeValue\";\n\n/**\n * A pagination component for use with cursor-based pagination.\n *\n * Cursor-based pagination is a way of loading data in chunks by using a cursor\n * from the last item on the current page to know where to start the next set,\n * making sure nothing is missed or repeated. Like a linked list, but for chunks\n * of data. It doesn't let you jump to a specific page or know how many total pages\n * there are, but it's more efficient for large or real-time data sets.\n *\n * @see https://mantle.ngrok.com/components/pagination\n *\n * @example\n * Composition:\n * ```\n * CursorPagination.Root\n * ├── CursorPagination.PageSizeSelect\n * ├── CursorPagination.PageSizeValue\n * └── CursorPagination.Buttons\n * ```\n *\n * @example\n * ```tsx\n * <CursorPagination defaultPageSize={10}>\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={handleNext}\n * onPreviousPage={handlePrevious}\n * />\n * <CursorPagination.PageSizeSelect />\n * </CursorPagination>\n * ```\n */\nconst CursorPagination = {\n\t/**\n\t * The root container of the cursor pagination component.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.Root defaultPageSize={10}>\n\t * <CursorPagination.Buttons\n\t * hasNextPage={hasNext}\n\t * hasPreviousPage={hasPrevious}\n\t * onNextPage={handleNext}\n\t * onPreviousPage={handlePrevious}\n\t * />\n\t * <CursorPagination.PageSizeSelect />\n\t * </CursorPagination.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * A pair of buttons for navigating between pages of data when using cursor-based pagination.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationbuttons\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.Buttons\n\t * hasNextPage={hasNext}\n\t * hasPreviousPage={hasPrevious}\n\t * onNextPage={() => loadNextPage()}\n\t * onPreviousPage={() => loadPreviousPage()}\n\t * />\n\t * ```\n\t */\n\tButtons,\n\t/**\n\t * A select input for changing the number of items per page when using cursor-based pagination.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizeselect\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.PageSizeSelect\n\t * pageSizes={[10, 20, 50, 100]}\n\t * onChangePageSize={(size) => console.log('Page size changed to:', size)}\n\t * />\n\t * ```\n\t */\n\tPageSizeSelect,\n\t/**\n\t * Displays the current page size when using cursor-based pagination as a read-only value.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizevalue\n\t *\n\t * @example\n\t * ```tsx\n\t * <div className=\"flex items-center gap-2\">\n\t * <span>Items per page:</span>\n\t * <CursorPagination.PageSizeValue />\n\t * </div>\n\t * ```\n\t */\n\tPageSizeValue,\n} as const;\n\nexport {\n\t//,\n\tCursorPagination,\n};\n\nexport type {\n\t//,\n\tCursorButtonsProps,\n\tCursorPageSizeSelectProps,\n\tCursorPageSizeValueProps,\n\tCursorPaginationProps,\n};\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\ntype UseOffsetPaginationProps = {\n\t/**\n\t * The total number of items in the list to be paginated.\n\t */\n\tlistSize: number;\n\t/**\n\t * The number of items per page.\n\t */\n\tpageSize: number;\n};\n\ntype OffsetPaginationState = {\n\t/**\n\t * The current page number, 1-indexed (starting at 1).\n\t */\n\tcurrentPage: number;\n\t/**\n\t * Whether there is a previous page.\n\t */\n\thasPreviousPage: boolean;\n\t/**\n\t * Whether there is a next page.\n\t */\n\thasNextPage: boolean;\n\t/**\n\t * Go to a specific page.\n\t */\n\tgoToPage: (page: number) => void;\n\t/**\n\t * Go to the first page.\n\t */\n\tgoToFirstPage: () => void;\n\t/**\n\t * Go to the last page.\n\t */\n\tgoToLastPage: () => void;\n\t/**\n\t * Go to the next page.\n\t */\n\tnextPage: () => void;\n\t/**\n\t * The offset of the current page in the list.\n\t */\n\toffset: number;\n\t/**\n\t * The number of items per page.\n\t */\n\tpageSize: number;\n\t/**\n\t * Go to the previous page.\n\t */\n\tpreviousPage: () => void;\n\t/**\n\t * Set the number of items per page. This will reset the current page to the first page.\n\t */\n\tsetPageSize: (size: number) => void;\n\t/**\n\t * The total number of pages.\n\t */\n\ttotalPages: number;\n};\n\n/**\n * A headless hook for managing offset-based pagination state\n *\n * @example\n * ```tsx\n * const pagination = useOffsetPagination({\n * listSize: 150,\n * pageSize: 10\n * });\n *\n * return (\n * <div>\n * <p>Page {pagination.currentPage} of {pagination.totalPages}</p>\n * <button onClick={pagination.previousPage} disabled={!pagination.hasPreviousPage}>\n * Previous\n * </button>\n * <button onClick={pagination.nextPage} disabled={!pagination.hasNextPage}>\n * Next\n * </button>\n * </div>\n * );\n * ```\n */\nfunction useOffsetPagination({\n\tlistSize,\n\tpageSize,\n}: UseOffsetPaginationProps): OffsetPaginationState {\n\tconst [currentPage, setCurrentPage] = useState(1);\n\tconst [currentPageSize, setCurrentPageSize] = useState(pageSize);\n\n\t// Reset the current page to 1 when the page size prop changes\n\tuseEffect(() => {\n\t\tsetCurrentPageSize(pageSize);\n\t\tsetCurrentPage(1);\n\t}, [pageSize]);\n\n\t// Reset the current page to 1 when the list size prop changes\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: when the listSize prop changes, we want to reset the current page to the start\n\tuseEffect(() => {\n\t\tsetCurrentPage(1);\n\t}, [listSize]);\n\n\tconst totalPages = Math.ceil(listSize / currentPageSize);\n\tconst offset = (currentPage - 1) * currentPageSize;\n\n\tconst hasPreviousPage = currentPage > 1;\n\tconst hasNextPage = currentPage < totalPages;\n\n\tfunction goToPage(page: number) {\n\t\tconst clampedPage = Math.max(1, Math.min(page, totalPages));\n\t\tsetCurrentPage(clampedPage);\n\t}\n\n\tfunction nextPage() {\n\t\tif (hasNextPage) {\n\t\t\tsetCurrentPage((prev) => Math.min(prev + 1, totalPages));\n\t\t}\n\t}\n\n\tfunction previousPage() {\n\t\tif (hasPreviousPage) {\n\t\t\tsetCurrentPage((prev) => Math.max(prev - 1, 1));\n\t\t}\n\t}\n\n\tfunction setPageSize(size: number) {\n\t\tsetCurrentPageSize(size);\n\t\tsetCurrentPage(1); // reset to the first page when page size changes\n\t}\n\n\tfunction goToLastPage() {\n\t\tsetCurrentPage(totalPages);\n\t}\n\n\tfunction goToFirstPage() {\n\t\tsetCurrentPage(1);\n\t}\n\n\treturn {\n\t\tcurrentPage,\n\t\tgoToFirstPage,\n\t\tgoToLastPage,\n\t\tgoToPage,\n\t\thasNextPage,\n\t\thasPreviousPage,\n\t\tnextPage,\n\t\toffset,\n\t\tpageSize: currentPageSize,\n\t\tpreviousPage,\n\t\tsetPageSize,\n\t\ttotalPages,\n\t};\n}\n\n/**\n * Get a paginated slice of a list based on the current offset pagination state.\n *\n * @example\n * ```tsx\n * const data = ['a', 'b', 'c', 'd', 'e', 'f'];\n * const pagination = useOffsetPagination({ listSize: data.length, pageSize: 2 });\n * const currentPageData = getOffsetPaginatedSlice(data, pagination);\n * // Returns: ['a', 'b'] for page 1, ['c', 'd'] for page 2, etc.\n * ```\n */\nfunction getOffsetPaginatedSlice<T>(list: readonly T[], pagination: OffsetPaginationState): T[] {\n\treturn list.slice(pagination.offset, pagination.offset + pagination.pageSize);\n}\n\nexport {\n\t//,\n\tgetOffsetPaginatedSlice,\n\tuseOffsetPagination,\n};\n\nexport type {\n\t//,\n\tOffsetPaginationState,\n\tUseOffsetPaginationProps,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pagination.js","names":[],"sources":["../src/components/pagination/cursor-pagination.tsx","../src/components/pagination/use-offset-pagination.tsx"],"sourcesContent":["\"use client\";\n\nimport { CaretLeftIcon } from \"@phosphor-icons/react/CaretLeft\";\nimport { CaretRightIcon } from \"@phosphor-icons/react/CaretRight\";\nimport {\n\ttype ComponentProps,\n\ttype ComponentRef,\n\tcreateContext,\n\tforwardRef,\n\tuseContext,\n\tuseState,\n} from \"react\";\nimport invariant from \"tiny-invariant\";\nimport type { WithAsChild } from \"../../types/as-child.js\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { ButtonGroup, IconButton } from \"../button/index.js\";\nimport { Select } from \"../select/select.js\";\nimport { Separator } from \"../separator/separator.js\";\nimport { Slot } from \"../slot/index.js\";\n\ntype CursorPaginationContextValue = {\n\t/**\n\t * The default number of items per page.\n\t */\n\tdefaultPageSize: number;\n\t/**\n\t * The current number of items per page.\n\t */\n\tpageSize: number;\n\t/**\n\t * A function to set the number of items per page.\n\t */\n\tsetPageSize: (value: number) => void;\n};\n\nconst CursorPaginationContext = createContext<CursorPaginationContextValue | undefined>(undefined);\n\ntype CursorPaginationProps = ComponentProps<\"div\"> & {\n\t/**\n\t * The default number of items per page.\n\t */\n\tdefaultPageSize: number;\n};\n\n/**\n * A pagination component for use with cursor-based pagination.\n *\n * Cursor-based pagination is a way of loading data in chunks by using a cursor\n * from the last item on the current page to know where to start the next set,\n * making sure nothing is missed or repeated. Like a linked list, but for chunks\n * of data. It doesn't let you jump to a specific page or know how many total pages\n * there are, but it's more efficient for large or real-time data sets.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationroot\n *\n * @example\n * ```tsx\n * <CursorPagination defaultPageSize={10}>\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={handleNext}\n * onPreviousPage={handlePrevious}\n * />\n * <CursorPagination.PageSizeSelect />\n * </CursorPagination>\n * ```\n */\nconst Root = forwardRef<HTMLDivElement, CursorPaginationProps>(\n\t({ className, children, defaultPageSize, ...props }, ref) => {\n\t\tconst [pageSize, setPageSize] = useState<number>(defaultPageSize);\n\n\t\treturn (\n\t\t\t<CursorPaginationContext.Provider value={{ defaultPageSize, pageSize, setPageSize }}>\n\t\t\t\t<div\n\t\t\t\t\tdata-slot=\"cursor-pagination\"\n\t\t\t\t\tclassName={cx(\"inline-flex items-center justify-between gap-2\", className)}\n\t\t\t\t\tref={ref}\n\t\t\t\t\t{...props}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</CursorPaginationContext.Provider>\n\t\t);\n\t},\n);\nRoot.displayName = \"CursorPagination\";\n\ntype CursorButtonsProps = Omit<ComponentProps<typeof ButtonGroup>, \"appearance\"> & {\n\t/**\n\t * Whether there is a next page of data to load.\n\t */\n\thasNextPage: boolean;\n\t/**\n\t * Whether there is a previous page of data to load.\n\t */\n\thasPreviousPage: boolean;\n\t/**\n\t * A callback that is called when the next page button is clicked.\n\t */\n\tonNextPage?: () => void;\n\t/**\n\t * A callback that is called when the previous page button is clicked.\n\t */\n\tonPreviousPage?: () => void;\n};\n\n/**\n * A pair of buttons for navigating between pages of data when using cursor-based pagination.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationbuttons\n *\n * @example\n * ```tsx\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={() => loadNextPage()}\n * onPreviousPage={() => loadPreviousPage()}\n * />\n * ```\n */\nconst Buttons = forwardRef<ComponentRef<typeof ButtonGroup>, CursorButtonsProps>(\n\t({ hasNextPage, hasPreviousPage, onNextPage, onPreviousPage, ...props }, ref) => {\n\t\t// TODO(cody): this _feels_ like a good spot for left and right arrow keys to navigate between pages when focused on the buttons\n\n\t\treturn (\n\t\t\t<ButtonGroup data-slot=\"cursor-pagination-buttons\" appearance=\"panel\" ref={ref} {...props}>\n\t\t\t\t<IconButton\n\t\t\t\t\tdata-slot=\"cursor-pagination-previous\"\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tdisabled={!hasPreviousPage}\n\t\t\t\t\ticon={<CaretLeftIcon />}\n\t\t\t\t\tlabel=\"Previous page\"\n\t\t\t\t\tonClick={onPreviousPage}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t/>\n\t\t\t\t<Separator\n\t\t\t\t\tdata-slot=\"cursor-pagination-separator\"\n\t\t\t\t\torientation=\"vertical\"\n\t\t\t\t\tclassName=\"min-h-5\"\n\t\t\t\t/>\n\t\t\t\t<IconButton\n\t\t\t\t\tdata-slot=\"cursor-pagination-next\"\n\t\t\t\t\tappearance=\"ghost\"\n\t\t\t\t\tdisabled={!hasNextPage}\n\t\t\t\t\ticon={<CaretRightIcon />}\n\t\t\t\t\tlabel=\"Next page\"\n\t\t\t\t\tonClick={onNextPage}\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t/>\n\t\t\t</ButtonGroup>\n\t\t);\n\t},\n);\nButtons.displayName = \"CursorButtons\";\n\nconst defaultPageSizes = [5, 10, 20, 50, 100] as const;\n\ntype CursorPageSizeSelectProps = Omit<ComponentProps<typeof Select.Trigger>, \"children\"> & {\n\t/**\n\t * A list of page sizes to choose from. The default page size must be included in this list.\n\t */\n\tpageSizes?: typeof defaultPageSizes | readonly number[];\n\t/**\n\t * A callback that is called when the page size is changed.\n\t */\n\tonChangePageSize?: (value: number) => void;\n};\n\n/**\n * A select input for changing the number of items per page when using cursor-based pagination.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizeselect\n *\n * @example\n * ```tsx\n * <CursorPagination.PageSizeSelect\n * pageSizes={[10, 20, 50, 100]}\n * onChangePageSize={(size) => console.log('Page size changed to:', size)}\n * />\n * ```\n */\nconst PageSizeSelect = forwardRef<ComponentRef<typeof Select.Trigger>, CursorPageSizeSelectProps>(\n\t({ className, pageSizes = defaultPageSizes, onChangePageSize, ...rest }, ref) => {\n\t\tconst ctx = useContext(CursorPaginationContext);\n\n\t\tinvariant(ctx, \"CursorPageSizeSelect must be used as a child of a CursorPagination component\");\n\n\t\tinvariant(\n\t\t\tpageSizes.includes(ctx.defaultPageSize),\n\t\t\t\"CursorPagination.defaultPageSize must be included in CursorPageSizeSelect.pageSizes\",\n\t\t);\n\n\t\tinvariant(\n\t\t\tpageSizes.includes(ctx.pageSize),\n\t\t\t\"CursorPagination.pageSize must be included in CursorPageSizeSelect.pageSizes\",\n\t\t);\n\n\t\treturn (\n\t\t\t<Select.Root\n\t\t\t\tdefaultValue={`${ctx.pageSize}`}\n\t\t\t\tonValueChange={(value) => {\n\t\t\t\t\tlet newPageSize = Number.parseInt(value, 10);\n\t\t\t\t\tif (Number.isNaN(newPageSize)) {\n\t\t\t\t\t\tnewPageSize = ctx.defaultPageSize;\n\t\t\t\t\t}\n\t\t\t\t\tctx.setPageSize(newPageSize);\n\t\t\t\t\tonChangePageSize?.(newPageSize);\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<Select.Trigger\n\t\t\t\t\tref={ref}\n\t\t\t\t\tdata-slot=\"cursor-pagination-page-size-select\"\n\t\t\t\t\tclassName={cx(\"w-auto min-w-36\", className)}\n\t\t\t\t\tvalue={ctx.pageSize}\n\t\t\t\t\t{...rest}\n\t\t\t\t>\n\t\t\t\t\t<Select.Value />\n\t\t\t\t</Select.Trigger>\n\t\t\t\t<Select.Content width=\"trigger\">\n\t\t\t\t\t{pageSizes.map((size) => (\n\t\t\t\t\t\t<Select.Item key={size} value={`${size}`}>\n\t\t\t\t\t\t\t{size} per page\n\t\t\t\t\t\t</Select.Item>\n\t\t\t\t\t))}\n\t\t\t\t</Select.Content>\n\t\t\t</Select.Root>\n\t\t);\n\t},\n);\nPageSizeSelect.displayName = \"CursorPageSizeSelect\";\n\ntype CursorPageSizeValueProps = Omit<ComponentProps<\"span\">, \"children\"> & WithAsChild;\n\n/**\n * Displays the current page size when using cursor-based pagination as a read-only value.\n *\n * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizevalue\n *\n * @example\n * ```tsx\n * <div className=\"flex items-center gap-2\">\n * <span>Items per page:</span>\n * <CursorPagination.PageSizeValue />\n * </div>\n * ```\n */\nfunction PageSizeValue({ asChild = false, className, ...props }: CursorPageSizeValueProps) {\n\tconst ctx = useContext(CursorPaginationContext);\n\n\tinvariant(ctx, \"CursorPageSizeValue must be used as a child of a CursorPagination component\");\n\n\tconst Component = asChild ? Slot : \"span\";\n\n\treturn (\n\t\t<Component\n\t\t\tdata-slot=\"cursor-pagination-page-size-value\"\n\t\t\tclassName={cx(\"text-muted text-sm font-normal\", className)}\n\t\t\t{...props}\n\t\t>\n\t\t\t{ctx.pageSize} per page\n\t\t</Component>\n\t);\n}\nPageSizeValue.displayName = \"CursorPageSizeValue\";\n\n/**\n * A pagination component for use with cursor-based pagination.\n *\n * Cursor-based pagination is a way of loading data in chunks by using a cursor\n * from the last item on the current page to know where to start the next set,\n * making sure nothing is missed or repeated. Like a linked list, but for chunks\n * of data. It doesn't let you jump to a specific page or know how many total pages\n * there are, but it's more efficient for large or real-time data sets.\n *\n * @see https://mantle.ngrok.com/components/pagination\n *\n * @example\n * Composition:\n * ```\n * CursorPagination.Root\n * ├── CursorPagination.PageSizeSelect\n * ├── CursorPagination.PageSizeValue\n * └── CursorPagination.Buttons\n * ```\n *\n * @example\n * ```tsx\n * <CursorPagination defaultPageSize={10}>\n * <CursorPagination.Buttons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={handleNext}\n * onPreviousPage={handlePrevious}\n * />\n * <CursorPagination.PageSizeSelect />\n * </CursorPagination>\n * ```\n */\nconst CursorPagination = {\n\t/**\n\t * The root container of the cursor pagination component.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.Root defaultPageSize={10}>\n\t * <CursorPagination.Buttons\n\t * hasNextPage={hasNext}\n\t * hasPreviousPage={hasPrevious}\n\t * onNextPage={handleNext}\n\t * onPreviousPage={handlePrevious}\n\t * />\n\t * <CursorPagination.PageSizeSelect />\n\t * </CursorPagination.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * A pair of buttons for navigating between pages of data when using cursor-based pagination.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationbuttons\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.Buttons\n\t * hasNextPage={hasNext}\n\t * hasPreviousPage={hasPrevious}\n\t * onNextPage={() => loadNextPage()}\n\t * onPreviousPage={() => loadPreviousPage()}\n\t * />\n\t * ```\n\t */\n\tButtons,\n\t/**\n\t * A select input for changing the number of items per page when using cursor-based pagination.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizeselect\n\t *\n\t * @example\n\t * ```tsx\n\t * <CursorPagination.PageSizeSelect\n\t * pageSizes={[10, 20, 50, 100]}\n\t * onChangePageSize={(size) => console.log('Page size changed to:', size)}\n\t * />\n\t * ```\n\t */\n\tPageSizeSelect,\n\t/**\n\t * Displays the current page size when using cursor-based pagination as a read-only value.\n\t *\n\t * @see https://mantle.ngrok.com/components/pagination#cursorpaginationpagesizevalue\n\t *\n\t * @example\n\t * ```tsx\n\t * <div className=\"flex items-center gap-2\">\n\t * <span>Items per page:</span>\n\t * <CursorPagination.PageSizeValue />\n\t * </div>\n\t * ```\n\t */\n\tPageSizeValue,\n} as const;\n\nexport {\n\t//,\n\tCursorPagination,\n};\n\nexport type {\n\t//,\n\tCursorButtonsProps,\n\tCursorPageSizeSelectProps,\n\tCursorPageSizeValueProps,\n\tCursorPaginationProps,\n};\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\n\ntype UseOffsetPaginationProps = {\n\t/**\n\t * The total number of items in the list to be paginated.\n\t */\n\tlistSize: number;\n\t/**\n\t * The number of items per page.\n\t */\n\tpageSize: number;\n};\n\ntype OffsetPaginationState = {\n\t/**\n\t * The current page number, 1-indexed (starting at 1).\n\t */\n\tcurrentPage: number;\n\t/**\n\t * Whether there is a previous page.\n\t */\n\thasPreviousPage: boolean;\n\t/**\n\t * Whether there is a next page.\n\t */\n\thasNextPage: boolean;\n\t/**\n\t * Go to a specific page.\n\t */\n\tgoToPage: (page: number) => void;\n\t/**\n\t * Go to the first page.\n\t */\n\tgoToFirstPage: () => void;\n\t/**\n\t * Go to the last page.\n\t */\n\tgoToLastPage: () => void;\n\t/**\n\t * Go to the next page.\n\t */\n\tnextPage: () => void;\n\t/**\n\t * The offset of the current page in the list.\n\t */\n\toffset: number;\n\t/**\n\t * The number of items per page.\n\t */\n\tpageSize: number;\n\t/**\n\t * Go to the previous page.\n\t */\n\tpreviousPage: () => void;\n\t/**\n\t * Set the number of items per page. This will reset the current page to the first page.\n\t */\n\tsetPageSize: (size: number) => void;\n\t/**\n\t * The total number of pages.\n\t */\n\ttotalPages: number;\n};\n\n/**\n * A headless hook for managing offset-based pagination state\n *\n * @example\n * ```tsx\n * const pagination = useOffsetPagination({\n * listSize: 150,\n * pageSize: 10\n * });\n *\n * return (\n * <div>\n * <p>Page {pagination.currentPage} of {pagination.totalPages}</p>\n * <button onClick={pagination.previousPage} disabled={!pagination.hasPreviousPage}>\n * Previous\n * </button>\n * <button onClick={pagination.nextPage} disabled={!pagination.hasNextPage}>\n * Next\n * </button>\n * </div>\n * );\n * ```\n */\nfunction useOffsetPagination({\n\tlistSize,\n\tpageSize,\n}: UseOffsetPaginationProps): OffsetPaginationState {\n\tconst [currentPage, setCurrentPage] = useState(1);\n\tconst [currentPageSize, setCurrentPageSize] = useState(pageSize);\n\n\t// Reset the current page to 1 when the page size prop changes\n\tuseEffect(() => {\n\t\tsetCurrentPageSize(pageSize);\n\t\tsetCurrentPage(1);\n\t}, [pageSize]);\n\n\t// Reset the current page to 1 when the list size prop changes\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: when the listSize prop changes, we want to reset the current page to the start\n\tuseEffect(() => {\n\t\tsetCurrentPage(1);\n\t}, [listSize]);\n\n\tconst totalPages = Math.ceil(listSize / currentPageSize);\n\tconst offset = (currentPage - 1) * currentPageSize;\n\n\tconst hasPreviousPage = currentPage > 1;\n\tconst hasNextPage = currentPage < totalPages;\n\n\tfunction goToPage(page: number) {\n\t\tconst clampedPage = Math.max(1, Math.min(page, totalPages));\n\t\tsetCurrentPage(clampedPage);\n\t}\n\n\tfunction nextPage() {\n\t\tif (hasNextPage) {\n\t\t\tsetCurrentPage((prev) => Math.min(prev + 1, totalPages));\n\t\t}\n\t}\n\n\tfunction previousPage() {\n\t\tif (hasPreviousPage) {\n\t\t\tsetCurrentPage((prev) => Math.max(prev - 1, 1));\n\t\t}\n\t}\n\n\tfunction setPageSize(size: number) {\n\t\tsetCurrentPageSize(size);\n\t\tsetCurrentPage(1); // reset to the first page when page size changes\n\t}\n\n\tfunction goToLastPage() {\n\t\tsetCurrentPage(totalPages);\n\t}\n\n\tfunction goToFirstPage() {\n\t\tsetCurrentPage(1);\n\t}\n\n\treturn {\n\t\tcurrentPage,\n\t\tgoToFirstPage,\n\t\tgoToLastPage,\n\t\tgoToPage,\n\t\thasNextPage,\n\t\thasPreviousPage,\n\t\tnextPage,\n\t\toffset,\n\t\tpageSize: currentPageSize,\n\t\tpreviousPage,\n\t\tsetPageSize,\n\t\ttotalPages,\n\t};\n}\n\n/**\n * Get a paginated slice of a list based on the current offset pagination state.\n *\n * @example\n * ```tsx\n * const data = ['a', 'b', 'c', 'd', 'e', 'f'];\n * const pagination = useOffsetPagination({ listSize: data.length, pageSize: 2 });\n * const currentPageData = getOffsetPaginatedSlice(data, pagination);\n * // Returns: ['a', 'b'] for page 1, ['c', 'd'] for page 2, etc.\n * ```\n */\nfunction getOffsetPaginatedSlice<T>(list: readonly T[], pagination: OffsetPaginationState): T[] {\n\treturn list.slice(pagination.offset, pagination.offset + pagination.pageSize);\n}\n\nexport {\n\t//,\n\tgetOffsetPaginatedSlice,\n\tuseOffsetPagination,\n};\n\nexport type {\n\t//,\n\tOffsetPaginationState,\n\tUseOffsetPaginationProps,\n};\n"],"mappings":"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"}
|
package/dist/popover.d.ts
CHANGED
|
@@ -5,7 +5,19 @@ import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
|
5
5
|
/**
|
|
6
6
|
* A floating overlay that displays rich content in a portal, triggered by a button.
|
|
7
7
|
*
|
|
8
|
+
* `Popover` is a non-modal dialog by default: focus moves into the content
|
|
9
|
+
* when it opens, `Escape` closes and returns focus to the trigger, clicking
|
|
10
|
+
* outside dismisses, and the page (body and any scroll containers) continues
|
|
11
|
+
* to scroll normally. Pass `modal` on `Popover.Root` to trap focus inside
|
|
12
|
+
* the content, block interaction with the rest of the page, and lock body
|
|
13
|
+
* scroll while the popover is open. Use a `Popover` when the floating
|
|
14
|
+
* content must be interactive — forms, action menus, filters, settings.
|
|
15
|
+
* Prefer `Tooltip` for short, non-interactive labels on controls, or
|
|
16
|
+
* `HoverCard` for a sighted-only preview of content that already lives
|
|
17
|
+
* behind a link.
|
|
18
|
+
*
|
|
8
19
|
* @see https://mantle.ngrok.com/components/popover
|
|
20
|
+
* @see https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
|
|
9
21
|
*
|
|
10
22
|
* @example
|
|
11
23
|
* Composition:
|
package/dist/popover.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./cx-D1HYnpvA.js";import{forwardRef as t}from"react";import{jsx as n}from"react/jsx-runtime";import*as r from"@radix-ui/react-popover";const i=r.Root;i.displayName=`Popover`;const a=r.Trigger;a.displayName=`PopoverTrigger`;const o=r.Anchor;o.displayName=`PopoverAnchor`;const s=r.Close;s.displayName=`PopoverClose`;const c=t(({align:t=`center`,className:i,onClick:a,preferredWidth:o=`max-w-72`,sideOffset:s=4,...c},l)=>n(r.Portal,{children:n(r.Content,{align:t,className:e(`text-popover-foreground border-popover bg-popover data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 z-50 rounded-md border p-4 shadow-md outline-hidden`,o,i),onClick:e=>{e.stopPropagation(),a?.(e)},ref:l,sideOffset:s,...c})}));c.displayName=`PopoverContent`;const l={Root:i,Anchor:o,Close:s,Content:c,Trigger:a};export{l as Popover};
|
|
1
|
+
import{t as e}from"./cx-D1HYnpvA.js";import{forwardRef as t}from"react";import{jsx as n}from"react/jsx-runtime";import*as r from"@radix-ui/react-popover";const i=r.Root;i.displayName=`Popover`;const a=r.Trigger;a.displayName=`PopoverTrigger`;const o=r.Anchor;o.displayName=`PopoverAnchor`;const s=r.Close;s.displayName=`PopoverClose`;const c=t(({align:t=`center`,className:i,onClick:a,preferredWidth:o=`max-w-72`,sideOffset:s=4,...c},l)=>n(r.Portal,{children:n(r.Content,{align:t,"data-slot":`popover-content`,className:e(`text-popover-foreground border-popover bg-popover data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 z-50 rounded-md border p-4 shadow-md outline-hidden`,o,i),onClick:e=>{e.stopPropagation(),a?.(e)},ref:l,sideOffset:s,...c})}));c.displayName=`PopoverContent`;const l={Root:i,Anchor:o,Close:s,Content:c,Trigger:a};export{l as Popover};
|
|
2
2
|
//# sourceMappingURL=popover.js.map
|
package/dist/popover.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.js","names":[],"sources":["../src/components/popover/popover.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A floating overlay that displays rich content in a portal, triggered by a button.\n * This is the root, stateful component that manages the open/closed state of the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popoverroot\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Root = PopoverPrimitive.Root;\nRoot.displayName = \"Popover\";\n\n/**\n * The trigger button that opens the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popovertrigger\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Trigger = PopoverPrimitive.Trigger;\nTrigger.displayName = \"PopoverTrigger\";\n\n/**\n * An optional element to position the PopoverContent against. If this part is not used, the content will position alongside the PopoverTrigger.\n *\n * @see https://mantle.ngrok.com/components/popover#popoveranchor\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Anchor asChild>\n * <div>Anchor element</div>\n * </Popover.Anchor>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Anchor = PopoverPrimitive.Anchor;\nAnchor.displayName = \"PopoverAnchor\";\n\n/**\n * A button that closes an open popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popoverclose\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * <Popover.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Popover.Close>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Close = PopoverPrimitive.Close;\nClose.displayName = \"PopoverClose\";\n\ntype PopoverContentProps = ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> & {\n\t/**\n\t * The preferred width of the `PopoverContent` as a tailwind `max-w-` class.\n\t *\n\t * By default, a `Popover`'s content width is responsive with a default\n\t * preferred width: the maximum width of the `PopoverContent`\n\t *\n\t * @default `max-w-72`\n\t */\n\tpreferredWidth?: `max-w-${string}`;\n};\n\n/**\n * The content to render inside the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popovercontent\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Content = forwardRef<ComponentRef<\"div\">, PopoverContentProps>(\n\t(\n\t\t{\n\t\t\t//,\n\t\t\talign = \"center\",\n\t\t\tclassName,\n\t\t\tonClick,\n\t\t\tpreferredWidth = \"max-w-72\",\n\t\t\tsideOffset = 4,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<PopoverPrimitive.Portal>\n\t\t\t<PopoverPrimitive.Content\n\t\t\t\talign={align}\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-popover-foreground border-popover bg-popover data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 z-50 rounded-md border p-4 shadow-md outline-hidden\",\n\t\t\t\t\tpreferredWidth,\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Prevent the click event from propagating up to parent/containing elements\n\t\t\t\t\t * of the PopoverContent\n\t\t\t\t\t */\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t}}\n\t\t\t\tref={ref}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</PopoverPrimitive.Portal>\n\t),\n);\nContent.displayName = \"PopoverContent\";\n\n/**\n * A floating overlay that displays rich content in a portal, triggered by a button.\n *\n * @see https://mantle.ngrok.com/components/popover\n *\n * @example\n * Composition:\n * ```\n * Popover.Root\n * ├── Popover.Trigger\n * ├── Popover.Anchor\n * └── Popover.Content\n * └── Popover.Close\n * ```\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Popover = {\n\t/**\n\t * The root, stateful component that manages the open/closed state of the popover.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoverroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button>Open popover</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <p>This is the popover content.</p>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * An optional element to position the PopoverContent against. If not used, content positions alongside the trigger.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoveranchor\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Anchor asChild>\n\t * <div>Position relative to this element</div>\n\t * </Popover.Anchor>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Popover</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <p>This popover is positioned relative to the anchor.</p>\n\t * <Popover.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Popover.Close>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tAnchor,\n\t/**\n\t * A button that closes an open popover. Can be placed anywhere within the popover content.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoverclose\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\">Settings</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <div className=\"flex items-center justify-between\">\n\t * <Text>Settings Panel</Text>\n\t * <Popover.Close asChild>\n\t * <Button type=\"button\" appearance=\"ghost\" size=\"sm\">✕</Button>\n\t * </Popover.Close>\n\t * </div>\n\t * <Text>Configure your preferences here.</Text>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tClose,\n\t/**\n\t * The content to render inside the popover. Appears in a portal with rich styling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popovercontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\">Show Info</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content side=\"top\" align=\"center\">\n\t * <div className=\"space-y-2\">\n\t * <Text weight=\"strong\">Additional Information</Text>\n\t * <Text>This is the content inside the popover.</Text>\n\t * <Button type=\"button\" size=\"sm\">Action</Button>\n\t * </div>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * The trigger button that opens the popover when clicked or focused.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popovertrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">\n\t * Options\n\t * </Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <div className=\"space-y-2\">\n\t * <Button type=\"button\" variant=\"ghost\">Edit</Button>\n\t * <Button type=\"button\" variant=\"ghost\">Delete</Button>\n\t * </div>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tPopover,\n};\n"],"mappings":"0JAyBA,MAAM,EAAO,EAAiB,KAC9B,EAAK,YAAc,UAqBnB,MAAM,EAAU,EAAiB,QACjC,EAAQ,YAAc,iBAwBtB,MAAM,EAAS,EAAiB,OAChC,EAAO,YAAc,gBAwBrB,MAAM,EAAQ,EAAiB,MAC/B,EAAM,YAAc,eAiCpB,MAAM,EAAU,GAEd,CAEC,QAAQ,SACR,YACA,UACA,iBAAiB,WACjB,aAAa,EACb,GAAG,GAEJ,IAEA,EAAC,EAAiB,OAAlB,CAAA,SACC,EAAC,EAAiB,QAAlB,CACQ,QACP,UAAW,EACV,qaACA,EACA,EACA,CACD,QAAU,GAAU,CAKnB,EAAM,iBAAiB,CACvB,IAAU,EAAM,EAEZ,MACO,aACZ,GAAI,EACH,CAAA,CACuB,CAAA,CAE3B,CACD,EAAQ,YAAc,iBA+BtB,MAAM,EAAU,CAkBf,OAwBA,SAwBA,QAsBA,UAuBA,UACA"}
|
|
1
|
+
{"version":3,"file":"popover.js","names":[],"sources":["../src/components/popover/popover.tsx"],"sourcesContent":["import * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { forwardRef } from \"react\";\nimport type { ComponentPropsWithoutRef, ComponentRef } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\n\n/**\n * A floating overlay that displays rich content in a portal, triggered by a button.\n * This is the root, stateful component that manages the open/closed state of the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popoverroot\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Root = PopoverPrimitive.Root;\nRoot.displayName = \"Popover\";\n\n/**\n * The trigger button that opens the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popovertrigger\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Trigger = PopoverPrimitive.Trigger;\nTrigger.displayName = \"PopoverTrigger\";\n\n/**\n * An optional element to position the PopoverContent against. If this part is not used, the content will position alongside the PopoverTrigger.\n *\n * @see https://mantle.ngrok.com/components/popover#popoveranchor\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Anchor asChild>\n * <div>Anchor element</div>\n * </Popover.Anchor>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Anchor = PopoverPrimitive.Anchor;\nAnchor.displayName = \"PopoverAnchor\";\n\n/**\n * A button that closes an open popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popoverclose\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * <Popover.Close asChild>\n * <Button type=\"button\">Close</Button>\n * </Popover.Close>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Close = PopoverPrimitive.Close;\nClose.displayName = \"PopoverClose\";\n\ntype PopoverContentProps = ComponentPropsWithoutRef<typeof PopoverPrimitive.Content> & {\n\t/**\n\t * The preferred width of the `PopoverContent` as a tailwind `max-w-` class.\n\t *\n\t * By default, a `Popover`'s content width is responsive with a default\n\t * preferred width: the maximum width of the `PopoverContent`\n\t *\n\t * @default `max-w-72`\n\t */\n\tpreferredWidth?: `max-w-${string}`;\n};\n\n/**\n * The content to render inside the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#popovercontent\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Content = forwardRef<ComponentRef<\"div\">, PopoverContentProps>(\n\t(\n\t\t{\n\t\t\t//,\n\t\t\talign = \"center\",\n\t\t\tclassName,\n\t\t\tonClick,\n\t\t\tpreferredWidth = \"max-w-72\",\n\t\t\tsideOffset = 4,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<PopoverPrimitive.Portal>\n\t\t\t<PopoverPrimitive.Content\n\t\t\t\talign={align}\n\t\t\t\tdata-slot=\"popover-content\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"text-popover-foreground border-popover bg-popover data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 data-state-closed:animate-out data-state-closed:fade-out-0 data-state-closed:zoom-out-95 data-state-open:animate-in data-state-open:fade-in-0 data-state-open:zoom-in-95 z-50 rounded-md border p-4 shadow-md outline-hidden\",\n\t\t\t\t\tpreferredWidth,\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tonClick={(event) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Prevent the click event from propagating up to parent/containing elements\n\t\t\t\t\t * of the PopoverContent\n\t\t\t\t\t */\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\tonClick?.(event);\n\t\t\t\t}}\n\t\t\t\tref={ref}\n\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t{...props}\n\t\t\t/>\n\t\t</PopoverPrimitive.Portal>\n\t),\n);\nContent.displayName = \"PopoverContent\";\n\n/**\n * A floating overlay that displays rich content in a portal, triggered by a button.\n *\n * `Popover` is a non-modal dialog by default: focus moves into the content\n * when it opens, `Escape` closes and returns focus to the trigger, clicking\n * outside dismisses, and the page (body and any scroll containers) continues\n * to scroll normally. Pass `modal` on `Popover.Root` to trap focus inside\n * the content, block interaction with the rest of the page, and lock body\n * scroll while the popover is open. Use a `Popover` when the floating\n * content must be interactive — forms, action menus, filters, settings.\n * Prefer `Tooltip` for short, non-interactive labels on controls, or\n * `HoverCard` for a sighted-only preview of content that already lives\n * behind a link.\n *\n * @see https://mantle.ngrok.com/components/popover\n * @see https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/\n *\n * @example\n * Composition:\n * ```\n * Popover.Root\n * ├── Popover.Trigger\n * ├── Popover.Anchor\n * └── Popover.Content\n * └── Popover.Close\n * ```\n *\n * @example\n * ```tsx\n * <Popover.Root>\n * <Popover.Trigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </Popover.Trigger>\n * <Popover.Content>\n * <p>This is the popover content.</p>\n * </Popover.Content>\n * </Popover.Root>\n * ```\n */\nconst Popover = {\n\t/**\n\t * The root, stateful component that manages the open/closed state of the popover.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoverroot\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button>Open popover</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <p>This is the popover content.</p>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tRoot,\n\t/**\n\t * An optional element to position the PopoverContent against. If not used, content positions alongside the trigger.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoveranchor\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Anchor asChild>\n\t * <div>Position relative to this element</div>\n\t * </Popover.Anchor>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">Open Popover</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <p>This popover is positioned relative to the anchor.</p>\n\t * <Popover.Close asChild>\n\t * <Button type=\"button\">Close</Button>\n\t * </Popover.Close>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tAnchor,\n\t/**\n\t * A button that closes an open popover. Can be placed anywhere within the popover content.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popoverclose\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\">Settings</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <div className=\"flex items-center justify-between\">\n\t * <Text>Settings Panel</Text>\n\t * <Popover.Close asChild>\n\t * <Button type=\"button\" appearance=\"ghost\" size=\"sm\">✕</Button>\n\t * </Popover.Close>\n\t * </div>\n\t * <Text>Configure your preferences here.</Text>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tClose,\n\t/**\n\t * The content to render inside the popover. Appears in a portal with rich styling and animations.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popovercontent\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\">Show Info</Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content side=\"top\" align=\"center\">\n\t * <div className=\"space-y-2\">\n\t * <Text weight=\"strong\">Additional Information</Text>\n\t * <Text>This is the content inside the popover.</Text>\n\t * <Button type=\"button\" size=\"sm\">Action</Button>\n\t * </div>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tContent,\n\t/**\n\t * The trigger button that opens the popover when clicked or focused.\n\t *\n\t * @see https://mantle.ngrok.com/components/popover#popovertrigger\n\t *\n\t * @example\n\t * ```tsx\n\t * <Popover.Root>\n\t * <Popover.Trigger asChild>\n\t * <Button type=\"button\" appearance=\"outlined\">\n\t * Options\n\t * </Button>\n\t * </Popover.Trigger>\n\t * <Popover.Content>\n\t * <div className=\"space-y-2\">\n\t * <Button type=\"button\" variant=\"ghost\">Edit</Button>\n\t * <Button type=\"button\" variant=\"ghost\">Delete</Button>\n\t * </div>\n\t * </Popover.Content>\n\t * </Popover.Root>\n\t * ```\n\t */\n\tTrigger,\n} as const;\n\nexport {\n\t//,\n\tPopover,\n};\n"],"mappings":"0JAyBA,MAAM,EAAO,EAAiB,KAC9B,EAAK,YAAc,UAqBnB,MAAM,EAAU,EAAiB,QACjC,EAAQ,YAAc,iBAwBtB,MAAM,EAAS,EAAiB,OAChC,EAAO,YAAc,gBAwBrB,MAAM,EAAQ,EAAiB,MAC/B,EAAM,YAAc,eAiCpB,MAAM,EAAU,GAEd,CAEC,QAAQ,SACR,YACA,UACA,iBAAiB,WACjB,aAAa,EACb,GAAG,GAEJ,IAEA,EAAC,EAAiB,OAAlB,CAAA,SACC,EAAC,EAAiB,QAAlB,CACQ,QACP,YAAU,kBACV,UAAW,EACV,qaACA,EACA,EACA,CACD,QAAU,GAAU,CAKnB,EAAM,iBAAiB,CACvB,IAAU,EAAM,EAEZ,MACO,aACZ,GAAI,EACH,CAAA,CACuB,CAAA,CAE3B,CACD,EAAQ,YAAc,iBA2CtB,MAAM,EAAU,CAkBf,OAwBA,SAwBA,QAsBA,UAuBA,UACA"}
|