@pickle-ui/react-native 1.0.0-beta.0 → 1.0.0-beta.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 (55) hide show
  1. package/README.md +44 -11
  2. package/dist/components/Badge.d.ts +6 -3
  3. package/dist/components/Badge.d.ts.map +1 -1
  4. package/dist/components/Badge.js +36 -7
  5. package/dist/components/Badge.js.map +1 -1
  6. package/dist/components/Button.d.ts +11 -4
  7. package/dist/components/Button.d.ts.map +1 -1
  8. package/dist/components/Button.js +97 -15
  9. package/dist/components/Button.js.map +1 -1
  10. package/dist/components/Card.d.ts +15 -5
  11. package/dist/components/Card.d.ts.map +1 -1
  12. package/dist/components/Card.js +28 -10
  13. package/dist/components/Card.js.map +1 -1
  14. package/dist/components/Text.d.ts +7 -3
  15. package/dist/components/Text.d.ts.map +1 -1
  16. package/dist/components/Text.js +23 -11
  17. package/dist/components/Text.js.map +1 -1
  18. package/dist/components/_internal/Spinner.d.ts +9 -0
  19. package/dist/components/_internal/Spinner.d.ts.map +1 -0
  20. package/dist/components/_internal/Spinner.js +31 -0
  21. package/dist/components/_internal/Spinner.js.map +1 -0
  22. package/dist/entries/card.d.ts +1 -1
  23. package/dist/entries/card.d.ts.map +1 -1
  24. package/dist/entries/theme.d.ts +3 -0
  25. package/dist/entries/theme.d.ts.map +1 -0
  26. package/dist/entries/theme.js +2 -0
  27. package/dist/entries/theme.js.map +1 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +1 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/lib/cn.d.ts.map +1 -1
  33. package/dist/lib/cn.js +13 -1
  34. package/dist/lib/cn.js.map +1 -1
  35. package/package.json +5 -2
  36. package/src/base.css +7 -2
  37. package/src/components/Badge.stories.tsx +51 -6
  38. package/src/components/Badge.test.tsx +15 -0
  39. package/src/components/Badge.tsx +73 -17
  40. package/src/components/Button.stories.tsx +96 -8
  41. package/src/components/Button.test.tsx +69 -0
  42. package/src/components/Button.tsx +156 -18
  43. package/src/components/Card.stories.tsx +17 -4
  44. package/src/components/Card.test.tsx +24 -1
  45. package/src/components/Card.tsx +71 -13
  46. package/src/components/Text.stories.tsx +52 -2
  47. package/src/components/Text.test.tsx +35 -3
  48. package/src/components/Text.tsx +42 -12
  49. package/src/components/_internal/Spinner.tsx +49 -0
  50. package/src/components/_internal/Story.tsx +34 -0
  51. package/src/entries/card.ts +2 -0
  52. package/src/entries/theme.ts +7 -0
  53. package/src/index.ts +1 -0
  54. package/src/lib/cn.test.ts +6 -0
  55. package/src/lib/cn.ts +14 -1
@@ -0,0 +1,49 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { Animated, Easing, Platform, View } from 'react-native';
3
+
4
+ import { cn } from '../../lib/cn';
5
+
6
+ /**
7
+ * The web `Spinner`'s look on native: a three-quarter ring turning once a
8
+ * second. Color it with a `border-*` class. Decorative: the control showing
9
+ * it reports the busy state.
10
+ */
11
+ export function Spinner({ className }: { className?: string }) {
12
+ const [turn] = useState(() => new Animated.Value(0));
13
+
14
+ useEffect(() => {
15
+ const loop = Animated.loop(
16
+ Animated.timing(turn, {
17
+ duration: 1000,
18
+ easing: Easing.linear,
19
+ toValue: 1,
20
+ // react-native-web has no native driver and warns when asked for it.
21
+ useNativeDriver: Platform.OS !== 'web',
22
+ }),
23
+ );
24
+ loop.start();
25
+ return () => loop.stop();
26
+ }, [turn]);
27
+
28
+ const rotate = turn.interpolate({
29
+ inputRange: [0, 1],
30
+ outputRange: ['0deg', '360deg'],
31
+ });
32
+
33
+ return (
34
+ <Animated.View
35
+ accessibilityElementsHidden
36
+ importantForAccessibility="no-hide-descendants"
37
+ style={{ transform: [{ rotate }] }}
38
+ >
39
+ <View
40
+ className={cn(
41
+ 'border-foreground size-3 rounded-full border-[1.5px] opacity-80',
42
+ className,
43
+ // After the color, which would otherwise override the open side.
44
+ 'border-t-transparent',
45
+ )}
46
+ />
47
+ </Animated.View>
48
+ );
49
+ }
@@ -1,5 +1,7 @@
1
+ import { type Icon as TablerIconComponent } from '@tabler/icons-react-native';
1
2
  import { type ComponentType, type ReactNode } from 'react';
