alouette 20.3.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 (56) 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 +4 -0
  7. package/dist/definitions/index.d.ts.map +1 -1
  8. package/dist/definitions/ui/feedback/CircularProgress.d.ts +21 -0
  9. package/dist/definitions/ui/feedback/CircularProgress.d.ts.map +1 -0
  10. package/dist/definitions/ui/feedback/CircularProgress.stories.d.ts +38 -0
  11. package/dist/definitions/ui/feedback/CircularProgress.stories.d.ts.map +1 -0
  12. package/dist/definitions/ui/feedback/LinearProgress.d.ts +21 -0
  13. package/dist/definitions/ui/feedback/LinearProgress.d.ts.map +1 -0
  14. package/dist/definitions/ui/feedback/LinearProgress.stories.d.ts +38 -0
  15. package/dist/definitions/ui/feedback/LinearProgress.stories.d.ts.map +1 -0
  16. package/dist/definitions/ui/feedback/RingCircle.d.ts +16 -0
  17. package/dist/definitions/ui/feedback/RingCircle.d.ts.map +1 -0
  18. package/dist/definitions/ui/feedback/RingCircle.web.d.ts +4 -0
  19. package/dist/definitions/ui/feedback/RingCircle.web.d.ts.map +1 -0
  20. package/dist/definitions/ui/feedback/useSimulatedProgress.d.ts +5 -0
  21. package/dist/definitions/ui/feedback/useSimulatedProgress.d.ts.map +1 -0
  22. package/dist/definitions/ui/primitives/Icon.d.ts +2 -1
  23. package/dist/definitions/ui/primitives/Icon.d.ts.map +1 -1
  24. package/dist/definitions/ui/story-components/IndeterminateToggleDemo.d.ts +7 -0
  25. package/dist/definitions/ui/story-components/IndeterminateToggleDemo.d.ts.map +1 -0
  26. package/dist/index-browser.es.js +144 -16
  27. package/dist/index-browser.es.js.map +1 -1
  28. package/dist/index-node22.cjs +171 -14
  29. package/dist/index-node22.cjs.map +1 -1
  30. package/dist/index-node22.mjs +170 -15
  31. package/dist/index-node22.mjs.map +1 -1
  32. package/dist/index-react-native.cjs.js +171 -14
  33. package/dist/index-react-native.cjs.js.map +1 -1
  34. package/dist/index-react-native.es.js +170 -15
  35. package/dist/index-react-native.es.js.map +1 -1
  36. package/package.json +6 -2
  37. package/src/animationDurationsMs.ts +4 -1
  38. package/src/core/useColorToken.ts +31 -0
  39. package/src/global.css +21 -12
  40. package/src/index.ts +12 -0
  41. package/src/themeVariables.ts +6 -6
  42. package/src/ui/containers/Box.tsx +1 -1
  43. package/src/ui/feedback/CircularProgress.stories.tsx +100 -0
  44. package/src/ui/feedback/CircularProgress.tsx +118 -0
  45. package/src/ui/feedback/ConnectionState.tsx +2 -2
  46. package/src/ui/feedback/LinearProgress.stories.tsx +101 -0
  47. package/src/ui/feedback/LinearProgress.tsx +77 -0
  48. package/src/ui/feedback/RingCircle.tsx +83 -0
  49. package/src/ui/feedback/RingCircle.web.tsx +39 -0
  50. package/src/ui/feedback/useSimulatedProgress.ts +66 -0
  51. package/src/ui/inputs/InputText.tsx +1 -1
  52. package/src/ui/inputs/Select.shared.tsx +1 -1
  53. package/src/ui/inputs/Select.web.tsx +2 -2
  54. package/src/ui/inputs/Switch.web.tsx +2 -2
  55. package/src/ui/primitives/Icon.tsx +4 -22
  56. package/src/ui/story-components/IndeterminateToggleDemo.tsx +29 -0
@@ -15,6 +15,8 @@ const InfoRegularIcon = require('alouette-icons/phosphor-icons/InfoRegularIcon')
15
15
  const QuestionRegularIcon = require('alouette-icons/phosphor-icons/QuestionRegularIcon');
16
16
  const WarningRegularIcon = require('alouette-icons/phosphor-icons/WarningRegularIcon');
17
17
  const CaretDownRegularIcon = require('alouette-icons/phosphor-icons/CaretDownRegularIcon');
