@ngrok/mantle 0.32.0 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/accordion.d.ts +143 -2
  2. package/dist/accordion.js +1 -1
  3. package/dist/accordion.js.map +1 -1
  4. package/dist/alert-dialog.d.ts +1 -1
  5. package/dist/alert-dialog.js +1 -1
  6. package/dist/alert-dialog.js.map +1 -1
  7. package/dist/alert.d.ts +5 -2
  8. package/dist/alert.js +1 -1
  9. package/dist/alert.js.map +1 -1
  10. package/dist/anchor.d.ts +1 -1
  11. package/dist/anchor.js +1 -1
  12. package/dist/anchor.js.map +1 -1
  13. package/dist/badge.d.ts +4 -1
  14. package/dist/badge.js +1 -1
  15. package/dist/badge.js.map +1 -1
  16. package/dist/{button-C8eGiHOm.d.ts → button-BvWgeelK.d.ts} +8 -1
  17. package/dist/{button-group-CpDp0fYZ.d.ts → button-group-7oT-O90J.d.ts} +11 -0
  18. package/dist/button.d.ts +3 -3
  19. package/dist/button.js +1 -1
  20. package/dist/calendar.d.ts +17 -0
  21. package/dist/calendar.js +1 -1
  22. package/dist/calendar.js.map +1 -1
  23. package/dist/checkbox.d.ts +1 -1
  24. package/dist/checkbox.js.map +1 -1
  25. package/dist/{chunk-7XIZZ4HQ.js → chunk-3H3EUKI7.js} +1 -1
  26. package/dist/chunk-3H3EUKI7.js.map +1 -0
  27. package/dist/{chunk-ZXLA5BJX.js → chunk-3X4AKTRA.js} +2 -2
  28. package/dist/chunk-3X4AKTRA.js.map +1 -0
  29. package/dist/chunk-6RJ2G2DK.js +34 -0
  30. package/dist/chunk-6RJ2G2DK.js.map +1 -0
  31. package/dist/chunk-I6T6YV2L.js +2 -0
  32. package/dist/chunk-I6T6YV2L.js.map +1 -0
  33. package/dist/chunk-IVXZIYX4.js +2 -0
  34. package/dist/chunk-IVXZIYX4.js.map +1 -0
  35. package/dist/chunk-J6ZF5J72.js +2 -0
  36. package/dist/chunk-J6ZF5J72.js.map +1 -0
  37. package/dist/chunk-JIRNFNH5.js +2 -0
  38. package/dist/{chunk-72UMV3YP.js.map → chunk-JIRNFNH5.js.map} +1 -1
  39. package/dist/chunk-NPTDRQT5.js +2 -0
  40. package/dist/chunk-NPTDRQT5.js.map +1 -0
  41. package/dist/chunk-NRMIFYYG.js +2 -0
  42. package/dist/chunk-NRMIFYYG.js.map +1 -0
  43. package/dist/{chunk-VTCWSFFJ.js → chunk-PANPBV3Q.js} +2 -2
  44. package/dist/{chunk-VTCWSFFJ.js.map → chunk-PANPBV3Q.js.map} +1 -1
  45. package/dist/{chunk-BK4P33ZH.js → chunk-RTXWW6ND.js} +2 -2
  46. package/dist/{chunk-BK4P33ZH.js.map → chunk-RTXWW6ND.js.map} +1 -1
  47. package/dist/{chunk-3MDQ3LC2.js → chunk-W2YQRWR5.js} +2 -2
  48. package/dist/{chunk-3MDQ3LC2.js.map → chunk-W2YQRWR5.js.map} +1 -1
  49. package/dist/code-block.d.ts +3 -0
  50. package/dist/code-block.js +3 -3
  51. package/dist/code-block.js.map +1 -1
  52. package/dist/combobox.d.ts +4 -1
  53. package/dist/combobox.js +1 -1
  54. package/dist/combobox.js.map +1 -1
  55. package/dist/data-table.d.ts +41 -12
  56. package/dist/data-table.js +1 -1
  57. package/dist/data-table.js.map +1 -1
  58. package/dist/dialog.d.ts +256 -3
  59. package/dist/dialog.js +1 -1
  60. package/dist/dialog.js.map +1 -1
  61. package/dist/dropdown-menu.d.ts +80 -0
  62. package/dist/dropdown-menu.js +1 -1
  63. package/dist/dropdown-menu.js.map +1 -1
  64. package/dist/flag.d.ts +4 -1
  65. package/dist/flag.js +1 -1
  66. package/dist/flag.js.map +1 -1
  67. package/dist/hover-card.d.ts +58 -0
  68. package/dist/hover-card.js +1 -1
  69. package/dist/hover-card.js.map +1 -1
  70. package/dist/{icon-Cu-iYUjr.d.ts → icon-CkvpQ4BK.d.ts} +1 -7
  71. package/dist/{icon-button-D41yiI7H.d.ts → icon-button-D4BTvC7F.d.ts} +12 -1
  72. package/dist/icon.d.ts +2 -2
  73. package/dist/icon.js +1 -1
  74. package/dist/icons.d.ts +9 -0
  75. package/dist/icons.js +1 -1
  76. package/dist/icons.js.map +1 -1
  77. package/dist/inline-code.d.ts +10 -1
  78. package/dist/inline-code.js.map +1 -1
  79. package/dist/input.d.ts +39 -1
  80. package/dist/input.js +1 -1
  81. package/dist/input.js.map +1 -1
  82. package/dist/label.d.ts +1 -1
  83. package/dist/label.js.map +1 -1
  84. package/dist/pagination.d.ts +51 -1
  85. package/dist/pagination.js +1 -1
  86. package/dist/pagination.js.map +1 -1
  87. package/dist/popover.d.ts +77 -17
  88. package/dist/popover.js.map +1 -1
  89. package/dist/{primitive-hud69IM9.d.ts → primitive-BUbUB7RS.d.ts} +3 -0
  90. package/dist/progress.d.ts +14 -2
  91. package/dist/progress.js +1 -1
  92. package/dist/progress.js.map +1 -1
  93. package/dist/radio-group.d.ts +51 -3
  94. package/dist/radio-group.js +1 -1
  95. package/dist/radio-group.js.map +1 -1
  96. package/dist/sandboxed-on-click.d.ts +0 -3
  97. package/dist/sandboxed-on-click.js.map +1 -1
  98. package/dist/select.d.ts +8 -4
  99. package/dist/select.js +1 -1
  100. package/dist/separator.d.ts +4 -1
  101. package/dist/separator.js +1 -1
  102. package/dist/sheet.d.ts +18 -6
  103. package/dist/sheet.js +1 -1
  104. package/dist/sheet.js.map +1 -1
  105. package/dist/{svg-only-CS2INnEL.d.ts → svg-only-Bj2yffO4.d.ts} +7 -7
  106. package/dist/switch.d.ts +2 -2
  107. package/dist/switch.js.map +1 -1
  108. package/dist/table.js +1 -1
  109. package/dist/tabs.d.ts +104 -1
  110. package/dist/tabs.js +1 -1
  111. package/dist/tabs.js.map +1 -1
  112. package/dist/text-area.d.ts +2 -1
  113. package/dist/text-area.js.map +1 -1
  114. package/dist/theme-provider.d.ts +29 -5
  115. package/dist/theme-provider.js +1 -1
  116. package/dist/toast.d.ts +70 -2
  117. package/dist/toast.js +1 -1
  118. package/dist/tooltip.d.ts +53 -13
  119. package/dist/tooltip.js +1 -1
  120. package/dist/tooltip.js.map +1 -1
  121. package/package.json +1 -1
  122. package/dist/chunk-3XX7M573.js +0 -34
  123. package/dist/chunk-3XX7M573.js.map +0 -1
  124. package/dist/chunk-72UMV3YP.js +0 -2
  125. package/dist/chunk-7XIZZ4HQ.js.map +0 -1
  126. package/dist/chunk-BGY3DO4G.js +0 -2
  127. package/dist/chunk-BGY3DO4G.js.map +0 -1
  128. package/dist/chunk-HDPLH5HC.js +0 -2
  129. package/dist/chunk-HDPLH5HC.js.map +0 -1
  130. package/dist/chunk-HVMKFNT3.js +0 -2
  131. package/dist/chunk-HVMKFNT3.js.map +0 -1
  132. package/dist/chunk-UXH22BMO.js +0 -2
  133. package/dist/chunk-UXH22BMO.js.map +0 -1
  134. package/dist/chunk-XQVVOOLT.js +0 -2
  135. package/dist/chunk-XQVVOOLT.js.map +0 -1
  136. package/dist/chunk-ZXLA5BJX.js.map +0 -1
package/dist/label.d.ts CHANGED
@@ -6,7 +6,7 @@ import * as react from 'react';
6
6
  * checkbox, radio button, etc. The label is typically displayed next to the
7
7
  * form control and helps users understand its purpose.
8
8
  *
9
- * @see https://mantle.ngrok.com/components/label#api
9
+ * @see https://mantle.ngrok.com/components/label#api-label
10
10
  *
11
11
  * @example
12
12
  * ```tsx
package/dist/label.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"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#api\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{\n\t\t\t\"aria-disabled\": _ariaDisabled,\n\t\t\tchildren,\n\t\t\tclassName,\n\t\t\tdisabled,\n\t\t\tonMouseDown,\n\t\t\t...props\n\t\t},\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\",\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":"wCAAA,OAAS,cAAAA,MAAkB,QA4CzB,cAAAC,MAAA,oBAbF,IAAMC,EAAQC,EACb,CACC,CACC,gBAAiBC,EACjB,SAAAC,EACA,UAAAC,EACA,SAAAC,EACA,YAAAC,EACA,GAAGC,CACJ,EACAC,IAGAT,EAAC,SACA,gBAAeM,GAAYH,EAC3B,UAAWO,EACV,8HACAL,CACD,EACA,YAAcM,GAAU,CAERA,EAAM,OACV,QAAQ,iCAAiC,IAIpDJ,IAAcI,CAAK,EAGf,CAACA,EAAM,kBAAoBA,EAAM,OAAS,GAC7CA,EAAM,eAAe,EAEvB,EACA,IAAKF,EACJ,GAAGD,EAEH,SAAAJ,EACF,CAEF,EACAH,EAAM,YAAc","names":["forwardRef","jsx","Label","forwardRef","_ariaDisabled","children","className","disabled","onMouseDown","props","ref","cx","event"]}
1
+ {"version":3,"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#api-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{\n\t\t\t\"aria-disabled\": _ariaDisabled,\n\t\t\tchildren,\n\t\t\tclassName,\n\t\t\tdisabled,\n\t\t\tonMouseDown,\n\t\t\t...props\n\t\t},\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\",\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":"wCAAA,OAAS,cAAAA,MAAkB,QA4CzB,cAAAC,MAAA,oBAbF,IAAMC,EAAQC,EACb,CACC,CACC,gBAAiBC,EACjB,SAAAC,EACA,UAAAC,EACA,SAAAC,EACA,YAAAC,EACA,GAAGC,CACJ,EACAC,IAGAT,EAAC,SACA,gBAAeM,GAAYH,EAC3B,UAAWO,EACV,8HACAL,CACD,EACA,YAAcM,GAAU,CAERA,EAAM,OACV,QAAQ,iCAAiC,IAIpDJ,IAAcI,CAAK,EAGf,CAACA,EAAM,kBAAoBA,EAAM,OAAS,GAC7CA,EAAM,eAAe,EAEvB,EACA,IAAKF,EACJ,GAAGD,EAEH,SAAAJ,EACF,CAEF,EACAH,EAAM,YAAc","names":["forwardRef","jsx","Label","forwardRef","_ariaDisabled","children","className","disabled","onMouseDown","props","ref","cx","event"]}
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
3
  import { ComponentProps } from 'react';
4
4
  import { W as WithAsChild } from './as-child-DJ7x3JFV.js';
5
- import { B as ButtonGroup } from './button-group-CpDp0fYZ.js';
5
+ import { B as ButtonGroup } from './button-group-7oT-O90J.js';
6
6
  import { SelectTrigger } from './select.js';
7
7
  import 'class-variance-authority/types';
8
8
  import './variant-props-oDo2u-We.js';
@@ -25,6 +25,21 @@ type CursorPaginationProps = ComponentProps<"div"> & {
25
25
  * making sure nothing is missed or repeated. Like a linked list, but for chunks
26
26
  * of data. It doesn't let you jump to a specific page or know how many total pages
27
27
  * there are, but it's more efficient for large or real-time data sets.
28
+ *
29
+ * @see https://mantle.ngrok.com/components/cursor-pagination#api-cursor-pagination
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <CursorPagination defaultPageSize={10}>
34
+ * <CursorButtons
35
+ * hasNextPage={hasNext}
36
+ * hasPreviousPage={hasPrevious}
37
+ * onNextPage={handleNext}
38
+ * onPreviousPage={handlePrevious}
39
+ * />
40
+ * <CursorPageSizeSelect />
41
+ * </CursorPagination>
42
+ * ```
28
43
  */
