alouette 20.2.0 → 20.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/bin/install-skills.mjs +72 -0
  2. package/dist/definitions/animationDurationsMs.d.ts +3 -0
  3. package/dist/definitions/animationDurationsMs.d.ts.map +1 -1
  4. package/dist/definitions/core/useColorToken.d.ts +9 -0
  5. package/dist/definitions/core/useColorToken.d.ts.map +1 -0
  6. package/dist/definitions/index.d.ts +8 -0
  7. package/dist/definitions/index.d.ts.map +1 -1
  8. package/dist/definitions/ui/containers/AlertDialog.d.ts +78 -0
  9. package/dist/definitions/ui/containers/AlertDialog.d.ts.map +1 -0
  10. package/dist/definitions/ui/containers/AlertDialog.stories.d.ts +33 -0
  11. package/dist/definitions/ui/containers/AlertDialog.stories.d.ts.map +1 -0
  12. package/dist/definitions/ui/containers/Modal.d.ts +66 -0
  13. package/dist/definitions/ui/containers/Modal.d.ts.map +1 -0
  14. package/dist/definitions/ui/containers/Modal.stories.d.ts +31 -0
  15. package/dist/definitions/ui/containers/Modal.stories.d.ts.map +1 -0
  16. package/dist/definitions/ui/feedback/CircularProgress.d.ts +21 -0
  17. package/dist/definitions/ui/feedback/CircularProgress.d.ts.map +1 -0
  18. package/dist/definitions/ui/feedback/CircularProgress.stories.d.ts +38 -0
  19. package/dist/definitions/ui/feedback/CircularProgress.stories.d.ts.map +1 -0
  20. package/dist/definitions/ui/feedback/LinearProgress.d.ts +21 -0
  21. package/dist/definitions/ui/feedback/LinearProgress.d.ts.map +1 -0
  22. package/dist/definitions/ui/feedback/LinearProgress.stories.d.ts +38 -0
  23. package/dist/definitions/ui/feedback/LinearProgress.stories.d.ts.map +1 -0
  24. package/dist/definitions/ui/feedback/RingCircle.d.ts +16 -0
  25. package/dist/definitions/ui/feedback/RingCircle.d.ts.map +1 -0
  26. package/dist/definitions/ui/feedback/RingCircle.web.d.ts +4 -0
  27. package/dist/definitions/ui/feedback/RingCircle.web.d.ts.map +1 -0
  28. package/dist/definitions/ui/feedback/useSimulatedProgress.d.ts +5 -0
  29. package/dist/definitions/ui/feedback/useSimulatedProgress.d.ts.map +1 -0
  30. package/dist/definitions/ui/primitives/Icon.d.ts +2 -1
  31. package/dist/definitions/ui/primitives/Icon.d.ts.map +1 -1
  32. package/dist/definitions/ui/story-components/IndeterminateToggleDemo.d.ts +7 -0
  33. package/dist/definitions/ui/story-components/IndeterminateToggleDemo.d.ts.map +1 -0
  34. package/dist/index-browser.es.js +380 -32
  35. package/dist/index-browser.es.js.map +1 -1
  36. package/dist/index-node22.cjs +411 -28
  37. package/dist/index-node22.cjs.map +1 -1
  38. package/dist/index-node22.mjs +407 -32
  39. package/dist/index-node22.mjs.map +1 -1
  40. package/dist/index-react-native.cjs.js +411 -28
  41. package/dist/index-react-native.cjs.js.map +1 -1
  42. package/dist/index-react-native.es.js +407 -32
  43. package/dist/index-react-native.es.js.map +1 -1
  44. package/package.json +6 -2
  45. package/src/animationDurationsMs.ts +4 -1
  46. package/src/config/defaultColorScales.ts +1 -1
  47. package/src/core/useColorToken.ts +31 -0
  48. package/src/global.css +21 -12
  49. package/src/index.ts +25 -0
  50. package/src/themeVariables.ts +6 -6
  51. package/src/ui/containers/AlertDialog.stories.tsx +425 -0
  52. package/src/ui/containers/AlertDialog.tsx +211 -0
  53. package/src/ui/containers/Box.tsx +1 -1
  54. package/src/ui/containers/Modal.stories.tsx +231 -0
  55. package/src/ui/containers/Modal.tsx +197 -0
  56. package/src/ui/feedback/CircularProgress.stories.tsx +100 -0
  57. package/src/ui/feedback/CircularProgress.tsx +118 -0
  58. package/src/ui/feedback/ConnectionState.tsx +2 -2
  59. package/src/ui/feedback/LinearProgress.stories.tsx +101 -0
  60. package/src/ui/feedback/LinearProgress.tsx +77 -0
  61. package/src/ui/feedback/RingCircle.tsx +83 -0
  62. package/src/ui/feedback/RingCircle.web.tsx +39 -0
  63. package/src/ui/feedback/useSimulatedProgress.ts +66 -0
  64. package/src/ui/inputs/InputText.tsx +1 -1
  65. package/src/ui/inputs/Select.shared.tsx +1 -1
  66. package/src/ui/inputs/Select.web.tsx +2 -2
  67. package/src/ui/inputs/Switch.web.tsx +2 -2
  68. package/src/ui/primitives/Icon.tsx +4 -22
  69. package/src/ui/story-components/IndeterminateToggleDemo.tsx +29 -0
