onecart-ui 1.0.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 (82) hide show
  1. package/README.md +351 -0
  2. package/dist/components/Button/Button.d.ts +4 -0
  3. package/dist/components/Button/Button.d.ts.map +1 -0
  4. package/dist/components/Button/index.d.ts +3 -0
  5. package/dist/components/Button/index.d.ts.map +1 -0
  6. package/dist/components/Heading/Heading.d.ts +5 -0
  7. package/dist/components/Heading/Heading.d.ts.map +1 -0
  8. package/dist/components/Heading/index.d.ts +3 -0
  9. package/dist/components/Heading/index.d.ts.map +1 -0
  10. package/dist/components/Paragraph/Paragraph.d.ts +5 -0
  11. package/dist/components/Paragraph/Paragraph.d.ts.map +1 -0
  12. package/dist/components/Paragraph/index.d.ts +3 -0
  13. package/dist/components/Paragraph/index.d.ts.map +1 -0
  14. package/dist/components/Text/Text.d.ts +5 -0
  15. package/dist/components/Text/Text.d.ts.map +1 -0
  16. package/dist/components/Text/index.d.ts +3 -0
  17. package/dist/components/Text/index.d.ts.map +1 -0
  18. package/dist/components/Typography/Typography.d.ts +5 -0
  19. package/dist/components/Typography/Typography.d.ts.map +1 -0
  20. package/dist/components/Typography/index.d.ts +3 -0
  21. package/dist/components/Typography/index.d.ts.map +1 -0
  22. package/dist/index.d.ts +13 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.esm.js +2 -0
  25. package/dist/index.esm.js.map +1 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/styles/tokens/index.d.ts +107 -0
  29. package/dist/styles/tokens/index.d.ts.map +1 -0
  30. package/dist/styles/tokens/tokens.d.ts +350 -0
  31. package/dist/styles/tokens/tokens.d.ts.map +1 -0
  32. package/dist/styles/tokens/typography.d.ts +154 -0
  33. package/dist/styles/tokens/typography.d.ts.map +1 -0
  34. package/dist/styles/tokens/utils/fontUtils.d.ts +26 -0
  35. package/dist/styles/tokens/utils/fontUtils.d.ts.map +1 -0
  36. package/dist/styles/tokens/utils/utils.d.ts +13 -0
  37. package/dist/styles/tokens/utils/utils.d.ts.map +1 -0
  38. package/dist/theme/ThemeProvider.d.ts +14 -0
  39. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  40. package/dist/theme/index.d.ts +55 -0
  41. package/dist/theme/index.d.ts.map +1 -0
  42. package/dist/types/Button.d.ts +47 -0
  43. package/dist/types/Button.d.ts.map +1 -0
  44. package/dist/types/Heading.d.ts +24 -0
  45. package/dist/types/Heading.d.ts.map +1 -0
  46. package/dist/types/Paragraph.d.ts +35 -0
  47. package/dist/types/Paragraph.d.ts.map +1 -0
  48. package/dist/types/Text.d.ts +32 -0
  49. package/dist/types/Text.d.ts.map +1 -0
  50. package/dist/types/Typography.d.ts +64 -0
  51. package/dist/types/Typography.d.ts.map +1 -0
  52. package/package.json +72 -0
  53. package/src/components/Button/Button.tsx +155 -0
  54. package/src/components/Button/index.ts +2 -0
  55. package/src/components/Heading/Heading.tsx +48 -0
  56. package/src/components/Heading/index.ts +2 -0
  57. package/src/components/Paragraph/Paragraph.tsx +93 -0
  58. package/src/components/Paragraph/index.ts +6 -0
  59. package/src/components/Text/Text.tsx +96 -0
  60. package/src/components/Text/index.ts +2 -0
  61. package/src/components/Typography/Typography.tsx +123 -0
  62. package/src/components/Typography/index.ts +7 -0
  63. package/src/index.ts +34 -0
  64. package/src/styles/tokens/index.ts +130 -0
  65. package/src/styles/tokens/tokens-autocomplete-config.json +2417 -0
  66. package/src/styles/tokens/tokens.css +352 -0
  67. package/src/styles/tokens/tokens.js +350 -0
  68. package/src/styles/tokens/tokens.json +427 -0
  69. package/src/styles/tokens/tokens.less +349 -0
  70. package/src/styles/tokens/tokens.scss +349 -0
  71. package/src/styles/tokens/tokens.ts +350 -0
  72. package/src/styles/tokens/tokensMap.scss +353 -0
  73. package/src/styles/tokens/typography.ts +172 -0
  74. package/src/styles/tokens/utils/fontUtils.ts +63 -0
  75. package/src/styles/tokens/utils/utils.ts +19 -0
  76. package/src/theme/ThemeProvider.tsx +71 -0
  77. package/src/theme/index.ts +107 -0
  78. package/src/types/Button.ts +56 -0
  79. package/src/types/Heading.ts +27 -0
  80. package/src/types/Paragraph.ts +40 -0
  81. package/src/types/Text.ts +40 -0
  82. package/src/types/Typography.ts +94 -0