29
44
  declare const CursorPagination: react.ForwardRefExoticComponent<Omit<CursorPaginationProps, "ref"> & react.RefAttributes<HTMLDivElement>>;
30
45
  type CursorButtonsProps = Omit<ComponentProps<typeof ButtonGroup>, "appearance"> & {
@@ -47,6 +62,18 @@ type CursorButtonsProps = Omit<ComponentProps<typeof ButtonGroup>, "appearance">
47
62
  };
48
63
  /**
49
64
  * A pair of buttons for navigating between pages of data when using cursor-based pagination.
65
+ *
66
+ * @see https://mantle.ngrok.com/components/cursor-pagination#api-cursor-buttons
67
+ *
68
+ * @example
69
+ * ```tsx
70
+ * <CursorButtons
71
+ * hasNextPage={hasNext}
72
+ * hasPreviousPage={hasPrevious}
73
+ * onNextPage={() => loadNextPage()}
74
+ * onPreviousPage={() => loadPreviousPage()}
75
+ * />
76
+ * ```
50
77
  */
51
78
  declare const CursorButtons: react.ForwardRefExoticComponent<Omit<CursorButtonsProps, "ref"> & react.RefAttributes<HTMLFieldSetElement>>;
52
79
  declare const defaultPageSizes: readonly [5, 10, 20, 50, 100];
@@ -62,13 +89,36 @@ type CursorPageSizeSelectProps = Omit<ComponentProps<typeof SelectTrigger>, "chi
62
89
  };
63
90
  /**
64
91
  * A select input for changing the number of items per page when using cursor-based pagination.
92
+ *
93
+ * @see https://mantle.ngrok.com/components/cursor-pagination#api-cursor-page-size-select
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * <CursorPageSizeSelect
98
+ * pageSizes={[10, 20, 50, 100]}
99
+ * onChangePageSize={(size) => console.log('Page size changed to:', size)}
100
+ * />
101
+ * ```
65
102
  */
66
103
  declare const CursorPageSizeSelect: react.ForwardRefExoticComponent<Omit<CursorPageSizeSelectProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
67
104
  type CursorPageSizeValueProps = Omit<ComponentProps<"span">, "children"> & WithAsChild;
68
105
  /**
69
106
  * Displays the current page size when using cursor-based pagination as a read-only value.
107
+ *
108
+ * @see https://mantle.ngrok.com/components/cursor-pagination#api-cursor-page-size-value
109
+ *
110
+ * @example
111
+ * ```tsx
112
+ * <div className="flex items-center gap-2">
113
+ * <span>Items per page:</span>
114
+ * <CursorPageSizeValue />
115
+ * </div>
116
+ * ```
70
117
  */
71
118
  declare function CursorPageSizeValue({ asChild, className, ...props }: CursorPageSizeValueProps): react_jsx_runtime.JSX.Element;
119
+ declare namespace CursorPageSizeValue {
120
+ var displayName: string;
121
+ }
72
122
 