2
3
  import { ScrollView, View } from 'react-native';
4
+ import { useResolveClassNames } from 'uniwind';
3
5
 
4
6
  import { cn } from '../../lib/cn';
5
7
  import { Text } from '../Text';
@@ -29,6 +31,37 @@ type ComponentMatrixRow = {
29
31
  label: string;
30
32
  };
31
33
 
34
+ /**
35
+ * A Tabler icon, the library the web stories use, dimmed and pulled in like
36
+ * the web `Button` styles its `svg`s. React Native has no `currentColor`, so
37
+ * `className` sets its color with the label's class (`text-primary-foreground`,
38
+ * …) and `size` follows the button's (14 for `xs`, 18 for `xl`).
39
+ */
40
+ function Icon({
41
+ className,
42
+ icon: TablerIcon,
43
+ size = 16,
44
+ }: {
45
+ className?: string;
46
+ icon: TablerIconComponent;
47
+ size?: number;
48
+ }) {
49
+ const style = useResolveClassNames(
50
+ cn('text-foreground -mx-0.5 opacity-80', className),
51
+ );
52
+
53
+ return (
54
+ <TablerIcon
55
+ accessibilityElementsHidden
56
+ color={style.color}
57
+ importantForAccessibility="no-hide-descendants"
58
+ size={size}
59
+ strokeWidth={2}
60
+ style={style}
61
+ />
62
+ );
63
+ }
64
+
32
65
  // Same layout as `Story` in @pickle-ui/react, built on React Native
33
66
  // primitives: a 12rem column of row labels, then one column per matrix
34
67
  // column that grows from 12rem, like the web's `minmax(12rem, 1fr)`, since
@@ -135,6 +168,7 @@ function Section({ children, title }: { children: ReactNode; title: string }) {
135
168
  }
136
169
 
137
170
  const Story = Object.assign(Layout, {
171
+ Icon,
138
172
  Layout,
139
173
  Matrix,
140
174
  Section,
@@ -1,7 +1,9 @@
1
1
  export { Card } from '../components/Card';
2
2
  export type {
3
+ CardActionProps,
3
4
  CardContentProps,
4
5
  CardDescriptionProps,
6
+ CardFooterProps,
5
7
  CardHeaderProps,
6
8
  CardProps,
7
9
  CardTitleProps,
@@ -0,0 +1,7 @@
1
+ export { createTheme } from '@pickle-ui/tokens/theme';
2
+ export type {
3
+ Theme,
4
+ ThemeFonts,
5
+ ThemeOptions,
6
+ ThemeVariables,
7
+ } from '@pickle-ui/tokens/theme';
package/src/index.ts CHANGED
@@ -5,4 +5,5 @@ export * from './entries/button';
5
5
  export * from './entries/card';
6
6
  export * from './entries/cn';
7
7
  export * from './entries/text';
8
+ export * from './entries/theme';
8
9
  export * from './entries/use-color-token';
@@ -6,4 +6,10 @@ describe('cn', () => {
6
6
  'text-sm px-4',
7
7
  );
8
8
  });
9
+
10
+ it('keeps a type scale size next to a text color', () => {
11
+ expect(cn('text-h1 text-foreground', 'text-muted-foreground')).toBe(
12
+ 'text-h1 text-muted-foreground',
13
+ );
14
+ });
9
15
  });
package/src/lib/cn.ts CHANGED
@@ -1,4 +1,17 @@
1
- import { twMerge } from 'tailwind-merge';
1
+ import { extendTailwindMerge } from 'tailwind-merge';
2
+
3
+ /**
4
+ * Teaches tailwind-merge Pickle's type scale: `text-body`, `text-h1`, … are
5
+ * font sizes, so they must not be mistaken for text colors and dropped next
6
+ * to one.
7
+ */
8
+ const twMerge = extendTailwindMerge({
9
+ extend: {
10
+ theme: {
11
+ text: ['body', 'code', 'h1', 'h2', 'h3', 'h4', 'lead', 'small'],
12
+ },
13
+ },
14
+ });
2
15
 
3
16
  /** Joins class names; later classes win, like `@pickle-ui/react/cn`. */
4
17
  export function cn(...classes: Array<false | null | string | undefined>) {