18
+ const Animated = require('react-native-reanimated');
19
+ const reactNativeSvg = require('react-native-svg');
18
20
  const CaretRightRegularIcon = require('alouette-icons/phosphor-icons/CaretRightRegularIcon');
19
21
  const WebBrowser = require('expo-web-browser');
20
22
 
@@ -55,7 +57,7 @@ const themeVariables = {
55
57
  "--color-interactive-accent-contained-bg-disabled": "#EBEBEB",
56
58
  "--color-interactive-accent-outlined-disabled": "#B8B8B8",
57
59
  "--color-screen": "#EBEBEB",
58
- "--color-surface": "#F5F5F5",
60
+ "--color-surface": "#FAFAFA",
59
61
  "--color-highlight": "#FFFFFF",
60
62
  "--color-enabled": "#C7C7C7",
61
63
  "--color-highlight-accent": "#E0E0E0",
@@ -66,8 +68,8 @@ const themeVariables = {
66
68
  "--color-border-muted": "#8F8F8F",
67
69
  "--color-border-sharp": "#616161",
68
70
  "--color-interactive-contained-pressable": "#FFFFFF",
69
- "--color-interactive-contained-hover": "#F5F5F5",
70
- "--color-interactive-contained-focus": "#F5F5F5",
71
+ "--color-interactive-contained-hover": "#FAFAFA",
72
+ "--color-interactive-contained-focus": "#FAFAFA",
71
73
  "--color-interactive-contained-active": "#EBEBEB",
72
74
  "--color-interactive-outlined-pressable": "#616161",
73
75
  "--color-interactive-outlined-hover": "#8F8F8F",
@@ -84,9 +86,9 @@ const themeVariables = {
84
86
  "--color-on-accent-muted": "#616161",
85
87
  "--color-selection": "#47474740",
86
88
  "--color-interactive-accent-contained-bg": "#EBEBEB",
87
- "--color-interactive-accent-contained-bg-hover": "#F5F5F5",
88
- "--color-interactive-accent-contained-bg-focus": "#F5F5F5",
89
- "--color-interactive-accent-contained-bg-active": "#F5F5F5"
89
+ "--color-interactive-accent-contained-bg-hover": "#FAFAFA",
90
+ "--color-interactive-accent-contained-bg-focus": "#FAFAFA",
91
+ "--color-interactive-accent-contained-bg-active": "#FAFAFA"
90
92
  },
91
93
  "dark": {
92
94
  "--color-translucent": "#1f1e1e55",
@@ -793,7 +795,7 @@ const interactiveBoxVariants = tailwindVariants.tv({
793
795
  base: [
794
796
  boxBaseClasses,
795
797
  "cursor-pointer",
796
- "transition-[transform,background-color,border-color] duration-200 ease-in",
798
+ "transition-[transform,background-color,border-color] duration-fast ease-in",
797
799
  "disabled:cursor-not-allowed disabled:opacity-70 aria-disabled:cursor-not-allowed aria-disabled:opacity-70",
798
800
  "active:scale-[0.975]"
799
801
  ].join(" "),
@@ -1259,7 +1261,10 @@ function PresenceOne({
1259
1261
 
1260
1262
  const animationDurationsMs = {
1261
1263
  "slide": 600,
1262
- "collapse": 800
1264
+ "collapse": 800,
1265
+ "progress": 300,
1266
+ "fade": 300,
1267
+ "fast": 200
1263
1268
  };
1264
1269
 
1265
1270
  const pressableBoxVariants = tailwindVariants.tv(
@@ -1393,13 +1398,17 @@ const PressableBox = react.forwardRef(
1393
1398
  }
1394
1399
  );
1395
1400
 
1401
+ function useColorToken(className) {
1402
+ const token = className.split(/\s+/).find((part) => part.startsWith("text-"))?.slice("text-".length);
1403
+ return useThemeToken(`--color-${token ?? "sharp"}`);
1404
+ }
1405
+
1396
1406
  function Icon({
1397
1407
  icon,
1398
1408
  size = 20,
1399
1409
  className = "text-sharp"
1400
1410
  }) {
1401
- const token = className.split(/\s+/).find((part) => part.startsWith("text-"))?.slice("text-".length);
1402
- const color = useThemeToken(`--color-${token ?? "sharp"}`);
1411
+ const color = useColorToken(className);
1403
1412
  return react.cloneElement(icon, {
1404
1413
  color,
1405
1414
  width: size,
@@ -1842,7 +1851,7 @@ const inputVariants = tailwindVariants.tv(
1842
1851
  base: [
1843
1852
  "bg-highlight text-base text-sharp",
1844
1853
  "border",
1845
- "transition-[border-color,background-color,outline-color] duration-200 ease-in",
1854
+ "transition-[border-color,background-color,outline-color] duration-fast ease-in",
1846
1855
  "outline-interactive-outlined-pressable",
1847
1856
  // to have proper outline color transition
1848
1857
  process.env.EXPO_PUBLIC_STORYBOOK_ENABLED ? "" : "border-interactive-outlined-pressable",
@@ -1993,7 +2002,7 @@ function useControllableValue(controlled, defaultValue, onValueChange) {
1993
2002
  const selectTriggerBaseClassName = [
1994
2003
  "flex-row items-center justify-between gap-xs",
1995
2004
  "rounded-md border px-m py-xs min-h-[44px]",
1996
- "transition-[border-color,outline-color,background-color] duration-200 ease-in"
2005
+ "transition-[border-color,outline-color,background-color] duration-fast ease-in"
1997
2006
  ].join(" ");
1998
2007
  const triggerLabelVariants = tailwindVariants.tv({
1999
2008
  base: "flex-1 text-base",
@@ -2267,8 +2276,154 @@ function ConnectionState({
2267
2276
  return /* @__PURE__ */ jsxRuntime.jsx(AccentScope, { accent, children: /* @__PURE__ */ jsxRuntime.jsx(
2268
2277
  View,
2269
2278
  {
2270
- 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"}`,
2271
- children: state ? /* @__PURE__ */ jsxRuntime.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
2279
+ 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"}`,
2280
+ children: state ? /* @__PURE__ */ jsxRuntime.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
2281
+ }
2282
+ ) });
2283
+ }
2284
+
2285
+ const track = tailwindVariants.tv({
2286
+ base: "absolute inset-x-0 top-0 z-10 overflow-hidden transition-opacity duration-fade",
2287
+ variants: {
2288
+ size: {
2289
+ xs: "h-0.5",
2290
+ sm: "h-1",
2291
+ md: "h-1.5",
2292
+ lg: "h-2"
2293
+ },
2294
+ hidden: {
2295
+ true: "opacity-0",
2296
+ false: "opacity-100"
2297
+ }
2298
+ },
2299
+ defaultVariants: { size: "md", hidden: false }
2300
+ });
2301
+ function LinearProgress({
2302
+ progress,
2303
+ hidden = false,
2304
+ accent = "brand",
2305
+ size = "md"
2306
+ }) {
2307
+ return /* @__PURE__ */ jsxRuntime.jsx(AccentScope, { accent, children: /* @__PURE__ */ jsxRuntime.jsx(View, { pointerEvents: "none", className: track({ size, hidden }), children: /* @__PURE__ */ jsxRuntime.jsx(
2308
+ View,
2309
+ {
2310
+ className: "h-full bg-accent transition-[width] duration-progress ease-out",
2311
+ style: { width: `${progress}%` }
2312
+ }
2313
+ ) }) });
2314
+ }
2315
+
2316
+ const AnimatedCircle = Animated.createAnimatedComponent(reactNativeSvg.Circle);
2317
+ const easeOut = Animated.Easing.bezier(0, 0, 0.58, 1);
2318
+ function RingCircle({
2319
+ center,
2320
+ radius,
2321
+ strokeWidth,
2322
+ strokeDasharray,
2323
+ strokeDashoffset,
2324
+ color,
2325
+ width,
2326
+ height
2327
+ }) {
2328
+ const animatedOffset = Animated.useSharedValue(strokeDashoffset ?? 0);
2329
+ react.useEffect(() => {
2330
+ animatedOffset.value = Animated.withTiming(strokeDashoffset ?? 0, {
2331
+ duration: animationDurationsMs.progress,
2332
+ easing: easeOut
2333
+ });
2334
+ }, [animatedOffset, strokeDashoffset]);
2335
+ const animatedProps = Animated.useAnimatedProps(() => ({
2336
+ strokeDashoffset: animatedOffset.value
2337
+ }));
2338
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNativeSvg.Svg, { color, width, height, children: strokeDasharray == null ? /* @__PURE__ */ jsxRuntime.jsx(
2339
+ reactNativeSvg.Circle,
2340
+ {
2341
+ cx: center,
2342
+ cy: center,
2343
+ r: radius,
2344
+ stroke: "currentColor",
2345
+ strokeWidth,
2346
+ fill: "none"
2347
+ }
2348
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2349
+ AnimatedCircle,
2350
+ {
2351
+ animatedProps,
2352
+ cx: center,
2353
+ cy: center,
2354
+ r: radius,
2355
+ stroke: "currentColor",
2356
+ strokeWidth,
2357
+ strokeDasharray,
2358
+ strokeLinecap: "round",
2359
+ transform: `rotate(-90 ${center} ${center})`,
2360
+ fill: "none"
2361
+ }
2362
+ ) });
2363
+ }
2364
+
2365
+ const diameterBySize = {
2366
+ xs: 16,
2367
+ sm: 32,
2368
+ md: 64,
2369
+ lg: 128
2370
+ };
2371
+ const strokeWidthBySize = {
2372
+ xs: 2,
2373
+ sm: 4,
2374
+ md: 8,
2375
+ lg: 16
2376
+ };
2377
+ const ring = tailwindVariants.tv({
2378
+ base: "relative transition-opacity duration-fade",
2379
+ variants: {
2380
+ hidden: {
2381
+ true: "opacity-0",
2382
+ false: "opacity-100"
2383
+ }
2384
+ },
2385
+ defaultVariants: { hidden: false }
2386
+ });
2387
+ function CircularProgress({
2388
+ progress,
2389
+ hidden = false,
2390
+ accent = "brand",
2391
+ size = "md"
2392
+ }) {
2393
+ const diameter = diameterBySize[size];
2394
+ const strokeWidth = strokeWidthBySize[size];
2395
+ const radius = (diameter - strokeWidth) / 2;
2396
+ const circumference = 2 * Math.PI * radius;
2397
+ const clampedProgress = Math.min(Math.max(progress, 0), 100);
2398
+ const dashOffset = circumference * (1 - clampedProgress / 100);
2399
+ const center = diameter / 2;
2400
+ const trackRing = /* @__PURE__ */ jsxRuntime.jsx(RingCircle, { center, radius, strokeWidth });
2401
+ const fillRing = /* @__PURE__ */ jsxRuntime.jsx(
2402
+ RingCircle,
2403
+ {
2404
+ center,
2405
+ radius,
2406
+ strokeWidth,
2407
+ strokeDasharray: circumference,
2408
+ strokeDashoffset: dashOffset
2409
+ }
2410
+ );
2411
+ return /* @__PURE__ */ jsxRuntime.jsx(AccentScope, { accent, children: /* @__PURE__ */ jsxRuntime.jsxs(
2412
+ View,
2413
+ {
2414
+ className: ring({ hidden }),
2415
+ style: { width: diameter, height: diameter },
2416
+ children: [
2417
+ /* @__PURE__ */ jsxRuntime.jsx(View, { className: "absolute inset-0", children: /* @__PURE__ */ jsxRuntime.jsx(
2418
+ Icon,
2419
+ {
2420
+ icon: trackRing,
2421
+ size: diameter,
2422
+ className: "text-highlight-accent"
2423
+ }
2424
+ ) }),
2425
+ /* @__PURE__ */ jsxRuntime.jsx(View, { className: "absolute inset-0", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: fillRing, size: diameter, className: "text-accent" }) })
2426
+ ]
2272
2427
  }
2273
2428
  ) });
2274
2429
  }
@@ -2562,6 +2717,7 @@ exports.Box = Box;
2562
2717
  exports.BreakpointNameEnum = BreakpointNameEnum;
2563
2718
  exports.Breakpoints = Breakpoints;
2564
2719
  exports.Button = Button;
2720
+ exports.CircularProgress = CircularProgress;
2565
2721
  exports.ConfirmationMessage = ConfirmationMessage;
2566
2722
  exports.ConnectionState = ConnectionState;
2567
2723
  exports.ExternalLink = ExternalLink;
@@ -2577,6 +2733,7 @@ exports.InfoMessage = InfoMessage;
2577
2733
  exports.InputText = InputText;
2578
2734
  exports.InteractiveBox = InteractiveBox;
2579
2735
  exports.InternalLinkButton = InternalLinkButton;
2736
+ exports.LinearProgress = LinearProgress;
2580
2737
  exports.Message = Message;
2581
2738
  exports.Modal = Modal;
2582
2739
  exports.Paragraph = Paragraph;