73
123
  type UseOffsetPaginationProps = {
74
124
  /**
@@ -1,2 +1,2 @@
1
- import{a as b,c as v,d as x,e as y,g as h}from"./chunk-ZXLA5BJX.js";import"./chunk-MF2QITTY.js";import{b as z}from"./chunk-UXH22BMO.js";import{a as d}from"./chunk-7XIZZ4HQ.js";import{a as l}from"./chunk-BK4P33ZH.js";import"./chunk-VTCWSFFJ.js";import"./chunk-4LSFAAZW.js";import"./chunk-72TJUKMV.js";import"./chunk-3C5O3AQA.js";import"./chunk-XQVVOOLT.js";import"./chunk-HDPLH5HC.js";import{a as p}from"./chunk-AZ56JGNY.js";import{CaretLeftIcon as k}from"@phosphor-icons/react/CaretLeft";import{CaretRightIcon as A}from"@phosphor-icons/react/CaretRight";import{Slot as E}from"@radix-ui/react-slot";import{createContext as F,forwardRef as c,useContext as N,useState as W}from"react";import P from"tiny-invariant";import{jsx as s,jsxs as f}from"react/jsx-runtime";var m=F(void 0),O=c(({className:n,children:e,defaultPageSize:a,...t},i)=>{let[o,r]=W(a);return s(m.Provider,{value:{defaultPageSize:a,pageSize:o,setPageSize:r},children:s("div",{className:p("inline-flex items-center justify-between gap-2",n),ref:i,...t,children:e})})});O.displayName="CursorPagination";var T=c(({hasNextPage:n,hasPreviousPage:e,onNextPage:a,onPreviousPage:t,...i},o)=>f(d,{appearance:"panel",ref:o,...i,children:[s(l,{appearance:"ghost",disabled:!e,icon:s(k,{}),label:"Previous page",onClick:t,size:"sm",type:"button"}),s(z,{orientation:"vertical",className:"min-h-5"}),s(l,{appearance:"ghost",disabled:!n,icon:s(A,{}),label:"Next page",onClick:a,size:"sm",type:"button"})]}));T.displayName="CursorButtons";var $=[5,10,20,50,100],B=c(({className:n,pageSizes:e=$,onChangePageSize:a,...t},i)=>{let o=N(m);return P(o,"CursorPageSizeSelect must be used as a child of a CursorPagination component"),P(e.includes(o.defaultPageSize),"CursorPagination.defaultPageSize must be included in CursorPageSizeSelect.pageSizes"),P(e.includes(o.pageSize),"CursorPagination.pageSize must be included in CursorPageSizeSelect.pageSizes"),f(b,{defaultValue:`${o.pageSize}`,onValueChange:r=>{let g=Number.parseInt(r,10);Number.isNaN(g)&&(g=o.defaultPageSize),o.setPageSize(g),a?.(g)},children:[s(x,{ref:i,className:p("w-auto min-w-36",n),value:o.pageSize,...t,children:s(v,{})}),s(y,{width:"trigger",children:e.map(r=>f(h,{value:`${r}`,children:[r," per page"]},r))})]})});B.displayName="CursorPageSizeSelect";function D({asChild:n=!1,className:e,...a}){let t=N(m);return P(t,"CursorPageSizeValue must be used as a child of a CursorPagination component"),f(n?E:"span",{className:p("text-muted text-sm font-normal",e),...a,children:[t.pageSize," per page"]})}import{useEffect as V,useState as w}from"react";function H({listSize:n,pageSize:e}){let[a,t]=w(1),[i,o]=w(e);V(()=>{o(e),t(1)},[e]),V(()=>{t(1)},[n]);let r=Math.ceil(n/i),g=(a-1)*i,S=a>1,C=a<r;function I(u){let j=Math.max(1,Math.min(u,r));t(j)}function M(){C&&t(u=>Math.min(u+1,r))}function R(){S&&t(u=>Math.max(u-1,1))}function G(u){o(u),t(1)}function L(){t(r)}function U(){t(1)}return{currentPage:a,goToFirstPage:U,goToLastPage:L,goToPage:I,hasNextPage:C,hasPreviousPage:S,nextPage:M,offset:g,pageSize:i,previousPage:R,setPageSize:G,totalPages:r}}function q(n,e){return n.slice(e.offset,e.offset+e.pageSize)}export{T as CursorButtons,B as CursorPageSizeSelect,D as CursorPageSizeValue,O as CursorPagination,q as getOffsetPaginatedSlice,H as useOffsetPagination};
1
+ import{a as b,c as v,d as y,e as x,g as h}from"./chunk-3X4AKTRA.js";import"./chunk-MF2QITTY.js";import{b as z}from"./chunk-J6ZF5J72.js";import{a as d}from"./chunk-3H3EUKI7.js";import{a as f}from"./chunk-RTXWW6ND.js";import"./chunk-PANPBV3Q.js";import"./chunk-4LSFAAZW.js";import"./chunk-72TJUKMV.js";import"./chunk-3C5O3AQA.js";import"./chunk-I6T6YV2L.js";import"./chunk-NPTDRQT5.js";import{a as p}from"./chunk-AZ56JGNY.js";import{CaretLeftIcon as A}from"@phosphor-icons/react/CaretLeft";import{CaretRightIcon as E}from"@phosphor-icons/react/CaretRight";import{Slot as F}from"@radix-ui/react-slot";import{createContext as W,forwardRef as c,useContext as N,useState as $}from"react";import P from"tiny-invariant";import{jsx as s,jsxs as l}from"react/jsx-runtime";var m=W(void 0),O=c(({className:n,children:e,defaultPageSize:a,...t},i)=>{let[o,r]=$(a);return s(m.Provider,{value:{defaultPageSize:a,pageSize:o,setPageSize:r},children:s("div",{className:p("inline-flex items-center justify-between gap-2",n),ref:i,...t,children:e})})});O.displayName="CursorPagination";var T=c(({hasNextPage:n,hasPreviousPage:e,onNextPage:a,onPreviousPage:t,...i},o)=>l(d,{appearance:"panel",ref:o,...i,children:[s(f,{appearance:"ghost",disabled:!e,icon:s(A,{}),label:"Previous page",onClick:t,size:"sm",type:"button"}),s(z,{orientation:"vertical",className:"min-h-5"}),s(f,{appearance:"ghost",disabled:!n,icon:s(E,{}),label:"Next page",onClick:a,size:"sm",type:"button"})]}));T.displayName="CursorButtons";var D=[5,10,20,50,100],V=c(({className:n,pageSizes:e=D,onChangePageSize:a,...t},i)=>{let o=N(m);return P(o,"CursorPageSizeSelect must be used as a child of a CursorPagination component"),P(e.includes(o.defaultPageSize),"CursorPagination.defaultPageSize must be included in CursorPageSizeSelect.pageSizes"),P(e.includes(o.pageSize),"CursorPagination.pageSize must be included in CursorPageSizeSelect.pageSizes"),l(b,{defaultValue:`${o.pageSize}`,onValueChange:r=>{let g=Number.parseInt(r,10);Number.isNaN(g)&&(g=o.defaultPageSize),o.setPageSize(g),a?.(g)},children:[s(y,{ref:i,className:p("w-auto min-w-36",n),value:o.pageSize,...t,children:s(v,{})}),s(x,{width:"trigger",children:e.map(r=>l(h,{value:`${r}`,children:[r," per page"]},r))})]})});V.displayName="CursorPageSizeSelect";function B({asChild:n=!1,className:e,...a}){let t=N(m);return P(t,"CursorPageSizeValue must be used as a child of a CursorPagination component"),l(n?F:"span",{className:p("text-muted text-sm font-normal",e),...a,children:[t.pageSize," per page"]})}B.displayName="CursorPageSizeValue";import{useEffect as w,useState as I}from"react";function H({listSize:n,pageSize:e}){let[a,t]=I(1),[i,o]=I(e);w(()=>{o(e),t(1)},[e]),w(()=>{t(1)},[n]);let r=Math.ceil(n/i),g=(a-1)*i,S=a>1,C=a<r;function M(u){let k=Math.max(1,Math.min(u,r));t(k)}function R(){C&&t(u=>Math.min(u+1,r))}function G(){S&&t(u=>Math.max(u-1,1))}function L(u){o(u),t(1)}function U(){t(r)}function j(){t(1)}return{currentPage:a,goToFirstPage:j,goToLastPage:U,goToPage:M,hasNextPage:C,hasPreviousPage:S,nextPage:R,offset:g,pageSize:i,previousPage:G,setPageSize:L,totalPages:r}}function q(n,e){return n.slice(e.offset,e.offset+e.pageSize)}export{T as CursorButtons,V as CursorPageSizeSelect,B as CursorPageSizeValue,O as CursorPagination,q as getOffsetPaginatedSlice,H as useOffsetPagination};
2
2
  //# sourceMappingURL=pagination.js.map
@@ -1 +1 @@
1
- {"version":3,"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 { Slot } from \"@radix-ui/react-slot\";\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 {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"../select/select.js\";\nimport { Separator } from \"../separator/separator.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<\n\tCursorPaginationContextValue | undefined\n>(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 */\nconst CursorPagination = 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\n\t\t\t\tvalue={{ defaultPageSize, pageSize, setPageSize }}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"inline-flex items-center justify-between gap-2\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\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);\nCursorPagination.displayName = \"CursorPagination\";\n\ntype CursorButtonsProps = Omit<\n\tComponentProps<typeof ButtonGroup>,\n\t\"appearance\"\n> & {\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 */\nconst CursorButtons = forwardRef<\n\tComponentRef<typeof ButtonGroup>,\n\tCursorButtonsProps\n>(\n\t(\n\t\t{ hasNextPage, hasPreviousPage, onNextPage, onPreviousPage, ...props },\n\t\tref,\n\t) => {\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);\nCursorButtons.displayName = \"CursorButtons\";\n\nconst defaultPageSizes = [5, 10, 20, 50, 100] as const;\n\ntype CursorPageSizeSelectProps = Omit<\n\tComponentProps<typeof SelectTrigger>,\n\t\"children\"\n> & {\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 */\nconst CursorPageSizeSelect = forwardRef<\n\tComponentRef<typeof SelectTrigger>,\n\tCursorPageSizeSelectProps\n>(\n\t(\n\t\t{ className, pageSizes = defaultPageSizes, onChangePageSize, ...rest },\n\t\tref,\n\t) => {\n\t\tconst ctx = useContext(CursorPaginationContext);\n\n\t\tinvariant(\n\t\t\tctx,\n\t\t\t\"CursorPageSizeSelect must be used as a child of a CursorPagination component\",\n\t\t);\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\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<SelectTrigger\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<SelectValue />\n\t\t\t\t</SelectTrigger>\n\t\t\t\t<SelectContent width=\"trigger\">\n\t\t\t\t\t{pageSizes.map((size) => (\n\t\t\t\t\t\t<SelectItem key={size} value={`${size}`}>\n\t\t\t\t\t\t\t{size} per page\n\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t))}\n\t\t\t\t</SelectContent>\n\t\t\t</Select>\n\t\t);\n\t},\n);\nCursorPageSizeSelect.displayName = \"CursorPageSizeSelect\";\n\ntype CursorPageSizeValueProps = Omit<ComponentProps<\"span\">, \"children\"> &\n\tWithAsChild;\n\n/**\n * Displays the current page size when using cursor-based pagination as a read-only value.\n */\nfunction CursorPageSizeValue({\n\tasChild = false,\n\tclassName,\n\t...props\n}: CursorPageSizeValueProps) {\n\tconst ctx = useContext(CursorPaginationContext);\n\n\tinvariant(\n\t\tctx,\n\t\t\"CursorPageSizeValue must be used as a child of a CursorPagination component\",\n\t);\n\n\tconst Component = asChild ? Slot : \"span\";\n\n\treturn (\n\t\t<Component\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}\n\nexport {\n\t//,\n\tCursorButtons,\n\tCursorPageSizeSelect,\n\tCursorPageSizeValue,\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 */\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 nextPage = Math.max(1, Math.min(page, totalPages));\n\t\tsetCurrentPage(nextPage);\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 */\nfunction getOffsetPaginatedSlice<T>(\n\tlist: readonly T[],\n\tpagination: OffsetPaginationState,\n): 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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","names":["CaretLeftIcon","CaretRightIcon","Slot","createContext","forwardRef","useContext","useState","invariant","jsx","jsxs","CursorPaginationContext","createContext","CursorPagination","forwardRef","className","children","defaultPageSize","props","ref","pageSize","setPageSize","useState","cx","CursorButtons","hasNextPage","hasPreviousPage","onNextPage","onPreviousPage","ButtonGroup","IconButton","CaretLeftIcon","Separator","CaretRightIcon","defaultPageSizes","CursorPageSizeSelect","pageSizes","onChangePageSize","rest","ctx","useContext","invariant","Select","value","newPageSize","SelectTrigger","SelectValue","SelectContent","size","SelectItem","CursorPageSizeValue","asChild","Slot","useEffect","useState","useOffsetPagination","listSize","pageSize","currentPage","setCurrentPage","currentPageSize","setCurrentPageSize","totalPages","offset","hasPreviousPage","hasNextPage","goToPage","page","nextPage","prev","previousPage","setPageSize","size","goToLastPage","goToFirstPage","getOffsetPaginatedSlice","list","pagination"]}
1
+ {"version":3,"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 { Slot } from \"@radix-ui/react-slot\";\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 {\n\tSelect,\n\tSelectContent,\n\tSelectItem,\n\tSelectTrigger,\n\tSelectValue,\n} from \"../select/select.js\";\nimport { Separator } from \"../separator/separator.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<\n\tCursorPaginationContextValue | undefined\n>(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/cursor-pagination#api-cursor-pagination\n *\n * @example\n * ```tsx\n * <CursorPagination defaultPageSize={10}>\n * <CursorButtons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={handleNext}\n * onPreviousPage={handlePrevious}\n * />\n * <CursorPageSizeSelect />\n * </CursorPagination>\n * ```\n */\nconst CursorPagination = 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\n\t\t\t\tvalue={{ defaultPageSize, pageSize, setPageSize }}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={cx(\n\t\t\t\t\t\t\"inline-flex items-center justify-between gap-2\",\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t)}\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);\nCursorPagination.displayName = \"CursorPagination\";\n\ntype CursorButtonsProps = Omit<\n\tComponentProps<typeof ButtonGroup>,\n\t\"appearance\"\n> & {\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/cursor-pagination#api-cursor-buttons\n *\n * @example\n * ```tsx\n * <CursorButtons\n * hasNextPage={hasNext}\n * hasPreviousPage={hasPrevious}\n * onNextPage={() => loadNextPage()}\n * onPreviousPage={() => loadPreviousPage()}\n * />\n * ```\n */\nconst CursorButtons = forwardRef<\n\tComponentRef<typeof ButtonGroup>,\n\tCursorButtonsProps\n>(\n\t(\n\t\t{ hasNextPage, hasPreviousPage, onNextPage, onPreviousPage, ...props },\n\t\tref,\n\t) => {\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);\nCursorButtons.displayName = \"CursorButtons\";\n\nconst defaultPageSizes = [5, 10, 20, 50, 100] as const;\n\ntype CursorPageSizeSelectProps = Omit<\n\tComponentProps<typeof SelectTrigger>,\n\t\"children\"\n> & {\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/cursor-pagination#api-cursor-page-size-select\n *\n * @example\n * ```tsx\n * <CursorPageSizeSelect\n * pageSizes={[10, 20, 50, 100]}\n * onChangePageSize={(size) => console.log('Page size changed to:', size)}\n * />\n * ```\n */\nconst CursorPageSizeSelect = forwardRef<\n\tComponentRef<typeof SelectTrigger>,\n\tCursorPageSizeSelectProps\n>(\n\t(\n\t\t{ className, pageSizes = defaultPageSizes, onChangePageSize, ...rest },\n\t\tref,\n\t) => {\n\t\tconst ctx = useContext(CursorPaginationContext);\n\n\t\tinvariant(\n\t\t\tctx,\n\t\t\t\"CursorPageSizeSelect must be used as a child of a CursorPagination component\",\n\t\t);\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\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<SelectTrigger\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<SelectValue />\n\t\t\t\t</SelectTrigger>\n\t\t\t\t<SelectContent width=\"trigger\">\n\t\t\t\t\t{pageSizes.map((size) => (\n\t\t\t\t\t\t<SelectItem key={size} value={`${size}`}>\n\t\t\t\t\t\t\t{size} per page\n\t\t\t\t\t\t</SelectItem>\n\t\t\t\t\t))}\n\t\t\t\t</SelectContent>\n\t\t\t</Select>\n\t\t);\n\t},\n);\nCursorPageSizeSelect.displayName = \"CursorPageSizeSelect\";\n\ntype CursorPageSizeValueProps = Omit<ComponentProps<\"span\">, \"children\"> &\n\tWithAsChild;\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/cursor-pagination#api-cursor-page-size-value\n *\n * @example\n * ```tsx\n * <div className=\"flex items-center gap-2\">\n * <span>Items per page:</span>\n * <CursorPageSizeValue />\n * </div>\n * ```\n */\nfunction CursorPageSizeValue({\n\tasChild = false,\n\tclassName,\n\t...props\n}: CursorPageSizeValueProps) {\n\tconst ctx = useContext(CursorPaginationContext);\n\n\tinvariant(\n\t\tctx,\n\t\t\"CursorPageSizeValue must be used as a child of a CursorPagination component\",\n\t);\n\n\tconst Component = asChild ? Slot : \"span\";\n\n\treturn (\n\t\t<Component\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}\nCursorPageSizeValue.displayName = \"CursorPageSizeValue\";\n\nexport {\n\t//,\n\tCursorButtons,\n\tCursorPageSizeSelect,\n\tCursorPageSizeValue,\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 */\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 nextPage = Math.max(1, Math.min(page, totalPages));\n\t\tsetCurrentPage(nextPage);\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 */\nfunction getOffsetPaginatedSlice<T>(\n\tlist: readonly T[],\n\tpagination: OffsetPaginationState,\n): 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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","names":["CaretLeftIcon","CaretRightIcon","Slot","createContext","forwardRef","useContext","useState","invariant","jsx","jsxs","CursorPaginationContext","createContext","CursorPagination","forwardRef","className","children","defaultPageSize","props","ref","pageSize","setPageSize","useState","cx","CursorButtons","hasNextPage","hasPreviousPage","onNextPage","onPreviousPage","ButtonGroup","IconButton","CaretLeftIcon","Separator","CaretRightIcon","defaultPageSizes","CursorPageSizeSelect","pageSizes","onChangePageSize","rest","ctx","useContext","invariant","Select","value","newPageSize","SelectTrigger","SelectValue","SelectContent","size","SelectItem","CursorPageSizeValue","asChild","Slot","useEffect","useState","useOffsetPagination","listSize","pageSize","currentPage","setCurrentPage","currentPageSize","setCurrentPageSize","totalPages","offset","hasPreviousPage","hasNextPage","goToPage","page","nextPage","prev","previousPage","setPageSize","size","goToLastPage","goToFirstPage","getOffsetPaginatedSlice","list","pagination"]}
package/dist/popover.d.ts CHANGED
@@ -2,50 +2,110 @@ import * as react from 'react';
2
2
  import * as PopoverPrimitive from '@radix-ui/react-popover';