@@ -1,14 +1,15 @@
1
1
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
2
  import { VariableContextProvider, styled as styled$1 } from 'nativewind';
3
- import { createContext, useContext, forwardRef, Children, cloneElement, Fragment, useRef, useState, useEffect, isValidElement, useCallback } from 'react';
4
- import { useColorScheme, View as View$1, Text as Text$1, ScrollView as ScrollView$1, FlatList as FlatList$1, SectionList as SectionList$1, Pressable, Platform, TextInput, useWindowDimensions } from 'react-native-web';
3
+ import { createContext, useContext, forwardRef, Children, cloneElement, Fragment, useRef, useState, useEffect, isValidElement, useId, useCallback } from 'react';
4
+ import { useColorScheme, View as View$1, Text as Text$1, ScrollView as ScrollView$1, FlatList as FlatList$1, SectionList as SectionList$1, Pressable, Platform, useWindowDimensions, Modal as Modal$1, TextInput } from 'react-native-web';
5
5
  import { extendTailwindMerge, twMerge as twMerge$1 } from 'tailwind-merge';
6
6
  import { tv } from 'tailwind-variants';
7
- import { CaretDownRegularIcon } from 'alouette-icons/phosphor-icons/CaretDownRegularIcon';
7
+ import { XRegularIcon } from 'alouette-icons/phosphor-icons/XRegularIcon';
8
8
  import { CheckRegularIcon } from 'alouette-icons/phosphor-icons/CheckRegularIcon';
9
9
  import { InfoRegularIcon } from 'alouette-icons/phosphor-icons/InfoRegularIcon';
10
+ import { QuestionRegularIcon } from 'alouette-icons/phosphor-icons/QuestionRegularIcon';
10
11
  import { WarningRegularIcon } from 'alouette-icons/phosphor-icons/WarningRegularIcon';
11
- import { XRegularIcon } from 'alouette-icons/phosphor-icons/XRegularIcon';
12
+ import { CaretDownRegularIcon } from 'alouette-icons/phosphor-icons/CaretDownRegularIcon';
12
13
  import { CaretRightRegularIcon } from 'alouette-icons/phosphor-icons/CaretRightRegularIcon';
13
14
 
14
15
  const ThemeContext = createContext("light");