@@ -0,0 +1,47 @@
1
+ export interface ButtonProps {
2
+ /**
3
+ * The content to display inside the button
4
+ */
5
+ children: React.ReactNode;
6
+ /**
7
+ * The variant of the button
8
+ */
9
+ variant?: "primary" | "secondary" | "outline" | "ghost";
10
+ /**
11
+ * The size of the button
12
+ */
13
+ size?: "sm" | "md" | "lg";
14
+ /**
15
+ * Whether the button is disabled
16
+ */
17
+ disabled?: boolean;
18
+ /**
19
+ * Whether the button should take full width
20
+ */
21
+ fullWidth?: boolean;
22
+ /**
23
+ * Loading state
24
+ */
25
+ loading?: boolean;
26
+ /**
27
+ * Custom style override
28
+ */
29
+ style?: import("react-native").ViewStyle;
30
+ /**
31
+ * Custom text style override
32
+ */
33
+ textStyle?: import("react-native").TextStyle;
34
+ /**
35
+ * Accessibility label
36
+ */
37
+ accessibilityLabel?: string;
38
+ /**
39
+ * Test ID for testing
40
+ */
41
+ testID?: string;
42
+ /**
43
+ * Press handler
44
+ */
45
+ onPress?: () => void;
46
+ }
47
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/types/Button.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;IAExD;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,cAAc,EAAE,SAAS,CAAC;IAEzC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,cAAc,EAAE,SAAS,CAAC;IAE7C;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB"}
@@ -0,0 +1,24 @@
1
+ import { TypographyProps } from "./Typography";
2
+ /**
3
+ * Heading levels corresponding to HTML heading elements
4
+ */
5
+ export type HeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
6
+ /**
7
+ * Heading component props
8
+ */
9
+ export interface HeadingProps extends Omit<TypographyProps, "variant"> {
10
+ /**
11
+ * The heading level
12
+ * @default 'h2'
13
+ */
14
+ level?: HeadingLevel;
15
+ /**
16
+ * Optional subtitle to display below the heading
17
+ */
18
+ subtitle?: React.ReactNode;
19
+ /**
20
+ * Props to pass to the subtitle Typography component
21
+ */
22
+ subtitleProps?: Omit<TypographyProps, "children">;
23
+ }
24
+ //# sourceMappingURL=Heading.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Heading.d.ts","sourceRoot":"","sources":["../../src/types/Heading.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC;IACpE;;;OAGG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;OAEG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;CACnD"}
@@ -0,0 +1,35 @@
1
+ import { TextProps } from "./Text";
2
+ /**
3
+ * Paragraph size options
4
+ */
5
+ export type ParagraphSize = "xs" | "sm" | "md" | "lg";
6
+ /**
7
+ * Paragraph spacing options
8
+ */
9
+ export type ParagraphSpacing = "none" | "xs" | "sm" | "md" | "lg" | "xl";
10
+ /**
11
+ * Paragraph component props
12
+ */
13
+ export interface ParagraphProps extends TextProps {
14
+ /**
15
+ * Size of the paragraph text
16
+ * @default 'md'
17
+ */
18
+ size?: ParagraphSize;
19
+ /**
20
+ * Spacing below the paragraph
21
+ * @default 'md'
22
+ */
23
+ spacing?: ParagraphSpacing;
24
+ /**
25
+ * Whether to indent the first line of the paragraph
26
+ * @default false
27
+ */
28
+ firstLineIndent?: boolean;
29
+ /**
30
+ * Whether to apply a drop cap style to the first letter
31
+ * @default false
32
+ */
33
+ dropCap?: boolean;
34
+ }
35
+ //# sourceMappingURL=Paragraph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Paragraph.d.ts","sourceRoot":"","sources":["../../src/types/Paragraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEtD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C;;;OAGG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,32 @@
1
+ import { TypographyProps } from "./Typography";
2
+ /**
3
+ * Text component props extending Typography props with additional features
4
+ */
5
+ export interface TextProps extends TypographyProps {
6
+ /**
7
+ * Whether the text should be underlined
8
+ * @default false
9
+ */
10
+ underline?: boolean;
11
+ /**
12
+ * Whether the text should have a strikethrough line
13
+ * @default false
14
+ */
15
+ strikethrough?: boolean;
16
+ /**
17
+ * Whether the text should be italic
18
+ * @default false
19
+ */
20
+ italic?: boolean;
21
+ /**
22
+ * Whether the text should be styled as a link
23
+ * @default false
24
+ */
25
+ link?: boolean;
26
+ /**
27
+ * Callback function when the link is pressed
28
+ * Only used when link prop is true
29
+ */
30
+ onLinkPress?: () => void;
31
+ }
32
+ //# sourceMappingURL=Text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Text.d.ts","sourceRoot":"","sources":["../../src/types/Text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,eAAe;IAChD;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAK1B"}
@@ -0,0 +1,64 @@
1
+ import { TextProps } from "react-native";
2
+ /**
3
+ * Typography variants
4
+ */
5
+ export type TypographyVariant = "display2xl" | "displayXl" | "headingXl" | "headingLg" | "headingMd" | "headingSm" | "headingXs" | "bodyLg" | "bodyMd" | "bodySm" | "bodyXs" | "labelLg" | "labelMd" | "labelSm";
6
+ /**
7
+ * Text alignment options
8
+ */
9
+ export type TypographyAlign = "left" | "center" | "right";
10
+ /**
11
+ * Font weight options
12
+ */
13
+ export type TypographyWeight = "normal" | "medium" | "semibold" | "bold";
14
+ /**
15
+ * Typography component props
16
+ */
17
+ export interface TypographyProps extends Omit<TextProps, "children"> {
18
+ /**
19
+ * The content to display
20
+ */
21
+ children?: React.ReactNode;
22
+ /**
23
+ * The typography variant to use
24
+ * @default 'bodyMd'
25
+ */
26
+ variant?: TypographyVariant;
27
+ /**
28
+ * Text alignment
29
+ * @default 'left'
30
+ */
31
+ align?: TypographyAlign;
32
+ /**
33
+ * Font weight
34
+ */
35
+ weight?: TypographyWeight;
36
+ /**
37
+ * Text color
38
+ * If not provided, uses variant's default color from theme
39
+ */
40
+ color?: string;
41
+ /**
42
+ * Whether to truncate text with ellipsis if it overflows
43
+ * @default false
44
+ */
45
+ truncate?: boolean;
46
+ /**
47
+ * Maximum number of lines before truncating
48
+ * If not provided, text will not be truncated
49
+ */
50
+ numberOfLines?: number;
51
+ /**
52
+ * Additional custom styles for the text
53
+ */
54
+ style?: TextProps["style"];
55
+ /**
56
+ * Accessibility label for screen readers
57
+ */
58
+ accessibilityLabel?: string;
59
+ /**
60
+ * Test ID for testing
61
+ */
62
+ testID?: string;
63
+ }
64
+ //# sourceMappingURL=Typography.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Typography.d.ts","sourceRoot":"","sources":["../../src/types/Typography.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAEzB,YAAY,GACZ,WAAW,GAEX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GAEX,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,GAER,SAAS,GACT,SAAS,GACT,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC;IAClE;;OAEG;IACH,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B;;;OAGG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE5B;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,CAAC;IAExB;;OAEG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAE1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3B;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "onecart-ui",
3
+ "version": "1.0.1",
4
+ "description": "Cross-platform React and React Native component library with white-label support",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "react-native": "src/index.ts",
9
+ "files": [
10
+ "dist",
11
+ "src"
12
+ ],
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "build:watch": "rollup -c -w",
16
+ "storybook": "storybook dev -p 6006",
17
+ "build-storybook": "storybook build",
18
+ "type-check": "tsc --noEmit",
19
+ "lint": "eslint src --ext .ts,.tsx",
20
+ "test": "jest",
21
+ "dev": "npm run build:watch",
22
+ "generate-tokens": "npx figma-token-engine",
23
+ "prepublishOnly": "npm run build",
24
+ "prepare": "npm run build",
25
+ "publish:npm": "npm publish --access public"
26
+ },
27
+ "keywords": [
28
+ "react",
29
+ "react-native",
30
+ "components",
31
+ "ui",
32
+ "cross-platform",
33
+ "white-label"
34
+ ],
35
+ "author": "",
36
+ "license": "MIT",
37
+ "peerDependencies": {
38
+ "react": ">=16.8.0",
39
+ "react-native": ">=0.60.0"
40
+ },
41
+ "devDependencies": {
42
+ "@rollup/plugin-commonjs": "^28.0.3",
43
+ "@rollup/plugin-node-resolve": "^16.0.1",
44
+ "@rollup/plugin-typescript": "^12.1.2",
45
+ "@storybook/addon-docs": "^9.0.4",
46
+ "@storybook/addon-onboarding": "^9.0.4",
47
+ "@storybook/addon-webpack5-compiler-swc": "^3.0.0",
48
+ "@storybook/react-webpack5": "^9.0.4",
49
+ "@types/jest": "^29.5.14",
50
+ "@types/react": "^19.1.6",
51
+ "@types/react-dom": "^19.1.5",
52
+ "@types/react-native": "^0.72.8",
53
+ "@typescript-eslint/eslint-plugin": "^8.33.0",
54
+ "@typescript-eslint/parser": "^8.33.0",
55
+ "eslint": "^9.28.0",
56
+ "eslint-plugin-storybook": "^9.0.4",
57
+ "jest": "^29.7.0",
58
+ "react": "^19.1.0",
59
+ "react-dom": "^19.1.0",
60
+ "rollup": "^2.79.2",
61
+ "rollup-plugin-peer-deps-external": "^2.2.4",
62
+ "rollup-plugin-terser": "^7.0.2",
63
+ "storybook": "^9.0.4",
64
+ "ts-jest": "^29.3.4",
65
+ "typescript": "^5.8.3"
66
+ },
67
+ "dependencies": {
68
+ "figma-token-engine": "^0.3.0",
69
+ "react-native-web": "^0.20.0",
70
+ "style-dictionary": "^4.4.0"
71
+ }
72
+ }
@@ -0,0 +1,155 @@
1
+ import React from "react";
2
+ import {
3
+ TouchableOpacity,
4
+ Text,
5
+ ActivityIndicator,
6
+ ViewStyle,
7
+ TextStyle,
8
+ } from "react-native";
9
+ import { buttonTokens } from "../../styles/tokens";
10
+ import { ButtonProps } from "../../types/Button";
11
+
12
+ export const Button: React.FC<ButtonProps> = ({
13
+ children,
14
+ variant = "primary",
15
+ size = "md",
16
+ disabled = false,
17
+ fullWidth = false,
18
+ loading = false,
19
+ style,
20
+ textStyle,
21
+ accessibilityLabel,
22
+ testID,
23
+ onPress,
24
+ }) => {
25
+ // Calculate variant styles
26
+ const variantStyles = React.useMemo(() => {
27
+ try {
28
+ const sizeConfig = buttonTokens.sizes[size];
29
+ const variantConfig = buttonTokens[variant];
30
+
31
+ const baseStyle: ViewStyle = {
32
+ borderRadius: sizeConfig.borderRadius,
33
+ borderWidth: buttonTokens.common.borderWidth,
34
+ alignItems: "center",
35
+ justifyContent: "center",
36
+ flexDirection: "row",
37
+ };
38
+
39
+ return {
40
+ ...baseStyle,
41
+ backgroundColor: disabled
42
+ ? variantConfig.background.disabled
43
+ : variantConfig.background.default,
44
+ borderColor: disabled
45
+ ? variantConfig.border.disabled
46
+ : variantConfig.border.default,
47
+ };
48
+ } catch (error) {
49
+ // Fallback styles
50
+ return {
51
+ backgroundColor: variant === "primary" ? "#007AFF" : "transparent",
52
+ borderColor: variant === "primary" ? "#007AFF" : "#E5E5EA",
53
+ borderWidth: 1,
54
+ borderRadius: 4,
55
+ alignItems: "center",
56
+ justifyContent: "center",
57
+ flexDirection: "row",
58
+ };
59
+ }
60
+ }, [variant, size, disabled]);
61
+
62
+ // Calculate size styles
63
+ const sizeStyles = React.useMemo(() => {
64
+ try {
65
+ const sizeConfig = buttonTokens.sizes[size];
66
+ return {
67
+ paddingHorizontal: sizeConfig.paddingHorizontal,
68
+ paddingVertical: sizeConfig.paddingVertical,
69
+ minHeight: sizeConfig.minHeight,
70
+ };
71
+ } catch (error) {
72
+ // Fallback styles
73
+ return {
74
+ paddingHorizontal: 16,
75
+ paddingVertical: 8,
76
+ minHeight: size === "sm" ? 32 : size === "lg" ? 48 : 40,
77
+ };
78
+ }
79
+ }, [size]);
80
+
81
+ // Calculate text styles
82
+ const textStyles = React.useMemo(() => {
83
+ try {
84
+ const sizeConfig = buttonTokens.sizes[size];
85
+ const variantConfig = buttonTokens[variant];
86
+
87
+ const baseTextStyle: TextStyle = {
88
+ fontSize: sizeConfig.fontSize,
89
+ fontWeight: buttonTokens.common.fontWeight as any,
90
+ lineHeight: buttonTokens.common.lineHeight,
91
+ color: disabled
92
+ ? variantConfig.text.disabled
93
+ : variantConfig.text.default,
94
+ };
95
+
96
+ return {
97
+ ...baseTextStyle,
98
+ ...textStyle,
99
+ };
100
+ } catch (error) {
101
+ // Fallback styles
102
+ return {
103
+ fontSize: size === "sm" ? 12 : size === "lg" ? 18 : 16,
104
+ fontWeight: "500",
105
+ color: disabled
106
+ ? "#8E8E93"
107
+ : variant === "primary"
108
+ ? "#FFFFFF"
109
+ : "#007AFF",
110
+ ...textStyle,
111
+ };
112
+ }
113
+ }, [variant, size, disabled, textStyle]);
114
+
115
+ // Handle button press
116
+ const handlePress = React.useCallback(() => {
117
+ if (!disabled && !loading && onPress) {
118
+ onPress();
119
+ }
120
+ }, [disabled, loading, onPress]);
121
+
122
+ // Combine all styles
123
+ const buttonStyles = React.useMemo(
124
+ () => ({
125
+ ...variantStyles,
126
+ ...sizeStyles,
127
+ ...(fullWidth && { width: "100%" }),
128
+ ...(disabled && { opacity: 0.6 }),
129
+ ...style,
130
+ }),
131
+ [variantStyles, sizeStyles, fullWidth, disabled, style]
132
+ );
133
+
134
+ return (
135
+ <TouchableOpacity
136
+ style={buttonStyles}
137
+ onPress={handlePress}
138
+ disabled={disabled || loading}
139
+ accessibilityLabel={accessibilityLabel}
140
+ accessibilityRole="button"
141
+ testID={testID}
142
+ >
143
+ {loading && (
144
+ <ActivityIndicator
145
+ size="small"
146
+ color={
147
+ typeof textStyles.color === "string" ? textStyles.color : "#000000"
148
+ }
149
+ style={{ marginRight: 8 }}
150
+ />
151
+ )}
152
+ <Text style={textStyles}>{children}</Text>
153
+ </TouchableOpacity>
154
+ );
155
+ };
@@ -0,0 +1,2 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps } from '../../types/Button';
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import * as tokens from "../../styles/tokens/tokens";
3
+ import { HeadingProps } from "../../types/Heading";
4
+ import { Typography } from "../Typography";
5
+
6
+ const headingLevelToVariant = {
7
+ h1: "headingXl",
8
+ h2: "headingLg",
9
+ h3: "headingMd",
10
+ h4: "headingSm",
11
+ h5: "headingXs",
12
+ h6: "headingXs",
13
+ };
14
+
15
+ export const Heading: React.FC<HeadingProps> = ({
16
+ children,
17
+ level = "h2",
18
+ subtitle,
19
+ subtitleProps,
20
+ ...rest
21
+ }) => {
22
+ const variant = headingLevelToVariant[level];
23
+
24
+ return (
25
+ <>
26
+ <Typography variant={variant} accessibilityRole={level} {...rest}>
27
+ {children}
28
+ </Typography>
29
+
30
+ {subtitle && (
31
+ <Typography
32
+ variant="bodySm"
33
+ color={tokens.TEXT_TERTIARY}
34
+ style={{
35
+ marginTop: tokens.LAYOUT_SPACING_STACK_XS
36
+ ? parseInt(tokens.LAYOUT_SPACING_STACK_XS)
37
+ : 4,
38
+ }}
39
+ {...subtitleProps}
40
+ >
41
+ {subtitle}
42
+ </Typography>
43
+ )}
44
+ </>
45
+ );
46
+ };
47
+
48
+ export default Heading;
@@ -0,0 +1,2 @@
1
+ export { Heading } from './Heading';
2
+ export type { HeadingProps, HeadingLevel } from '../../types/Heading';
@@ -0,0 +1,93 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import * as tokens from "../../styles/tokens/tokens";
4
+ import { ParagraphProps } from "../../types/Paragraph";
5
+ import { remToNumber } from "../../styles/tokens/utils/utils";
6
+ import { Text } from "../Text";
7
+
8
+ export const Paragraph: React.FC<ParagraphProps> = ({
9
+ children,
10
+ size = "md",
11
+ spacing = "md",
12
+ firstLineIndent = false,
13
+ dropCap = false,
14
+ style,
15
+ ...rest
16
+ }) => {
17
+ const getVariant = () => {
18
+ switch (size) {
19
+ case "xs":
20
+ return "bodyXs";
21
+ case "sm":
22
+ return "bodySm";
23
+ case "lg":
24
+ return "bodyLg";
25
+ case "md":
26
+ default:
27
+ return "bodyMd";
28
+ }
29
+ };
30
+
31
+ const getMarginBottom = () => {
32
+ switch (spacing) {
33
+ case "none":
34
+ return tokens.LAYOUT_SPACING_STACK_NONE;
35
+ case "xs":
36
+ return remToNumber(tokens.LAYOUT_SPACING_STACK_XS);
37
+ case "sm":
38
+ return remToNumber(tokens.LAYOUT_SPACING_STACK_SM);
39
+ case "lg":
40
+ return remToNumber(tokens.LAYOUT_SPACING_STACK_LG);
41
+ case "xl":
42
+ return remToNumber(tokens.LAYOUT_SPACING_STACK_XL);
43
+ case "md":
44
+ default:
45
+ return remToNumber(tokens.LAYOUT_SPACING_STACK_MD);
46
+ }
47
+ };
48
+
49
+ const paragraphStyle = {
50
+ marginBottom: getMarginBottom(),
51
+ ...(firstLineIndent
52
+ ? {
53
+ textIndent: remToNumber(tokens.LAYOUT_SPACING_INLINE_MD) || 20,
54
+ }
55
+ : {}),
56
+ ...style,
57
+ };
58
+
59
+ if (dropCap && typeof children === "string" && children.length > 0) {
60
+ const firstChar = children.charAt(0);
61
+ const restOfText = children.slice(1);
62
+
63
+ return (
64
+ <View style={paragraphStyle}>
65
+ <View style={{ flexDirection: "row", alignItems: "flex-start" }}>
66
+ <Text
67
+ variant="headingLg"
68
+ style={{
69
+ lineHeight: 1,
70
+ marginRight:
71
+ remToNumber(tokens.LAYOUT_SPACING_INLINE_2XS) / 4 || 2,
72
+ marginTop: -2,
73
+ }}
74
+ {...rest}
75
+ >
76
+ {firstChar}
77
+ </Text>
78
+ <Text variant={getVariant()} {...rest}>
79
+ {restOfText}
80
+ </Text>
81
+ </View>
82
+ </View>
83
+ );
84
+ }
85
+
86
+ return (
87
+ <Text variant={getVariant()} style={paragraphStyle} {...rest}>
88
+ {children}
89
+ </Text>
90
+ );
91
+ };
92
+
93
+ export default Paragraph;
@@ -0,0 +1,6 @@
1
+ export { Paragraph } from "./Paragraph";
2
+ export type {
3
+ ParagraphProps,
4
+ ParagraphSize,
5
+ ParagraphSpacing,
6
+ } from "../../types/Paragraph";