3
3
 
4
4
  /**
5
- * A popover is a floating overlay that appears above other elements on the page.
6
- * Displays rich content in a portal, triggered by a button.
5
+ * A floating overlay that displays rich content in a portal, triggered by a button.
7
6
  * This is the root, stateful component that manages the open/closed state of the popover.
8
7
  *
9
- * @preview This component is in `preview` mode which means the API is not stable and may change.
10
- * There may also be bugs! Please file an issue if you find any! <3
8
+ * @see https://mantle.ngrok.com/components/popover#api-popover
11
9
  *
12
- * https://github.com/ngrok-oss/mantle/issues
10
+ * @example
11
+ * ```tsx
12
+ * <Popover>
13
+ * <PopoverTrigger asChild>
14
+ * <Button type="button" appearance="outlined">
15
+ * Open Popover
16
+ * </Button>
17
+ * </PopoverTrigger>
18
+ * <PopoverContent>
19
+ * <p>This is the popover content.</p>
20
+ * </PopoverContent>
21
+ * </Popover>
22
+ * ```
13
23
  */
14
24
  declare const Popover: react.FC<PopoverPrimitive.PopoverProps>;
15
25
  /**
16
26
  * The trigger button that opens the popover.
17
27
  *
18
- * @preview This component is in `preview` mode which means the API is not stable and may change.
19
- * There may also be bugs! Please file an issue if you find any! <3
28
+ * @see https://mantle.ngrok.com/components/popover#api-popover-trigger
20
29
  *
21
- * https://github.com/ngrok-oss/mantle/issues
30
+ * @example
31
+ * ```tsx
32
+ * <Popover>
33
+ * <PopoverTrigger asChild>
34
+ * <Button type="button" appearance="outlined">
35
+ * Open Popover
36
+ * </Button>
37
+ * </PopoverTrigger>
38
+ * <PopoverContent>
39
+ * <p>This is the popover content.</p>
40
+ * </PopoverContent>
41
+ * </Popover>
42
+ * ```
22
43
  */
23
44
  declare const PopoverTrigger: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverTriggerProps & react.RefAttributes<HTMLButtonElement>>;
24
45
  /**
25
46
  * An optional element to position the PopoverContent against. If this part is not used, the content will position alongside the PopoverTrigger.
26
47
  *
27
- * @preview This component is in `preview` mode which means the API is not stable and may change.
28
- * There may also be bugs! Please file an issue if you find any! <3
48
+ * @see https://mantle.ngrok.com/components/popover#api-popover-anchor
29
49
  *
30
- * https://github.com/ngrok-oss/mantle/issues
50
+ * @example
51
+ * ```tsx
52
+ * <Popover>
53
+ * <PopoverTrigger asChild>
54
+ * <Button type="button" appearance="outlined">
55
+ * Open Popover
56
+ * </Button>
57
+ * </PopoverTrigger>
58
+ * <PopoverAnchor asChild>
59
+ * <div>Anchor element</div>
60
+ * </PopoverAnchor>
61
+ * <PopoverContent>
62
+ * <p>This is the popover content.</p>
63
+ * </PopoverContent>
64
+ * </Popover>
65
+ * ```
31
66
  */
32
67
  declare const PopoverAnchor: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverAnchorProps & react.RefAttributes<HTMLDivElement>>;
33
68
  /**
34
69
  * A button that closes an open popover.
35
70
  *
36
- * @preview This component is in `preview` mode which means the API is not stable and may change.
37
- * There may also be bugs! Please file an issue if you find any! <3
71
+ * @see https://mantle.ngrok.com/components/popover#api-popover-close
38
72
  *
39
- * https://github.com/ngrok-oss/mantle/issues
73
+ * @example
74
+ * ```tsx
75
+ * <Popover>
76
+ * <PopoverTrigger asChild>
77
+ * <Button type="button" appearance="outlined">
78
+ * Open Popover
79
+ * </Button>
80
+ * </PopoverTrigger>
81
+ * <PopoverContent>
82
+ * <p>This is the popover content.</p>
83
+ * <PopoverClose asChild>
84
+ * <Button type="button">Close</Button>
85
+ * </PopoverClose>
86
+ * </PopoverContent>
87
+ * </Popover>
88
+ * ```
40
89
  */
41
90
  declare const PopoverClose: react.ForwardRefExoticComponent<PopoverPrimitive.PopoverCloseProps & react.RefAttributes<HTMLButtonElement>>;
42
91
  /**
43
92
  * The content to render inside the popover.
44
93
  *
45
- * @preview This component is in `preview` mode which means the API is not stable and may change.
46
- * There may also be bugs! Please file an issue if you find any! <3
94
+ * @see https://mantle.ngrok.com/components/popover#api-popover-content
47
95
  *
48
- * https://github.com/ngrok-oss/mantle/issues
96
+ * @example
97
+ * ```tsx
98
+ * <Popover>
99
+ * <PopoverTrigger asChild>
100
+ * <Button type="button" appearance="outlined">
101
+ * Open Popover
102
+ * </Button>
103
+ * </PopoverTrigger>
104
+ * <PopoverContent>
105
+ * <p>This is the popover content.</p>
106
+ * </PopoverContent>
107
+ * </Popover>
108
+ * ```
49
109
  */
50
110
  declare const PopoverContent: react.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & react.RefAttributes<HTMLDivElement>, "ref"> & {
51
111
  /**
@@ -1 +1 @@
1
- {"version":3,"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 popover is a floating overlay that appears above other elements on the page.\n * 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 * @preview This component is in `preview` mode which means the API is not stable and may change.\n * There may also be bugs! Please file an issue if you find any! <3\n *\n * https://github.com/ngrok-oss/mantle/issues\n */\nconst Popover = PopoverPrimitive.Root;\nPopover.displayName = \"Popover\";\n\n/**\n * The trigger button that opens the popover.\n *\n * @preview This component is in `preview` mode which means the API is not stable and may change.\n * There may also be bugs! Please file an issue if you find any! <3\n *\n * https://github.com/ngrok-oss/mantle/issues\n */\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nPopoverTrigger.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 * @preview This component is in `preview` mode which means the API is not stable and may change.\n * There may also be bugs! Please file an issue if you find any! <3\n *\n * https://github.com/ngrok-oss/mantle/issues\n */\nconst PopoverAnchor = PopoverPrimitive.Anchor;\nPopoverAnchor.displayName = \"PopoverAnchor\";\n\n/**\n * A button that closes an open popover.\n *\n * @preview This component is in `preview` mode which means the API is not stable and may change.\n * There may also be bugs! Please file an issue if you find any! <3\n *\n * https://github.com/ngrok-oss/mantle/issues\n */\nconst PopoverClose = PopoverPrimitive.Close;\nPopoverClose.displayName = \"PopoverClose\";\n\ntype PopoverContentProps = ComponentPropsWithoutRef<\n\ttypeof PopoverPrimitive.Content\n> & {\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 * @preview This component is in `preview` mode which means the API is not stable and may change.\n * There may also be bugs! Please file an issue if you find any! <3\n *\n * https://github.com/ngrok-oss/mantle/issues\n */\nconst PopoverContent = 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-none\",\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);\nPopoverContent.displayName = \"PopoverContent\";\n\nexport {\n\t//,\n\tPopover,\n\tPopoverAnchor,\n\tPopoverClose,\n\tPopoverContent,\n\tPopoverTrigger,\n};\n"],"mappings":"wCAAA,UAAYA,MAAsB,0BAClC,OAAS,cAAAC,MAAkB,QAsFxB,cAAAC,MAAA,oBAxEH,IAAMC,EAA2B,OACjCA,EAAQ,YAAc,UAUtB,IAAMC,EAAkC,UACxCA,EAAe,YAAc,iBAU7B,IAAMC,EAAiC,SACvCA,EAAc,YAAc,gBAU5B,IAAMC,EAAgC,QACtCA,EAAa,YAAc,eAwB3B,IAAMC,EAAiBC,EACtB,CACC,CAEC,MAAAC,EAAQ,SACR,UAAAC,EACA,QAAAC,EACA,eAAAC,EAAiB,WACjB,WAAAC,EAAa,EACb,GAAGC,CACJ,EACAC,IAEAb,EAAkB,SAAjB,CACA,SAAAA,EAAkB,UAAjB,CACA,MAAOO,EACP,UAAWO,EACV,maACAJ,EACAF,CACD,EACA,QAAUO,GAAU,CAKnBA,EAAM,gBAAgB,EACtBN,IAAUM,CAAK,CAChB,EACA,IAAKF,EACL,WAAYF,EACX,GAAGC,EACL,EACD,CAEF,EACAP,EAAe,YAAc","names":["PopoverPrimitive","forwardRef","jsx","Popover","PopoverTrigger","PopoverAnchor","PopoverClose","PopoverContent","forwardRef","align","className","onClick","preferredWidth","sideOffset","props","ref","cx","event"]}
1
+ {"version":3,"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#api-popover\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </PopoverTrigger>\n * <PopoverContent>\n * <p>This is the popover content.</p>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nconst Popover = PopoverPrimitive.Root;\nPopover.displayName = \"Popover\";\n\n/**\n * The trigger button that opens the popover.\n *\n * @see https://mantle.ngrok.com/components/popover#api-popover-trigger\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </PopoverTrigger>\n * <PopoverContent>\n * <p>This is the popover content.</p>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nconst PopoverTrigger = PopoverPrimitive.Trigger;\nPopoverTrigger.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#api-popover-anchor\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </PopoverTrigger>\n * <PopoverAnchor asChild>\n * <div>Anchor element</div>\n * </PopoverAnchor>\n * <PopoverContent>\n * <p>This is the popover content.</p>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nconst PopoverAnchor = PopoverPrimitive.Anchor;\nPopoverAnchor.displayName = \"PopoverAnchor\";\n\n/**\n * A button that closes an open popover.\n *\n * @see https://mantle.ngrok.com/components/popover#api-popover-close\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </PopoverTrigger>\n * <PopoverContent>\n * <p>This is the popover content.</p>\n * <PopoverClose asChild>\n * <Button type=\"button\">Close</Button>\n * </PopoverClose>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nconst PopoverClose = PopoverPrimitive.Close;\nPopoverClose.displayName = \"PopoverClose\";\n\ntype PopoverContentProps = ComponentPropsWithoutRef<\n\ttypeof PopoverPrimitive.Content\n> & {\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#api-popover-content\n *\n * @example\n * ```tsx\n * <Popover>\n * <PopoverTrigger asChild>\n * <Button type=\"button\" appearance=\"outlined\">\n * Open Popover\n * </Button>\n * </PopoverTrigger>\n * <PopoverContent>\n * <p>This is the popover content.</p>\n * </PopoverContent>\n * </Popover>\n * ```\n */\nconst PopoverContent = 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-none\",\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);\nPopoverContent.displayName = \"PopoverContent\";\n\nexport {\n\t//,\n\tPopover,\n\tPopoverAnchor,\n\tPopoverClose,\n\tPopoverContent,\n\tPopoverTrigger,\n};\n"],"mappings":"wCAAA,UAAYA,MAAsB,0BAClC,OAAS,cAAAC,MAAkB,QAkJxB,cAAAC,MAAA,oBA1HH,IAAMC,EAA2B,OACjCA,EAAQ,YAAc,UAqBtB,IAAMC,EAAkC,UACxCA,EAAe,YAAc,iBAwB7B,IAAMC,EAAiC,SACvCA,EAAc,YAAc,gBAwB5B,IAAMC,EAAgC,QACtCA,EAAa,YAAc,eAmC3B,IAAMC,EAAiBC,EACtB,CACC,CAEC,MAAAC,EAAQ,SACR,UAAAC,EACA,QAAAC,EACA,eAAAC,EAAiB,WACjB,WAAAC,EAAa,EACb,GAAGC,CACJ,EACAC,IAEAb,EAAkB,SAAjB,CACA,SAAAA,EAAkB,UAAjB,CACA,MAAOO,EACP,UAAWO,EACV,maACAJ,EACAF,CACD,EACA,QAAUO,GAAU,CAKnBA,EAAM,gBAAgB,EACtBN,IAAUM,CAAK,CAChB,EACA,IAAKF,EACL,WAAYF,EACX,GAAGC,EACL,EACD,CAEF,EACAP,EAAe,YAAc","names":["PopoverPrimitive","forwardRef","jsx","Popover","PopoverTrigger","PopoverAnchor","PopoverClose","PopoverContent","forwardRef","align","className","onClick","preferredWidth","sideOffset","props","ref","cx","event"]}
@@ -3,5 +3,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import * as _radix_ui_react_dialog from '@radix-ui/react-dialog';
4
4
 