@@ -35,7 +36,7 @@ const themeVariables = {
35
36
  "--color-interactive-accent-contained-bg-disabled": "#EBEBEB",
36
37
  "--color-interactive-accent-outlined-disabled": "#B8B8B8",
37
38
  "--color-screen": "#EBEBEB",
38
- "--color-surface": "#F5F5F5",
39
+ "--color-surface": "#FAFAFA",
39
40
  "--color-highlight": "#FFFFFF",
40
41
  "--color-enabled": "#C7C7C7",
41
42
  "--color-highlight-accent": "#E0E0E0",
@@ -46,8 +47,8 @@ const themeVariables = {
46
47
  "--color-border-muted": "#8F8F8F",
47
48
  "--color-border-sharp": "#616161",
48
49
  "--color-interactive-contained-pressable": "#FFFFFF",
49
- "--color-interactive-contained-hover": "#F5F5F5",
50
- "--color-interactive-contained-focus": "#F5F5F5",
50
+ "--color-interactive-contained-hover": "#FAFAFA",
51
+ "--color-interactive-contained-focus": "#FAFAFA",
51
52
  "--color-interactive-contained-active": "#EBEBEB",
52
53
  "--color-interactive-outlined-pressable": "#616161",
53
54
  "--color-interactive-outlined-hover": "#8F8F8F",
@@ -64,9 +65,9 @@ const themeVariables = {
64
65
  "--color-on-accent-muted": "#616161",
65
66
  "--color-selection": "#47474740",
66
67
  "--color-interactive-accent-contained-bg": "#EBEBEB",
67
- "--color-interactive-accent-contained-bg-hover": "#F5F5F5",
68
- "--color-interactive-accent-contained-bg-focus": "#F5F5F5",
69
- "--color-interactive-accent-contained-bg-active": "#F5F5F5"
68
+ "--color-interactive-accent-contained-bg-hover": "#FAFAFA",
69
+ "--color-interactive-accent-contained-bg-focus": "#FAFAFA",
70
+ "--color-interactive-accent-contained-bg-active": "#FAFAFA"
70
71
  },
71
72
  "dark": {
72
73
  "--color-translucent": "#1f1e1e55",
@@ -784,7 +785,7 @@ const interactiveBoxVariants = tv({
784
785
  base: [
785
786
  boxBaseClasses,
786
787
  "cursor-pointer",
787
- "transition-[transform,background-color,border-color] duration-200 ease-in",
788
+ "transition-[transform,background-color,border-color] duration-fast ease-in",
788
789
  "disabled:cursor-not-allowed disabled:opacity-70 aria-disabled:cursor-not-allowed aria-disabled:opacity-70",
789
790
  "active:scale-[0.975]"
790
791
  ].join(" "),
@@ -1250,21 +1251,12 @@ function PresenceOne({
1250
1251
 
1251
1252
  const animationDurationsMs = {
1252
1253
  "slide": 600,
1253
- "collapse": 800
1254
+ "collapse": 800,
1255
+ "progress": 300,
1256
+ "fade": 300,
1257
+ "fast": 200
1254
1258
  };
1255
1259
 
1256
- function Icon({
1257
- icon,
1258
- size = 20,
1259
- className = "text-sharp"
1260
- }) {
1261
- return cloneElement(icon, {
1262
- className,
1263
- width: size,
1264
- height: size
1265
- });
1266
- }
1267
-
1268
1260
  const pressableBoxVariants = tv(
1269
1261
  {
1270
1262
  extend: interactiveBoxVariants,
@@ -1396,6 +1388,18 @@ const PressableBox = forwardRef(
1396
1388
  }
1397
1389
  );
1398
1390
 
1391
+ function Icon({
1392
+ icon,
1393
+ size = 20,
1394
+ className = "text-sharp"
1395
+ }) {
1396
+ return cloneElement(icon, {
1397
+ className,
1398
+ width: size,
1399
+ height: size
1400
+ });
1401
+ }
1402
+
1399
1403
  const buttonHeight = {
1400
1404
  sm: 38,
1401
1405
  md: 44
@@ -1607,12 +1611,231 @@ function IconButton({
1607
1611
  );
1608
1612
  }
1609
1613
 
1614
+ const panelVariants = tv(
1615
+ {
1616
+ // w-full so the panel shrinks on small screens (the backdrop padding keeps a
1617
+ // margin); max-w caps it on wide viewports.
1618
+ base: "w-full",
1619
+ variants: {
1620
+ size: {
1621
+ sm: "max-w-[360px]",
1622
+ md: "max-w-[520px]",
1623
+ lg: "max-w-[720px]"
1624
+ }
1625
+ },
1626
+ defaultVariants: { size: "md" }
1627
+ },
1628
+ { twMerge: false }
1629
+ );
1630
+ const titleReserveVariants = tv(
1631
+ {
1632
+ variants: {
1633
+ size: {
1634
+ sm: "pr-xxl",
1635
+ md: "pr-xl",
1636
+ lg: "pr-xl"
1637
+ }
1638
+ },
1639
+ defaultVariants: { size: "md" }
1640
+ },
1641
+ { twMerge: false }
1642
+ );
1643
+ function Modal({
1644
+ visible,
1645
+ onClose,
1646
+ children,
1647
+ icon,
1648
+ footer,
1649
+ accent,
1650
+ size = "md",
1651
+ title,
1652
+ hideCloseButton = false,
1653
+ closeButtonAriaLabel = "Close",
1654
+ role = "dialog",
1655
+ "aria-describedby": ariaDescribedby,
1656
+ testID,
1657
+ "aria-label": ariaLabel
1658
+ }) {
1659
+ const { height: windowHeight } = useWindowDimensions();
1660
+ const titleId = useId();
1661
+ return /* @__PURE__ */ jsx(AccentScope, { accent, children: /* @__PURE__ */ jsx(
1662
+ Modal$1,
1663
+ {
1664
+ transparent: true,
1665
+ visible,
1666
+ animationType: "fade",
1667
+ onRequestClose: onClose,
1668
+ children: /* @__PURE__ */ jsxs(View, { className: "flex-1 flex-center p-l", children: [
1669
+ /* @__PURE__ */ jsx(
1670
+ Pressable,
1671
+ {
1672
+ "aria-hidden": true,
1673
+ focusable: false,
1674
+ className: "absolute inset-0 bg-translucent",
1675
+ onPress: onClose
1676
+ }
1677
+ ),
1678
+ /* @__PURE__ */ jsx(
1679
+ View,
1680
+ {
1681
+ "aria-modal": true,
1682
+ role,
1683
+ "aria-label": title === void 0 ? ariaLabel : void 0,
1684
+ "aria-labelledby": title === void 0 ? void 0 : titleId,
1685
+ "aria-describedby": ariaDescribedby,
1686
+ testID,
1687
+ className: `relative ${panelVariants({ size })}`,
1688
+ children: /* @__PURE__ */ jsxs(
1689
+ Surface,
1690
+ {
1691
+ variant: "highlight",
1692
+ size,
1693
+ shadow: "l",
1694
+ className: "relative gap-m",
1695
+ children: [
1696
+ title === void 0 && icon === void 0 ? null : /* @__PURE__ */ jsxs(
1697
+ HStack,
1698
+ {
1699
+ className: `items-center gap-xs ${hideCloseButton ? "" : titleReserveVariants({ size })}`,
1700
+ children: [
1701
+ icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, { icon, size: 24, className: "text-accent" }),
1702
+ title === void 0 ? null : /* @__PURE__ */ jsx(
1703
+ Text,
1704
+ {
1705
+ nativeID: titleId,
1706
+ className: "shrink font-heading-bold text-xl leading-tight text-sharp",
1707
+ children: title
1708
+ }
1709
+ )
1710
+ ]
1711
+ }
1712
+ ),
1713
+ hideCloseButton ? null : /* @__PURE__ */ jsx(
1714
+ IconButton,
1715
+ {
1716
+ icon: /* @__PURE__ */ jsx(XRegularIcon, {}),
1717
+ variant: "ghost",
1718
+ size: size === "lg" ? "md" : size,
1719
+ "aria-label": closeButtonAriaLabel,
1720
+ className: "absolute right-sm top-sm",
1721
+ onPress: onClose
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ jsx(ScrollView, { style: { maxHeight: windowHeight * 0.7 }, children: /* @__PURE__ */ jsx(VStack, { className: "gap-m", children }) }),
1725
+ footer === void 0 ? null : /* @__PURE__ */ jsx(HStack, { className: "items-center justify-end gap-m", children: footer })
1726
+ ]
1727
+ }
1728
+ )
1729
+ }
1730
+ )
1731
+ ] })
1732
+ }
1733
+ ) });
1734
+ }
1735
+
1736
+ function resolveVariant(props, accent) {
1737
+ switch (props.variant) {
1738
+ case "alert": {
1739
+ const { onClose, closeText } = props;
1740
+ return {
1741
+ onDismiss: onClose,
1742
+ footer: /* @__PURE__ */ jsx(Button, { accent, text: closeText ?? "OK", onPress: onClose })
1743
+ };
1744
+ }
1745
+ case "required": {
1746
+ const { onConfirm, confirmText, confirmDisabled } = props;
1747
+ return {
1748
+ // Non-dismissible: only the explicit action closes it.
1749
+ onDismiss: () => void 0,
1750
+ footer: /* @__PURE__ */ jsx(
1751
+ Button,
1752
+ {
1753
+ accent,
1754
+ text: confirmText ?? "OK",
1755
+ disabled: confirmDisabled,
1756
+ onPress: onConfirm
1757
+ }
1758
+ )
1759
+ };
1760
+ }
1761
+ case "confirm":
1762
+ case void 0:
1763
+ default: {
1764
+ const { onConfirm, onCancel, confirmText, cancelText, confirmDisabled } = props;
1765
+ return {
1766
+ onDismiss: onCancel,
1767
+ footer: /* @__PURE__ */ jsxs(Fragment$1, { children: [
1768
+ /* @__PURE__ */ jsx(
1769
+ Button,
1770
+ {
1771
+ variant: "outlined",
1772
+ text: cancelText ?? "Cancel",
1773
+ onPress: onCancel
1774
+ }
1775
+ ),
1776
+ /* @__PURE__ */ jsx(
1777
+ Button,
1778
+ {
1779
+ accent,
1780
+ text: confirmText ?? "Confirm",
1781
+ disabled: confirmDisabled,
1782
+ onPress: onConfirm
1783
+ }
1784
+ )
1785
+ ] })
1786
+ };
1787
+ }
1788
+ }
1789
+ }
1790
+ function AlertDialog(props) {
1791
+ const {
1792
+ visible,
1793
+ title,
1794
+ children,
1795
+ accent = "danger",
1796
+ icon,
1797
+ size = "md",
1798
+ testID
1799
+ } = props;
1800
+ const descriptionId = useId();
1801
+ const { footer, onDismiss } = resolveVariant(props, accent);
1802
+ return /* @__PURE__ */ jsx(
1803
+ Modal,
1804
+ {
1805
+ hideCloseButton: true,
1806
+ visible,
1807
+ role: "alertdialog",
1808
+ accent,
1809
+ size,
1810
+ title,
1811
+ icon,
1812
+ "aria-describedby": children === void 0 ? void 0 : descriptionId,
1813
+ testID,
1814
+ footer,
1815
+ onClose: onDismiss,
1816
+ children: children === void 0 ? null : /* @__PURE__ */ jsx(Text, { nativeID: descriptionId, className: "text-base text-muted", children })
1817
+ }
1818
+ );
1819
+ }
1820
+ function QuestionAlertDialog(props) {
1821
+ return /* @__PURE__ */ jsx(AlertDialog, { ...props, icon: /* @__PURE__ */ jsx(QuestionRegularIcon, {}) });
1822
+ }
1823
+ function WarningAlertDialog(props) {
1824
+ return /* @__PURE__ */ jsx(AlertDialog, { ...props, icon: /* @__PURE__ */ jsx(WarningRegularIcon, {}) });
1825
+ }
1826
+ function InfoAlertDialog(props) {
1827
+ return /* @__PURE__ */ jsx(AlertDialog, { ...props, icon: /* @__PURE__ */ jsx(InfoRegularIcon, {}) });
1828
+ }
1829
+ function SuccessAlertDialog(props) {
1830
+ return /* @__PURE__ */ jsx(AlertDialog, { ...props, icon: /* @__PURE__ */ jsx(CheckRegularIcon, {}) });
1831
+ }
1832
+
1610
1833
  const inputVariants = tv(
1611
1834
  {
1612
1835
  base: [
1613
1836
  "bg-highlight text-base text-sharp",
1614
1837
  "border",
1615
- "transition-[border-color,background-color,outline-color] duration-200 ease-in",
1838
+ "transition-[border-color,background-color,outline-color] duration-fast ease-in",
1616
1839
  "outline-interactive-outlined-pressable",
1617
1840
  // to have proper outline color transition
1618
1841
  process.env.EXPO_PUBLIC_STORYBOOK_ENABLED ? "" : "border-interactive-outlined-pressable",
@@ -1709,7 +1932,7 @@ const trackVariants = tv(
1709
1932
  "height-[36px] w-[58px]",
1710
1933
  // Must be identical to TRACK_HEIGHT and TRACK_WIDTH constants above
1711
1934
  "relative rounded-full overflow-hidden shadow-lowered pointer-events-auto",
1712
- "transition-background-color duration-200 ease-in",
1935
+ "transition-background-color duration-fast ease-in",
1713
1936
  "outline-interactive-outlined-outline-focus",
1714
1937
  "aria-disabled:bg-disabled-interactive-muted"
1715
1938
  ].join(" "),
@@ -1728,7 +1951,7 @@ const thumbVariants = tv(
1728
1951
  {
1729
1952
  base: [
1730
1953
  "absolute rounded-full shadow-s aria-disabled:shadow-none",
1731
- "transition-transform duration-200 ease-in",
1954
+ "transition-transform duration-fast ease-in",
1732
1955
  "bg-surface aria-disabled:bg-disabled-interactive"
1733
1956
  ].join(" ")
1734
1957
  },
@@ -1854,8 +2077,8 @@ function SelectTriggerContent({
1854
2077
  const wrapperVariants = tv(
1855
2078
  {
1856
2079
  base: [
1857
- "flex-row flex-1 rounded-md border min-h-11",
1858
- "transition-[border-color,outline-color] duration-200 ease-in",
2080
+ "relative flex-row flex-1 rounded-md border min-h-11",
2081
+ "transition-[border-color,outline-color] duration-fast ease-in",
1859
2082
  "outline-interactive-outlined-pressable"
1860
2083
  // for a proper outline color transition
1861
2084
  ].join(" "),
@@ -2059,8 +2282,133 @@ function ConnectionState({
2059
2282
  return /* @__PURE__ */ jsx(AccentScope, { accent, children: /* @__PURE__ */ jsx(
2060
2283
  View,
2061
2284
  {
2062
- className: `absolute inset-x-0 top-0 z-9 h-0.5 bg-interactive-contained-pressable shadow-m transition-transform duration-700 ease-in-out ${hidden ? "-translate-y-6" : "translate-y-0"}`,
2063
- children: state ? /* @__PURE__ */ jsx(Text, { className: "absolute left-1/2 top-0.5 h-5.5 w-50 -translate-x-1/2 rounded-b-sm bg-interactive-contained-pressable text-center leading-5.5 text-on-accent transition-colors duration-200", children }) : null
2285
+ className: `absolute inset-x-0 top-0 z-9 h-0.5 bg-interactive-contained-pressable shadow-m transition-transform duration-slide ease-in-out ${hidden ? "-translate-y-6" : "translate-y-0"}`,
2286
+ children: state ? /* @__PURE__ */ jsx(Text, { className: "absolute left-1/2 top-0.5 h-5.5 w-50 -translate-x-1/2 rounded-b-sm bg-interactive-contained-pressable text-center leading-5.5 text-on-accent transition-colors duration-fast", children }) : null
2287
+ }
2288
+ ) });
2289
+ }
2290
+
2291
+ const track = tv({
2292
+ base: "absolute inset-x-0 top-0 z-10 overflow-hidden transition-opacity duration-fade",
2293
+ variants: {
2294
+ size: {
2295
+ xs: "h-0.5",
2296
+ sm: "h-1",
2297
+ md: "h-1.5",
2298
+ lg: "h-2"
2299
+ },
2300
+ hidden: {
2301
+ true: "opacity-0",
2302
+ false: "opacity-100"
2303
+ }
2304
+ },
2305
+ defaultVariants: { size: "md", hidden: false }
2306
+ });
2307
+ function LinearProgress({
2308
+ progress,
2309
+ hidden = false,
2310
+ accent = "brand",
2311
+ size = "md"
2312
+ }) {
2313
+ return /* @__PURE__ */ jsx(AccentScope, { accent, children: /* @__PURE__ */ jsx(View, { pointerEvents: "none", className: track({ size, hidden }), children: /* @__PURE__ */ jsx(
2314
+ View,
2315
+ {
2316
+ className: "h-full bg-accent transition-[width] duration-progress ease-out",
2317
+ style: { width: `${progress}%` }
2318
+ }
2319
+ ) }) });
2320
+ }
2321
+
2322
+ function RingCircle({
2323
+ center,
2324
+ radius,
2325
+ strokeWidth,
2326
+ strokeDasharray,
2327
+ strokeDashoffset,
2328
+ className,
2329
+ width,
2330
+ height
2331
+ }) {
2332
+ return /* @__PURE__ */ jsx("svg", { className, width, height, children: /* @__PURE__ */ jsx(
2333
+ "circle",
2334
+ {
2335
+ cx: center,
2336
+ cy: center,
2337
+ r: radius,
2338
+ stroke: "currentColor",
2339
+ strokeWidth,
2340
+ strokeDasharray,
2341
+ strokeDashoffset,
2342
+ strokeLinecap: strokeDasharray == null ? void 0 : "round",
2343
+ transform: strokeDasharray == null ? void 0 : `rotate(-90 ${center} ${center})`,
2344
+ className: strokeDasharray == null ? void 0 : "transition-[stroke-dashoffset] duration-progress ease-out",
2345
+ fill: "none"
2346
+ }
2347
+ ) });
2348
+ }
2349
+
2350
+ const diameterBySize = {
2351
+ xs: 16,
2352
+ sm: 32,
2353
+ md: 64,
2354
+ lg: 128
2355
+ };
2356
+ const strokeWidthBySize = {
2357
+ xs: 2,
2358
+ sm: 4,
2359
+ md: 8,
2360
+ lg: 16
2361
+ };
2362
+ const ring = tv({
2363
+ base: "relative transition-opacity duration-fade",
2364
+ variants: {
2365
+ hidden: {
2366
+ true: "opacity-0",
2367
+ false: "opacity-100"
2368
+ }
2369
+ },
2370
+ defaultVariants: { hidden: false }
2371
+ });
2372
+ function CircularProgress({
2373
+ progress,
2374
+ hidden = false,
2375
+ accent = "brand",
2376
+ size = "md"
2377
+ }) {
2378
+ const diameter = diameterBySize[size];
2379
+ const strokeWidth = strokeWidthBySize[size];
2380
+ const radius = (diameter - strokeWidth) / 2;
2381
+ const circumference = 2 * Math.PI * radius;
2382
+ const clampedProgress = Math.min(Math.max(progress, 0), 100);
2383
+ const dashOffset = circumference * (1 - clampedProgress / 100);
2384
+ const center = diameter / 2;
2385
+ const trackRing = /* @__PURE__ */ jsx(RingCircle, { center, radius, strokeWidth });
2386
+ const fillRing = /* @__PURE__ */ jsx(
2387
+ RingCircle,
2388
+ {
2389
+ center,
2390
+ radius,
2391
+ strokeWidth,
2392
+ strokeDasharray: circumference,
2393
+ strokeDashoffset: dashOffset
2394
+ }
2395
+ );
2396
+ return /* @__PURE__ */ jsx(AccentScope, { accent, children: /* @__PURE__ */ jsxs(
2397
+ View,
2398
+ {
2399
+ className: ring({ hidden }),
2400
+ style: { width: diameter, height: diameter },
2401
+ children: [
2402
+ /* @__PURE__ */ jsx(View, { className: "absolute inset-0", children: /* @__PURE__ */ jsx(
2403
+ Icon,
2404
+ {
2405
+ icon: trackRing,
2406
+ size: diameter,
2407
+ className: "text-highlight-accent"
2408
+ }
2409
+ ) }),
2410
+ /* @__PURE__ */ jsx(View, { className: "absolute inset-0", children: /* @__PURE__ */ jsx(Icon, { icon: fillRing, size: diameter, className: "text-accent" }) })
2411
+ ]
2064
2412
  }
2065
2413
  ) });
2066
2414
  }
@@ -2311,5 +2659,5 @@ function ExternalLink({
2311
2659
  );
2312
2660
  }
2313
2661
 
2314
- export { AccentScope, AlouetteDecorator, AlouetteProvider, Badge, Box, BreakpointNameEnum, Breakpoints, Button, ConfirmationMessage, ConnectionState, ExternalLink, ExternalLinkButton, FlatList, GradientBackground, GradientScrollView, HStack, Icon, IconButton, InfoMessage, InputText, InteractiveBox, InternalLinkButton, Message, Paragraph, PresenceList, PresenceOne, PressableBox, PressableListItem, SafeAreaBox, SafeAreaProvider, ScopedTheme, ScrollView, SectionList, Select, Separator, Stack, Story, StoryContainer, StoryDecorator, StoryGrid, StoryTitle, Surface, Switch, SwitchBreakpointsUsingDisplayNone, SwitchBreakpointsUsingNull, Text, TextArea, VStack, View, WarningMessage, animationDurationsMs, styled, themeVariables, useCurrentBreakpointName, useCurrentBreakpointNameFiltered, useCurrentMode, useCurrentTheme, useSafeAreaInsets, useThemeToken };
2662
+ export { AccentScope, AlertDialog, AlouetteDecorator, AlouetteProvider, Badge, Box, BreakpointNameEnum, Breakpoints, Button, CircularProgress, ConfirmationMessage, ConnectionState, ExternalLink, ExternalLinkButton, FlatList, GradientBackground, GradientScrollView, HStack, Icon, IconButton, InfoAlertDialog, InfoMessage, InputText, InteractiveBox, InternalLinkButton, LinearProgress, Message, Modal, Paragraph, PresenceList, PresenceOne, PressableBox, PressableListItem, QuestionAlertDialog, SafeAreaBox, SafeAreaProvider, ScopedTheme, ScrollView, SectionList, Select, Separator, Stack, Story, StoryContainer, StoryDecorator, StoryGrid, StoryTitle, SuccessAlertDialog, Surface, Switch, SwitchBreakpointsUsingDisplayNone, SwitchBreakpointsUsingNull, Text, TextArea, VStack, View, WarningAlertDialog, WarningMessage, animationDurationsMs, styled, themeVariables, useCurrentBreakpointName, useCurrentBreakpointNameFiltered, useCurrentMode, useCurrentTheme, useSafeAreaInsets, useThemeToken };
2315
2663
  //# sourceMappingURL=index-browser.es.js.map