5
5
  declare function Root(props: ComponentPropsWithoutRef<typeof _radix_ui_react_dialog.Root>): react_jsx_runtime.JSX.Element;
6
+ declare namespace Root {
7
+ var displayName: string;
8
+ }
6
9
 
7
10
  export { Root as R };
@@ -53,7 +53,10 @@ type Props = SvgAttributes & {
53
53
  * </ProgressDonut>
54
54
  * ```
55
55
  */
56
- declare const ProgressDonut: ({ children, className, max: _max, strokeWidth: _strokeWidth, value: _value, ...props }: Props) => react_jsx_runtime.JSX.Element;
56
+ declare const ProgressDonut: {
57
+ ({ children, className, max: _max, strokeWidth: _strokeWidth, value: _value, ...props }: Props): react_jsx_runtime.JSX.Element;
58
+ displayName: string;
59
+ };
57
60
  type ProgressDonutIndicatorProps = Omit<ComponentProps<"g">, "children">;
58
61
  /**
59
62
  * The indicator for the circular progress bar.
@@ -71,7 +74,10 @@ type ProgressDonutIndicatorProps = Omit<ComponentProps<"g">, "children">;
71
74
  * </ProgressDonut>
72
75
  * ```
73
76
  */
74
- declare const ProgressDonutIndicator: ({ className, ...props }: ProgressDonutIndicatorProps) => react_jsx_runtime.JSX.Element;
77
+ declare const ProgressDonutIndicator: {
78
+ ({ className, ...props }: ProgressDonutIndicatorProps): react_jsx_runtime.JSX.Element;
79
+ displayName: string;
80
+ };
75
81
 
76
82
  type RootProps = ComponentProps<"div"> & {
77
83
  /**
@@ -117,6 +123,9 @@ type RootProps = ComponentProps<"div"> & {
117
123
  * ```
118
124
  */
119
125
  declare function Root({ className, children, max: _max, value: _value, ...props }: RootProps): react_jsx_runtime.JSX.Element;
126
+ declare namespace Root {
127
+ var displayName: string;
128
+ }
120
129
  type IndicatorProps = ComponentProps<typeof ProgressPrimitive.Indicator>;
121
130
  /**
122
131
  * Displays the progress indicator, which visually represents the completion progress of a task.
@@ -139,6 +148,9 @@ type IndicatorProps = ComponentProps<typeof ProgressPrimitive.Indicator>;
139
148
  * ```
140
149
  */
141
150
  declare function Indicator({ className, style, ...props }: IndicatorProps): react_jsx_runtime.JSX.Element;
151
+ declare namespace Indicator {
152
+ var displayName: string;
153
+ }
142
154
  /**
143
155
  * A horizontal progress bar component that shows the completion progress of a task.
144
156
  *
package/dist/progress.js CHANGED
@@ -1,2 +1,2 @@
1
- import{a as m}from"./chunk-AZ56JGNY.js";import N from"clsx";import{createContext as T,useContext as M,useId as W,useMemo as R}from"react";function h(e,{min:t,max:o}){return Math.min(o,Math.max(t,e))}function l(e){return typeof e=="number"}function d(e,t){return l(e)&&!Number.isNaN(e)&&e<=t&&e>=0}function p(e){return l(e)&&!Number.isNaN(e)&&e>0}import{jsx as c,jsxs as P}from"react/jsx-runtime";var f=100,g={max:f,strokeWidth:"0.25rem",value:0},V=T(g),D=({children:e,className:t,max:o=f,strokeWidth:r=4,value:a,...n})=>{let s=p(o)?o:f,i=d(a,s)?a:a==null?0:"indeterminate",u=C(r??g.strokeWidth),y=l(i)?i:void 0,S=k(u),I=R(()=>({max:s,strokeWidth:u,value:i}),[s,u,i]);return c(V.Provider,{value:I,children:P("svg",{"aria-valuemax":s,"aria-valuemin":0,"aria-valuenow":y,className:N(i==="indeterminate"&&"animation-duration-[15s] transform-gpu animate-spin",m("size-6 text-gray-200 dark:text-gray-300",t)),"data-max":s,"data-min":0,"data-value":y,height:"100%",role:"progressbar",width:"100%",...n,children:[c("circle",{className:"[r:var(--radius)]",cx:"50%",cy:"50%",fill:"transparent",stroke:"currentColor",strokeWidth:u,style:{"--radius":S}}),e]})})},A=.6,G=({className:e,...t})=>{let o=W(),r=M(V)??g,a=(r.value==="indeterminate"?A:r.value/r.max)*100,n=C(r.strokeWidth),s=k(n);return P("g",{className:m("text-accent-600",e),...t,children:[r.value==="indeterminate"&&c("defs",{children:P("linearGradient",{id:o,children:[c("stop",{className:"stop-opacity-100 stop-color-current",offset:"0%"}),c("stop",{className:"stop-opacity-0 stop-color-current",offset:"95%"})]})}),c("circle",{className:N("[r:var(--radius)]","origin-center"),cx:"50%",cy:"50%",fill:"transparent",pathLength:100,stroke:r.value==="indeterminate"?`url(#${o})`:"currentColor",strokeDasharray:100,strokeDashoffset:100-a,strokeLinecap:"round",strokeWidth:n,style:{"--radius":s},transform:"rotate(-90)"})]})};function C(e){let t=4;if(e==null)return t;typeof e=="number"?t=e:e.endsWith("rem")?t=Number(e.replace("rem",""))*16:t=Number(e);let o=Number.isNaN(t)?4:t;return h(o,{min:1,max:12})}function k(e){return`calc(50% - ${e/2}px)`}import*as x from"@radix-ui/react-progress";import{createContext as L,useContext as $,useMemo as B}from"react";import{jsx as v}from"react/jsx-runtime";var b=100,E={max:b,value:0},w=L(E);function H({className:e,children:t,max:o=b,value:r,...a}){let n=p(o)?o:b,s=d(r,n)?r:r==null?0:"indeterminate",i=l(s)?s:void 0,u=B(()=>({max:n,value:s}),[n,s]);return v(w.Provider,{value:u,children:v(x.Root,{"data-slot":"progress",className:m("bg-base-hover dark:bg-base shadow-inner relative h-3 w-full overflow-hidden rounded-md",e),value:i,max:n,...a,children:t})})}function O({className:e,style:t,...o}){let r=$(w),{max:a}=r,n=r.value==="indeterminate"?0:r.value,s=(a-n)/a*100;return v(x.Indicator,{"data-slot":"progress-indicator",className:m("bg-accent-600 h-full w-full flex-1 transition-all",e),style:{...t,transform:`translateX(-${s}%)`},...o})}var z={Root:H,Indicator:O};export{z as ProgressBar,D as ProgressDonut,G as ProgressDonutIndicator};
1
+ import{a as m}from"./chunk-AZ56JGNY.js";import h from"clsx";import{createContext as R,useContext as A,useId as G,useMemo as L}from"react";function N(e,{min:t,max:o}){return Math.min(o,Math.max(t,e))}function l(e){return typeof e=="number"}function d(e,t){return l(e)&&!Number.isNaN(e)&&e<=t&&e>=0}function p(e){return l(e)&&!Number.isNaN(e)&&e>0}import{jsx as c,jsxs as P}from"react/jsx-runtime";var f=100,g={max:f,strokeWidth:"0.25rem",value:0},V=R(g),C=({children:e,className:t,max:o=f,strokeWidth:r=4,value:n,...a})=>{let s=p(o)?o:f,i=d(n,s)?n:n==null?0:"indeterminate",u=w(r??g.strokeWidth),y=l(i)?i:void 0,W=I(u),D=L(()=>({max:s,strokeWidth:u,value:i}),[s,u,i]);return c(V.Provider,{value:D,children:P("svg",{"aria-valuemax":s,"aria-valuemin":0,"aria-valuenow":y,className:h(i==="indeterminate"&&"animation-duration-[15s] transform-gpu animate-spin",m("size-6 text-gray-200 dark:text-gray-300",t)),"data-max":s,"data-min":0,"data-value":y,height:"100%",role:"progressbar",width:"100%",...a,children:[c("circle",{className:"[r:var(--radius)]",cx:"50%",cy:"50%",fill:"transparent",stroke:"currentColor",strokeWidth:u,style:{"--radius":W}}),e]})})};C.displayName="ProgressDonut";var $=.6,k=({className:e,...t})=>{let o=G(),r=A(V)??g,n=(r.value==="indeterminate"?$:r.value/r.max)*100,a=w(r.strokeWidth),s=I(a);return P("g",{className:m("text-accent-600",e),...t,children:[r.value==="indeterminate"&&c("defs",{children:P("linearGradient",{id:o,children:[c("stop",{className:"stop-opacity-100 stop-color-current",offset:"0%"}),c("stop",{className:"stop-opacity-0 stop-color-current",offset:"95%"})]})}),c("circle",{className:h("[r:var(--radius)]","origin-center"),cx:"50%",cy:"50%",fill:"transparent",pathLength:100,stroke:r.value==="indeterminate"?`url(#${o})`:"currentColor",strokeDasharray:100,strokeDashoffset:100-n,strokeLinecap:"round",strokeWidth:a,style:{"--radius":s},transform:"rotate(-90)"})]})};k.displayName="ProgressDonutIndicator";function w(e){let t=4;if(e==null)return t;typeof e=="number"?t=e:e.endsWith("rem")?t=Number(e.replace("rem",""))*16:t=Number(e);let o=Number.isNaN(t)?4:t;return N(o,{min:1,max:12})}function I(e){return`calc(50% - ${e/2}px)`}import*as x from"@radix-ui/react-progress";import{createContext as B,useContext as E,useMemo as H}from"react";import{jsx as v}from"react/jsx-runtime";var b=100,O={max:b,value:0},S=B(O);function T({className:e,children:t,max:o=b,value:r,...n}){let a=p(o)?o:b,s=d(r,a)?r:r==null?0:"indeterminate",i=l(s)?s:void 0,u=H(()=>({max:a,value:s}),[a,s]);return v(S.Provider,{value:u,children:v(x.Root,{"data-slot":"progress",className:m("bg-base-hover dark:bg-base shadow-inner relative h-3 w-full overflow-hidden rounded-md",e),value:i,max:a,...n,children:t})})}T.displayName="Root";function M({className:e,style:t,...o}){let r=E(S),{max:n}=r,a=r.value==="indeterminate"?0:r.value,s=(n-a)/n*100;return v(x.Indicator,{"data-slot":"progress-indicator",className:m("bg-accent-600 h-full w-full flex-1 transition-all",e),style:{...t,transform:`translateX(-${s}%)`},...o})}M.displayName="Indicator";var z={Root:T,Indicator:M};export{z as ProgressBar,C as ProgressDonut,k as ProgressDonutIndicator};
2
2
  //# sourceMappingURL=progress.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/progress/progress-donut.tsx","../src/components/progress/math.ts","../src/components/progress/progress-bar.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { createContext, useContext, useId, useMemo } from \"react\";\nimport type { CSSProperties, ComponentProps, HTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport {\n\tclamp,\n\tisNumber,\n\tisValidMaxNumber,\n\tisValidValueNumber,\n} from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\ntype RemValue = `${number}rem`;\ntype StrokeWidth = number | RemValue;\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tstrokeWidth: StrokeWidth;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tstrokeWidth: \"0.25rem\",\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext =\n\tcreateContext<ProgressContextValue>(defaultContextValue);\n\ntype SvgAttributes = Omit<\n\tHTMLAttributes<SVGElement>,\n\t| \"viewBox\"\n\t| \"role\"\n\t| \"aria-valuemax\"\n\t| \"aria-valuemin\"\n\t| \"aria-valuenow\"\n\t| \"width\"\n\t| \"height\"\n>;\n\ntype Props = SvgAttributes & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The width of the progress bar stroke.\n\t * Note, we clamp the stroke width to a minimum of 1px and max of 12px since\n\t * it is proportional to the viewbox size (0 0 32 32).\n\t *\n\t * @default 0.25rem (4px)\n\t */\n\tstrokeWidth?: StrokeWidth;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate.\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * A simple circular progress bar which shows the completion progress of a task.\n *\n * The indicator color is inherited via `currentColor`. Override the default\n * (`accent-600`) by setting the `ProgressDonutIndicator`'s text color.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut\n *\n * @example\n * ```tsx\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator />\n * </ProgressDonut>\n *\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator color=\"text-danger-600\" />\n * </ProgressDonut>\n * ```\n */\nconst ProgressDonut = ({\n\tchildren,\n\tclassName,\n\tmax: _max = defaultMax,\n\tstrokeWidth: _strokeWidth = 4,\n\tvalue: _value,\n\t...props\n}: Props) => {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max)\n\t\t\t? _value\n\t\t\t: _value == null\n\t\t\t\t? 0\n\t\t\t\t: \"indeterminate\"\n\t) satisfies ValueType;\n\tconst strokeWidthPx = deriveStrokeWidthPx(\n\t\t_strokeWidth ?? defaultContextValue.strokeWidth,\n\t);\n\tconst valueNow = isNumber(value) ? value : undefined;\n\tconst radius = calcRadius(strokeWidthPx);\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tstrokeWidth: strokeWidthPx,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, strokeWidthPx, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t{/* biome-ignore lint/a11y/useFocusableInteractive: progress bars don't need to be focusable */}\n\t\t\t<svg\n\t\t\t\taria-valuemax={max}\n\t\t\t\taria-valuemin={0}\n\t\t\t\taria-valuenow={valueNow}\n\t\t\t\tclassName={clsx(\n\t\t\t\t\tvalue === \"indeterminate\" &&\n\t\t\t\t\t\t\"animation-duration-[15s] transform-gpu animate-spin\",\n\t\t\t\t\tcx(\"size-6 text-gray-200 dark:text-gray-300\", className),\n\t\t\t\t)}\n\t\t\t\tdata-max={max}\n\t\t\t\tdata-min={0}\n\t\t\t\tdata-value={valueNow}\n\t\t\t\theight=\"100%\"\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: this is a radial progress bar, which is possible by SVG\n\t\t\t\trole=\"progressbar\"\n\t\t\t\twidth=\"100%\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<circle\n\t\t\t\t\tclassName=\"[r:var(--radius)]\"\n\t\t\t\t\tcx=\"50%\"\n\t\t\t\t\tcy=\"50%\"\n\t\t\t\t\tfill=\"transparent\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\t/>\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t</ProgressContext.Provider>\n\t);\n};\n\n/**\n * Length (value) of the progress indicator tail when the progress bar is indeterminate.\n */\nconst indeterminateTailPercent = 0.6;\n\ntype ProgressDonutIndicatorProps = Omit<ComponentProps<\"g\">, \"children\">;\n\n/**\n * The indicator for the circular progress bar.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut-indicator\n *\n * @example\n * ```tsx\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator />\n * </ProgressDonut>\n *\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator color=\"text-danger-600\" />\n * </ProgressDonut>\n * ```\n */\nconst ProgressDonutIndicator = ({\n\tclassName,\n\t...props\n}: ProgressDonutIndicatorProps) => {\n\tconst gradientId = useId();\n\tconst ctx = useContext(ProgressContext) ?? defaultContextValue;\n\tconst percentage =\n\t\t(ctx.value === \"indeterminate\"\n\t\t\t? indeterminateTailPercent\n\t\t\t: ctx.value / ctx.max) * 100;\n\tconst strokeWidthPx = deriveStrokeWidthPx(ctx.strokeWidth);\n\tconst radius = calcRadius(strokeWidthPx);\n\n\treturn (\n\t\t<g className={cx(\"text-accent-600\", className)} {...props}>\n\t\t\t{ctx.value === \"indeterminate\" && (\n\t\t\t\t<defs>\n\t\t\t\t\t<linearGradient id={gradientId}>\n\t\t\t\t\t\t<stop className=\"stop-opacity-100 stop-color-current\" offset=\"0%\" />\n\t\t\t\t\t\t<stop className=\"stop-opacity-0 stop-color-current\" offset=\"95%\" />\n\t\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t)}\n\t\t\t<circle\n\t\t\t\tclassName={clsx(\n\t\t\t\t\t\"[r:var(--radius)]\", // set the circle radius to be the value of the calc'd CSS variable set on the style\n\t\t\t\t\t\"origin-center\",\n\t\t\t\t)}\n\t\t\t\tcx=\"50%\"\n\t\t\t\tcy=\"50%\"\n\t\t\t\tfill=\"transparent\"\n\t\t\t\tpathLength={100}\n\t\t\t\tstroke={\n\t\t\t\t\tctx.value === \"indeterminate\" ? `url(#${gradientId})` : \"currentColor\"\n\t\t\t\t}\n\t\t\t\tstrokeDasharray={100}\n\t\t\t\tstrokeDashoffset={100 - percentage}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\ttransform=\"rotate(-90)\" // rotate -90 degrees so it starts from the top\n\t\t\t/>\n\t\t</g>\n\t);\n};\n\nexport {\n\t//,\n\tProgressDonut,\n\tProgressDonutIndicator,\n};\n\n/**\n * Derive the stroke width in pixels as a number value or pixels/rem from a string value.\n * Note, this function clamps the stroke width to a minimum of 1 and max of 12 since\n * it is proportional to the viewbox size (0 0 32 32).\n */\nexport function deriveStrokeWidthPx(\n\tstrokeWidth: number | string | undefined | null,\n): number {\n\tlet value = 4;\n\tif (strokeWidth == null) {\n\t\treturn value;\n\t}\n\n\tif (typeof strokeWidth === \"number\") {\n\t\tvalue = strokeWidth;\n\t} else if (strokeWidth.endsWith(\"rem\")) {\n\t\tvalue = Number(strokeWidth.replace(\"rem\", \"\")) * 16;\n\t} else {\n\t\tvalue = Number(strokeWidth);\n\t}\n\n\tconst stroke = Number.isNaN(value) ? 4 : value;\n\treturn clamp(stroke, { min: 1, max: 12 });\n}\n\n/**\n * Calculate the radius of the progress donut and indicator based on the stroke\n * width in pixels.\n */\nfunction calcRadius(strokeWidthPx: number) {\n\treturn `calc(50% - ${strokeWidthPx / 2}px)` as const;\n}\n","/**\n * Clamp a value between a minimum and maximum value.\n */\nfunction clamp(\n\tvalue: number,\n\t{ min, max }: { min: number; max: number },\n): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Check if a value is a number.\n */\nfunction isNumber(value: unknown): value is number {\n\treturn typeof value === \"number\";\n}\n\n/**\n * Check if a value is a valid number within the range of 0 to `max`.\n */\nfunction isValidValueNumber(value: unknown, max: number): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value <= max && value >= 0;\n}\n\n/**\n * Check if a value is a valid number greater than 0.\n */\nfunction isValidMaxNumber(value: unknown): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value > 0;\n}\n\nexport {\n\t//,\n\tclamp,\n\tisNumber,\n\tisValidValueNumber,\n\tisValidMaxNumber,\n};\n","\"use client\";\n\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\n\nimport { type ComponentProps, createContext, useContext, useMemo } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { isNumber, isValidMaxNumber, isValidValueNumber } from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext =\n\tcreateContext<ProgressContextValue>(defaultContextValue);\n\ntype RootProps = ComponentProps<\"div\"> & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate. (for now there is no visual difference than 0)\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.\n *\n * A horizontal progress bar that shows the completion progress of a task.\n * Use this component for linear progress indication.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * <ProgressBar.Root value={75} max={100}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Indeterminate progress\n * <ProgressBar.Root value=\"indeterminate\">\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nfunction Root({\n\tclassName,\n\tchildren,\n\tmax: _max = defaultMax,\n\tvalue: _value,\n\t...props\n}: RootProps) {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max)\n\t\t\t? _value\n\t\t\t: _value == null\n\t\t\t\t? 0\n\t\t\t\t: \"indeterminate\"\n\t) satisfies ValueType;\n\n\tconst valueNow = isNumber(value) ? value : undefined;\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<ProgressPrimitive.Root\n\t\t\t\tdata-slot=\"progress\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"bg-base-hover dark:bg-base shadow-inner relative h-3 w-full overflow-hidden rounded-md\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tvalue={valueNow}\n\t\t\t\tmax={max}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ProgressPrimitive.Root>\n\t\t</ProgressContext.Provider>\n\t);\n}\n\ntype IndicatorProps = ComponentProps<typeof ProgressPrimitive.Indicator>;\n\n/**\n * Displays the progress indicator, which visually represents the completion progress of a task.\n *\n * The visual indicator that shows the actual progress within the progress bar.\n * This component should be used inside a ProgressBar.Root component.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar-indicator\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Custom styled indicator\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator className=\"bg-success-600\" />\n * </ProgressBar.Root>\n * ```\n */\nfunction Indicator({ className, style, ...props }: IndicatorProps) {\n\tconst ctx = useContext(ProgressContext);\n\tconst { max } = ctx;\n\tconst value = ctx.value === \"indeterminate\" ? 0 : ctx.value;\n\tconst translatePercent = ((max - value) / max) * 100;\n\n\treturn (\n\t\t<ProgressPrimitive.Indicator\n\t\t\tdata-slot=\"progress-indicator\"\n\t\t\tclassName={cx(\n\t\t\t\t\"bg-accent-600 h-full w-full flex-1 transition-all\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{ ...style, transform: `translateX(-${translatePercent}%)` }}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n/**\n * A horizontal progress bar component that shows the completion progress of a task.\n *\n * @example\n * ```tsx\n * import { ProgressBar } from \"@ngrok/mantle/progress\";\n *\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nconst ProgressBar = {\n\tRoot,\n\tIndicator,\n} as const;\n\nexport {\n\t//,\n\tProgressBar,\n};\n"],"mappings":"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","names":["clsx","createContext","useContext","useId","useMemo","clamp","value","min","max","isNumber","isValidValueNumber","isValidMaxNumber","jsx","jsxs","defaultMax","defaultContextValue","ProgressContext","createContext","ProgressDonut","children","className","_max","_strokeWidth","_value","props","max","isValidMaxNumber","value","isValidValueNumber","strokeWidthPx","deriveStrokeWidthPx","valueNow","isNumber","radius","calcRadius","ctx","useMemo","clsx","cx","indeterminateTailPercent","ProgressDonutIndicator","gradientId","useId","useContext","percentage","deriveStrokeWidthPx","strokeWidth","value","stroke","clamp","calcRadius","strokeWidthPx","ProgressPrimitive","createContext","useContext","useMemo","jsx","defaultMax","defaultContextValue","ProgressContext","createContext","Root","className","children","_max","_value","props","max","isValidMaxNumber","value","isValidValueNumber","valueNow","isNumber","ctx","useMemo","cx","Indicator","style","useContext","translatePercent","ProgressBar"]}
1
+ {"version":3,"sources":["../src/components/progress/progress-donut.tsx","../src/components/progress/math.ts","../src/components/progress/progress-bar.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { createContext, useContext, useId, useMemo } from \"react\";\nimport type { CSSProperties, ComponentProps, HTMLAttributes } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport {\n\tclamp,\n\tisNumber,\n\tisValidMaxNumber,\n\tisValidValueNumber,\n} from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\ntype RemValue = `${number}rem`;\ntype StrokeWidth = number | RemValue;\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tstrokeWidth: StrokeWidth;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tstrokeWidth: \"0.25rem\",\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext =\n\tcreateContext<ProgressContextValue>(defaultContextValue);\n\ntype SvgAttributes = Omit<\n\tHTMLAttributes<SVGElement>,\n\t| \"viewBox\"\n\t| \"role\"\n\t| \"aria-valuemax\"\n\t| \"aria-valuemin\"\n\t| \"aria-valuenow\"\n\t| \"width\"\n\t| \"height\"\n>;\n\ntype Props = SvgAttributes & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The width of the progress bar stroke.\n\t * Note, we clamp the stroke width to a minimum of 1px and max of 12px since\n\t * it is proportional to the viewbox size (0 0 32 32).\n\t *\n\t * @default 0.25rem (4px)\n\t */\n\tstrokeWidth?: StrokeWidth;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate.\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * A simple circular progress bar which shows the completion progress of a task.\n *\n * The indicator color is inherited via `currentColor`. Override the default\n * (`accent-600`) by setting the `ProgressDonutIndicator`'s text color.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut\n *\n * @example\n * ```tsx\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator />\n * </ProgressDonut>\n *\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator color=\"text-danger-600\" />\n * </ProgressDonut>\n * ```\n */\nconst ProgressDonut = ({\n\tchildren,\n\tclassName,\n\tmax: _max = defaultMax,\n\tstrokeWidth: _strokeWidth = 4,\n\tvalue: _value,\n\t...props\n}: Props) => {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max)\n\t\t\t? _value\n\t\t\t: _value == null\n\t\t\t\t? 0\n\t\t\t\t: \"indeterminate\"\n\t) satisfies ValueType;\n\tconst strokeWidthPx = deriveStrokeWidthPx(\n\t\t_strokeWidth ?? defaultContextValue.strokeWidth,\n\t);\n\tconst valueNow = isNumber(value) ? value : undefined;\n\tconst radius = calcRadius(strokeWidthPx);\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tstrokeWidth: strokeWidthPx,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, strokeWidthPx, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t{/* biome-ignore lint/a11y/useFocusableInteractive: progress bars don't need to be focusable */}\n\t\t\t<svg\n\t\t\t\taria-valuemax={max}\n\t\t\t\taria-valuemin={0}\n\t\t\t\taria-valuenow={valueNow}\n\t\t\t\tclassName={clsx(\n\t\t\t\t\tvalue === \"indeterminate\" &&\n\t\t\t\t\t\t\"animation-duration-[15s] transform-gpu animate-spin\",\n\t\t\t\t\tcx(\"size-6 text-gray-200 dark:text-gray-300\", className),\n\t\t\t\t)}\n\t\t\t\tdata-max={max}\n\t\t\t\tdata-min={0}\n\t\t\t\tdata-value={valueNow}\n\t\t\t\theight=\"100%\"\n\t\t\t\t// biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: this is a radial progress bar, which is possible by SVG\n\t\t\t\trole=\"progressbar\"\n\t\t\t\twidth=\"100%\"\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t<circle\n\t\t\t\t\tclassName=\"[r:var(--radius)]\"\n\t\t\t\t\tcx=\"50%\"\n\t\t\t\t\tcy=\"50%\"\n\t\t\t\t\tfill=\"transparent\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\t/>\n\t\t\t\t{children}\n\t\t\t</svg>\n\t\t</ProgressContext.Provider>\n\t);\n};\nProgressDonut.displayName = \"ProgressDonut\";\n\n/**\n * Length (value) of the progress indicator tail when the progress bar is indeterminate.\n */\nconst indeterminateTailPercent = 0.6;\n\ntype ProgressDonutIndicatorProps = Omit<ComponentProps<\"g\">, \"children\">;\n\n/**\n * The indicator for the circular progress bar.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-donut-indicator\n *\n * @example\n * ```tsx\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator />\n * </ProgressDonut>\n *\n * <ProgressDonut value={60}>\n * <ProgressDonutIndicator color=\"text-danger-600\" />\n * </ProgressDonut>\n * ```\n */\nconst ProgressDonutIndicator = ({\n\tclassName,\n\t...props\n}: ProgressDonutIndicatorProps) => {\n\tconst gradientId = useId();\n\tconst ctx = useContext(ProgressContext) ?? defaultContextValue;\n\tconst percentage =\n\t\t(ctx.value === \"indeterminate\"\n\t\t\t? indeterminateTailPercent\n\t\t\t: ctx.value / ctx.max) * 100;\n\tconst strokeWidthPx = deriveStrokeWidthPx(ctx.strokeWidth);\n\tconst radius = calcRadius(strokeWidthPx);\n\n\treturn (\n\t\t<g className={cx(\"text-accent-600\", className)} {...props}>\n\t\t\t{ctx.value === \"indeterminate\" && (\n\t\t\t\t<defs>\n\t\t\t\t\t<linearGradient id={gradientId}>\n\t\t\t\t\t\t<stop className=\"stop-opacity-100 stop-color-current\" offset=\"0%\" />\n\t\t\t\t\t\t<stop className=\"stop-opacity-0 stop-color-current\" offset=\"95%\" />\n\t\t\t\t\t</linearGradient>\n\t\t\t\t</defs>\n\t\t\t)}\n\t\t\t<circle\n\t\t\t\tclassName={clsx(\n\t\t\t\t\t\"[r:var(--radius)]\", // set the circle radius to be the value of the calc'd CSS variable set on the style\n\t\t\t\t\t\"origin-center\",\n\t\t\t\t)}\n\t\t\t\tcx=\"50%\"\n\t\t\t\tcy=\"50%\"\n\t\t\t\tfill=\"transparent\"\n\t\t\t\tpathLength={100}\n\t\t\t\tstroke={\n\t\t\t\t\tctx.value === \"indeterminate\" ? `url(#${gradientId})` : \"currentColor\"\n\t\t\t\t}\n\t\t\t\tstrokeDasharray={100}\n\t\t\t\tstrokeDashoffset={100 - percentage}\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeWidth={strokeWidthPx}\n\t\t\t\tstyle={{ \"--radius\": radius } as CSSProperties}\n\t\t\t\ttransform=\"rotate(-90)\" // rotate -90 degrees so it starts from the top\n\t\t\t/>\n\t\t</g>\n\t);\n};\nProgressDonutIndicator.displayName = \"ProgressDonutIndicator\";\n\nexport {\n\t//,\n\tProgressDonut,\n\tProgressDonutIndicator,\n};\n\n/**\n * Derive the stroke width in pixels as a number value or pixels/rem from a string value.\n * Note, this function clamps the stroke width to a minimum of 1 and max of 12 since\n * it is proportional to the viewbox size (0 0 32 32).\n */\nexport function deriveStrokeWidthPx(\n\tstrokeWidth: number | string | undefined | null,\n): number {\n\tlet value = 4;\n\tif (strokeWidth == null) {\n\t\treturn value;\n\t}\n\n\tif (typeof strokeWidth === \"number\") {\n\t\tvalue = strokeWidth;\n\t} else if (strokeWidth.endsWith(\"rem\")) {\n\t\tvalue = Number(strokeWidth.replace(\"rem\", \"\")) * 16;\n\t} else {\n\t\tvalue = Number(strokeWidth);\n\t}\n\n\tconst stroke = Number.isNaN(value) ? 4 : value;\n\treturn clamp(stroke, { min: 1, max: 12 });\n}\n\n/**\n * Calculate the radius of the progress donut and indicator based on the stroke\n * width in pixels.\n */\nfunction calcRadius(strokeWidthPx: number) {\n\treturn `calc(50% - ${strokeWidthPx / 2}px)` as const;\n}\n","/**\n * Clamp a value between a minimum and maximum value.\n */\nfunction clamp(\n\tvalue: number,\n\t{ min, max }: { min: number; max: number },\n): number {\n\treturn Math.min(max, Math.max(min, value));\n}\n\n/**\n * Check if a value is a number.\n */\nfunction isNumber(value: unknown): value is number {\n\treturn typeof value === \"number\";\n}\n\n/**\n * Check if a value is a valid number within the range of 0 to `max`.\n */\nfunction isValidValueNumber(value: unknown, max: number): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value <= max && value >= 0;\n}\n\n/**\n * Check if a value is a valid number greater than 0.\n */\nfunction isValidMaxNumber(value: unknown): value is number {\n\treturn isNumber(value) && !Number.isNaN(value) && value > 0;\n}\n\nexport {\n\t//,\n\tclamp,\n\tisNumber,\n\tisValidValueNumber,\n\tisValidMaxNumber,\n};\n","\"use client\";\n\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\n\nimport { type ComponentProps, createContext, useContext, useMemo } from \"react\";\nimport { cx } from \"../../utils/cx/cx.js\";\nimport { isNumber, isValidMaxNumber, isValidValueNumber } from \"./math.js\";\nimport type { ValueType } from \"./types.js\";\n\n/**\n * The default maximum value of the progress bar.\n */\nconst defaultMax = 100;\n\ntype ProgressContextValue = {\n\tmax: number;\n\tvalue: ValueType;\n};\n\nconst defaultContextValue = {\n\tmax: defaultMax,\n\tvalue: 0,\n} as const satisfies ProgressContextValue;\n\nconst ProgressContext =\n\tcreateContext<ProgressContextValue>(defaultContextValue);\n\ntype RootProps = ComponentProps<\"div\"> & {\n\t/**\n\t * The maximum value of the progress bar.\n\t * This attribute describes how much work the task indicated by the progress element requires.\n\t * The max attribute, if present, must have a value greater than 0. The default value is 100.\n\t *\n\t * @default 100\n\t */\n\tmax?: number | undefined;\n\t/**\n\t * The current value of the progress bar.\n\t * This attribute specifies how much of the task that has been completed.\n\t * It must be a valid floating point number between 0 and max, or between 0 and 100 if max is omitted.\n\t * If set to `\"indeterminate\"`, the progress bar is considered indeterminate. (for now there is no visual difference than 0)\n\t *\n\t * @default 0\n\t */\n\tvalue?: ValueType | undefined;\n};\n\n/**\n * Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.\n *\n * A horizontal progress bar that shows the completion progress of a task.\n * Use this component for linear progress indication.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * <ProgressBar.Root value={75} max={100}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Indeterminate progress\n * <ProgressBar.Root value=\"indeterminate\">\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nfunction Root({\n\tclassName,\n\tchildren,\n\tmax: _max = defaultMax,\n\tvalue: _value,\n\t...props\n}: RootProps) {\n\tconst max = isValidMaxNumber(_max) ? _max : defaultMax;\n\tconst value = (\n\t\tisValidValueNumber(_value, max)\n\t\t\t? _value\n\t\t\t: _value == null\n\t\t\t\t? 0\n\t\t\t\t: \"indeterminate\"\n\t) satisfies ValueType;\n\n\tconst valueNow = isNumber(value) ? value : undefined;\n\n\tconst ctx: ProgressContextValue = useMemo(\n\t\t() => ({\n\t\t\tmax,\n\t\t\tvalue,\n\t\t}),\n\t\t[max, value],\n\t);\n\n\treturn (\n\t\t<ProgressContext.Provider value={ctx}>\n\t\t\t<ProgressPrimitive.Root\n\t\t\t\tdata-slot=\"progress\"\n\t\t\t\tclassName={cx(\n\t\t\t\t\t\"bg-base-hover dark:bg-base shadow-inner relative h-3 w-full overflow-hidden rounded-md\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t\tvalue={valueNow}\n\t\t\t\tmax={max}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</ProgressPrimitive.Root>\n\t\t</ProgressContext.Provider>\n\t);\n}\nRoot.displayName = \"Root\";\n\ntype IndicatorProps = ComponentProps<typeof ProgressPrimitive.Indicator>;\n\n/**\n * Displays the progress indicator, which visually represents the completion progress of a task.\n *\n * The visual indicator that shows the actual progress within the progress bar.\n * This component should be used inside a ProgressBar.Root component.\n *\n * @see https://mantle.ngrok.com/components/progress#api-progress-bar-indicator\n *\n * @example\n * ```tsx\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n *\n * // Custom styled indicator\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator className=\"bg-success-600\" />\n * </ProgressBar.Root>\n * ```\n */\nfunction Indicator({ className, style, ...props }: IndicatorProps) {\n\tconst ctx = useContext(ProgressContext);\n\tconst { max } = ctx;\n\tconst value = ctx.value === \"indeterminate\" ? 0 : ctx.value;\n\tconst translatePercent = ((max - value) / max) * 100;\n\n\treturn (\n\t\t<ProgressPrimitive.Indicator\n\t\t\tdata-slot=\"progress-indicator\"\n\t\t\tclassName={cx(\n\t\t\t\t\"bg-accent-600 h-full w-full flex-1 transition-all\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\tstyle={{ ...style, transform: `translateX(-${translatePercent}%)` }}\n\t\t\t{...props}\n\t\t/>\n\t);\n}\nIndicator.displayName = \"Indicator\";\n\n/**\n * A horizontal progress bar component that shows the completion progress of a task.\n *\n * @example\n * ```tsx\n * import { ProgressBar } from \"@ngrok/mantle/progress\";\n *\n * <ProgressBar.Root value={60}>\n * <ProgressBar.Indicator />\n * </ProgressBar.Root>\n * ```\n */\nconst ProgressBar = {\n\tRoot,\n\tIndicator,\n} as const;\n\nexport {\n\t//,\n\tProgressBar,\n};\n"],"mappings":"wCAAA,OAAOA,MAAU,OACjB,OAAS,iBAAAC,EAAe,cAAAC,EAAY,SAAAC,EAAO,WAAAC,MAAe,QCE1D,SAASC,EACRC,EACA,CAAE,IAAAC,EAAK,IAAAC,CAAI,EACF,CACT,OAAO,KAAK,IAAIA,EAAK,KAAK,IAAID,EAAKD,CAAK,CAAC,CAC1C,CAKA,SAASG,EAASH,EAAiC,CAClD,OAAO,OAAOA,GAAU,QACzB,CAKA,SAASI,EAAmBJ,EAAgBE,EAA8B,CACzE,OAAOC,EAASH,CAAK,GAAK,CAAC,OAAO,MAAMA,CAAK,GAAKA,GAASE,GAAOF,GAAS,CAC5E,CAKA,SAASK,EAAiBL,EAAiC,CAC1D,OAAOG,EAASH,CAAK,GAAK,CAAC,OAAO,MAAMA,CAAK,GAAKA,EAAQ,CAC3D,CDkGG,OAkBC,OAAAM,EAlBD,QAAAC,MAAA,oBA7GH,IAAMC,EAAa,IAQbC,EAAsB,CAC3B,IAAKD,EACL,YAAa,UACb,MAAO,CACR,EAEME,EACLC,EAAoCF,CAAmB,EA4DlDG,EAAgB,CAAC,CACtB,SAAAC,EACA,UAAAC,EACA,IAAKC,EAAOP,EACZ,YAAaQ,EAAe,EAC5B,MAAOC,EACP,GAAGC,CACJ,IAAa,CACZ,IAAMC,EAAMC,EAAiBL,CAAI,EAAIA,EAAOP,EACtCa,EACLC,EAAmBL,EAAQE,CAAG,EAC3BF,EACAA,GAAU,KACT,EACA,gBAECM,EAAgBC,EACrBR,GAAgBP,EAAoB,WACrC,EACMgB,EAAWC,EAASL,CAAK,EAAIA,EAAQ,OACrCM,EAASC,EAAWL,CAAa,EAEjCM,EAA4BC,EACjC,KAAO,CACN,IAAAX,EACA,YAAaI,EACb,MAAAF,CACD,GACA,CAACF,EAAKI,EAAeF,CAAK,CAC3B,EAEA,OACCf,EAACI,EAAgB,SAAhB,CAAyB,MAAOmB,EAEhC,SAAAtB,EAAC,OACA,gBAAeY,EACf,gBAAe,EACf,gBAAeM,EACf,UAAWM,EACVV,IAAU,iBACT,sDACDW,EAAG,0CAA2ClB,CAAS,CACxD,EACA,WAAUK,EACV,WAAU,EACV,aAAYM,EACZ,OAAO,OAEP,KAAK,cACL,MAAM,OACL,GAAGP,EAEJ,UAAAZ,EAAC,UACA,UAAU,oBACV,GAAG,MACH,GAAG,MACH,KAAK,cACL,OAAO,eACP,YAAaiB,EACb,MAAO,CAAE,WAAYI,CAAO,EAC7B,EACCd,GACF,EACD,CAEF,EACAD,EAAc,YAAc,gBAK5B,IAAMqB,EAA2B,GAoB3BC,EAAyB,CAAC,CAC/B,UAAApB,EACA,GAAGI,CACJ,IAAmC,CAClC,IAAMiB,EAAaC,EAAM,EACnBP,EAAMQ,EAAW3B,CAAe,GAAKD,EACrC6B,GACJT,EAAI,QAAU,gBACZI,EACAJ,EAAI,MAAQA,EAAI,KAAO,IACrBN,EAAgBC,EAAoBK,EAAI,WAAW,EACnDF,EAASC,EAAWL,CAAa,EAEvC,OACChB,EAAC,KAAE,UAAWyB,EAAG,kBAAmBlB,CAAS,EAAI,GAAGI,EAClD,UAAAW,EAAI,QAAU,iBACdvB,EAAC,QACA,SAAAC,EAAC,kBAAe,GAAI4B,EACnB,UAAA7B,EAAC,QAAK,UAAU,sCAAsC,OAAO,KAAK,EAClEA,EAAC,QAAK,UAAU,oCAAoC,OAAO,MAAM,GAClE,EACD,EAEDA,EAAC,UACA,UAAWyB,EACV,oBACA,eACD,EACA,GAAG,MACH,GAAG,MACH,KAAK,cACL,WAAY,IACZ,OACCF,EAAI,QAAU,gBAAkB,QAAQM,CAAU,IAAM,eAEzD,gBAAiB,IACjB,iBAAkB,IAAMG,EACxB,cAAc,QACd,YAAaf,EACb,MAAO,CAAE,WAAYI,CAAO,EAC5B,UAAU,cACX,GACD,CAEF,EACAO,EAAuB,YAAc,yBAa9B,SAASK,EACfC,EACS,CACT,IAAIC,EAAQ,EACZ,GAAID,GAAe,KAClB,OAAOC,EAGJ,OAAOD,GAAgB,SAC1BC,EAAQD,EACEA,EAAY,SAAS,KAAK,EACpCC,EAAQ,OAAOD,EAAY,QAAQ,MAAO,EAAE,CAAC,EAAI,GAEjDC,EAAQ,OAAOD,CAAW,EAG3B,IAAME,EAAS,OAAO,MAAMD,CAAK,EAAI,EAAIA,EACzC,OAAOE,EAAMD,EAAQ,CAAE,IAAK,EAAG,IAAK,EAAG,CAAC,CACzC,CAMA,SAASE,EAAWC,EAAuB,CAC1C,MAAO,cAAcA,EAAgB,CAAC,KACvC,CE1QA,UAAYC,MAAuB,2BAEnC,OAA8B,iBAAAC,EAAe,cAAAC,EAAY,WAAAC,MAAe,QA+FrE,cAAAC,MAAA,oBAvFH,IAAMC,EAAa,IAObC,EAAsB,CAC3B,IAAKD,EACL,MAAO,CACR,EAEME,EACLC,EAAoCF,CAAmB,EA8CxD,SAASG,EAAK,CACb,UAAAC,EACA,SAAAC,EACA,IAAKC,EAAOP,EACZ,MAAOQ,EACP,GAAGC,CACJ,EAAc,CACb,IAAMC,EAAMC,EAAiBJ,CAAI,EAAIA,EAAOP,EACtCY,EACLC,EAAmBL,EAAQE,CAAG,EAC3BF,EACAA,GAAU,KACT,EACA,gBAGCM,EAAWC,EAASH,CAAK,EAAIA,EAAQ,OAErCI,EAA4BC,EACjC,KAAO,CACN,IAAAP,EACA,MAAAE,CACD,GACA,CAACF,EAAKE,CAAK,CACZ,EAEA,OACCb,EAACG,EAAgB,SAAhB,CAAyB,MAAOc,EAChC,SAAAjB,EAAmB,OAAlB,CACA,YAAU,WACV,UAAWmB,EACV,yFACAb,CACD,EACA,MAAOS,EACP,IAAKJ,EACJ,GAAGD,EAEH,SAAAH,EACF,EACD,CAEF,CACAF,EAAK,YAAc,OAwBnB,SAASe,EAAU,CAAE,UAAAd,EAAW,MAAAe,EAAO,GAAGX,CAAM,EAAmB,CAClE,IAAMO,EAAMK,EAAWnB,CAAe,EAChC,CAAE,IAAAQ,CAAI,EAAIM,EACVJ,EAAQI,EAAI,QAAU,gBAAkB,EAAIA,EAAI,MAChDM,GAAqBZ,EAAME,GAASF,EAAO,IAEjD,OACCX,EAAmB,YAAlB,CACA,YAAU,qBACV,UAAWmB,EACV,oDACAb,CACD,EACA,MAAO,CAAE,GAAGe,EAAO,UAAW,eAAeE,CAAgB,IAAK,EACjE,GAAGb,EACL,CAEF,CACAU,EAAU,YAAc,YAcxB,IAAMI,EAAc,CACnB,KAAAnB,EACA,UAAAe,CACD","names":["clsx","createContext","useContext","useId","useMemo","clamp","value","min","max","isNumber","isValidValueNumber","isValidMaxNumber","jsx","jsxs","defaultMax","defaultContextValue","ProgressContext","createContext","ProgressDonut","children","className","_max","_strokeWidth","_value","props","max","isValidMaxNumber","value","isValidValueNumber","strokeWidthPx","deriveStrokeWidthPx","valueNow","isNumber","radius","calcRadius","ctx","useMemo","clsx","cx","indeterminateTailPercent","ProgressDonutIndicator","gradientId","useId","useContext","percentage","deriveStrokeWidthPx","strokeWidth","value","stroke","clamp","calcRadius","strokeWidthPx","ProgressPrimitive","createContext","useContext","useMemo","jsx","defaultMax","defaultContextValue","ProgressContext","createContext","Root","className","children","_max","_value","props","max","isValidMaxNumber","value","isValidValueNumber","valueNow","isNumber","ctx","useMemo","cx","Indicator","style","useContext","translatePercent","ProgressBar"]}