onecart-ui
Version:
OneCart UI: Cross-platform design tokens + React & React Native components
474 lines (460 loc) • 18.3 kB
JavaScript
import { jsx } from 'react/jsx-runtime';
import { useState } from 'react';
import { TouchableOpacity, Text, Pressable } from 'react-native';
/**
* File generated by the Figma Token Engine
* Do not edit directly
*/
const ACTION_PRIMARY_DEFAULT$1 = "#00df88";
const ACTION_PRIMARY_HOVER$1 = "#4ce9ac";
const ACTION_PRIMARY_ACTIVE$1 = "#98f2cf";
const ACTION_PRIMARY_DISABLED$1 = "#E5FCF3";
const ACTION_DESTRUCTIVE_DEFAULT$1 = "#d60000";
const ACTION_DESTRUCTIVE_HOVER$1 = "#a90000";
const ACTION_DESTRUCTIVE_ACTIVE$1 = "#fed8d8";
const ACTION_DESTRUCTIVE_DISABLE$1 = "#feecec";
const ACTION_TERTIARY_DEFAULT$1 = "#3b3b3b";
const ACTION_TERTIARY_HOVER$1 = "#111";
const ACTION_TERTIARY_ACTIVE$1 = "#ababab";
const ACTION_TERTIARY_DISABLE$1 = "#f1f1f1";
const NEUTRAL_80$1 = "#3b3b3b";
const DISPLAY_2XL_LINE_HEIGHT = "56px";
const DISPLAY_2XL_FONT_SIZE = "52px";
const DISPLAY_2XL_LETTER_SPACING = "0%";
const DISPLAY_2XL_TEXT_DECORATION = "none";
const DISPLAY_XL_LINE_HEIGHT = "48px";
const DISPLAY_XL_FONT_SIZE = "44px";
const DISPLAY_XL_LETTER_SPACING = "0%";
const DISPLAY_XL_TEXT_DECORATION = "none";
const HEADING_XL_LINE_HEIGHT = "48px";
const HEADING_XL_FONT_SIZE = "40px";
const HEADING_XL_LETTER_SPACING = "0%";
const HEADING_XL_TEXT_DECORATION = "none";
const HEADING_LG_LINE_HEIGHT = "44px";
const HEADING_LG_FONT_SIZE = "36px";
const HEADING_LG_LETTER_SPACING = "0%";
const HEADING_LG_TEXT_DECORATION = "none";
const HEADING_MD_LINE_HEIGHT = "40px";
const HEADING_MD_FONT_SIZE = "32px";
const HEADING_MD_LETTER_SPACING = "0%";
const HEADING_MD_TEXT_DECORATION = "none";
const HEADING_SM_LINE_HEIGHT = "36px";
const HEADING_SM_FONT_SIZE = "28px";
const HEADING_SM_LETTER_SPACING = "0%";
const HEADING_SM_TEXT_DECORATION = "none";
const HEADING_XS_LINE_HEIGHT = "28px";
const HEADING_XS_FONT_SIZE = "20px";
const HEADING_XS_LETTER_SPACING = "0%";
const HEADING_XS_TEXT_DECORATION = "none";
const HEADING_2XS_LINE_HEIGHT = "24px";
const HEADING_2XS_FONT_SIZE = "18px";
const HEADING_2XS_LETTER_SPACING = "0%";
const HEADING_2XS_TEXT_DECORATION = "none";
const BODY_XL_LINE_HEIGHT = "28px";
const BODY_XL_FONT_SIZE = "18px";
const BODY_XL_LETTER_SPACING = "0%";
const BODY_XL_TEXT_DECORATION = "none";
const BODY_LG_LINE_HEIGHT = "24px";
const BODY_LG_FONT_SIZE = "16px";
const BODY_LG_LETTER_SPACING = "0%";
const BODY_LG_TEXT_DECORATION = "none";
const BODY_MD_LINE_HEIGHT = "20px";
const BODY_MD_FONT_SIZE = "14px";
const BODY_MD_LETTER_SPACING = "0%";
const BODY_MD_TEXT_DECORATION = "none";
const BODY_SM_LINE_HEIGHT = "20px";
const BODY_SM_FONT_SIZE = "12px";
const BODY_SM_LETTER_SPACING = "0%";
const BODY_SM_TEXT_DECORATION = "none";
const UTILITY_BUTTON_FONT_WEIGHT = 500;
const UTILITY_BUTTON_LINE_HEIGHT = "16px";
const UTILITY_BUTTON_FONT_SIZE = "16px";
const UTILITY_BUTTON_LETTER_SPACING = "0%";
const UTILITY_BUTTON_TEXT_DECORATION = "none";
const UTILITY_LINK_FONT_WEIGHT = 500;
const UTILITY_LINK_LINE_HEIGHT = "20px";
const UTILITY_LINK_FONT_SIZE = "14px";
const UTILITY_LINK_LETTER_SPACING = "0%";
const UTILITY_LINK_TEXT_DECORATION = "underline";
const UTILITY_CAPTION_FONT_WEIGHT = "book";
const UTILITY_CAPTION_LINE_HEIGHT = "16px";
const UTILITY_CAPTION_FONT_SIZE = "12px";
const UTILITY_CAPTION_LETTER_SPACING = "0%";
const UTILITY_CAPTION_TEXT_DECORATION = "none";
const FONT_FAMILIES_CAMPTON$1 = "Campton";
const SEMI_BOLD = 600;
const BOOK = "book";
// Facade: curated subset of raw Figma tokens for button usage
// Generated manually; consider automating selection logic later.
const ACTION_PRIMARY_DEFAULT = ACTION_PRIMARY_DEFAULT$1;
const ACTION_PRIMARY_HOVER = ACTION_PRIMARY_HOVER$1;
const ACTION_PRIMARY_ACTIVE = ACTION_PRIMARY_ACTIVE$1;
const ACTION_PRIMARY_DISABLED = ACTION_PRIMARY_DISABLED$1;
const ACTION_TERTIARY_DEFAULT = ACTION_TERTIARY_DEFAULT$1;
const ACTION_TERTIARY_HOVER = ACTION_TERTIARY_HOVER$1;
const ACTION_TERTIARY_ACTIVE = ACTION_TERTIARY_ACTIVE$1;
const ACTION_TERTIARY_DISABLE = ACTION_TERTIARY_DISABLE$1;
const ACTION_DESTRUCTIVE_DEFAULT = ACTION_DESTRUCTIVE_DEFAULT$1;
const ACTION_DESTRUCTIVE_HOVER = ACTION_DESTRUCTIVE_HOVER$1;
const ACTION_DESTRUCTIVE_ACTIVE = ACTION_DESTRUCTIVE_ACTIVE$1;
const ACTION_DESTRUCTIVE_DISABLE = ACTION_DESTRUCTIVE_DISABLE$1;
const NEUTRAL_80 = NEUTRAL_80$1;
const FONT_FAMILIES_CAMPTON = FONT_FAMILIES_CAMPTON$1;
// Central design tokens import facade for components.
// Pulls curated subset from the tokens package facade; extend as needed.
const buttonTokens = {
primary: {
default: ACTION_PRIMARY_DEFAULT,
hover: ACTION_PRIMARY_HOVER,
active: ACTION_PRIMARY_ACTIVE,
disabled: ACTION_PRIMARY_DISABLED,
},
outline: {
text: {
default: ACTION_TERTIARY_DEFAULT,
hover: ACTION_TERTIARY_HOVER,
active: ACTION_TERTIARY_ACTIVE,
disabled: ACTION_TERTIARY_DISABLE,
},
},
ghost: {
text: {
default: ACTION_TERTIARY_DEFAULT,
hover: ACTION_TERTIARY_HOVER,
active: ACTION_TERTIARY_ACTIVE,
disabled: ACTION_TERTIARY_DISABLE,
},
},
destructive: {
text: {
default: ACTION_DESTRUCTIVE_DEFAULT,
hover: ACTION_DESTRUCTIVE_HOVER,
active: ACTION_DESTRUCTIVE_ACTIVE,
disabled: ACTION_DESTRUCTIVE_DISABLE,
},
},
typography: {
family: FONT_FAMILIES_CAMPTON},
neutralText: NEUTRAL_80,
};
const computeMobileButtonStyles = (type, state, size, overrides) => {
const basePaddingVertical = size === "large" ? 14 : size === "small" ? 8 : 10;
const basePaddingHorizontal = 16;
const container = {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
paddingVertical: basePaddingVertical,
paddingHorizontal: basePaddingHorizontal,
borderRadius: 999,
opacity: state === "disabled" ? 0.6 : 1,
};
switch (type) {
case "primary":
container.backgroundColor =
buttonTokens.primary[state === "default" ? "default" : state];
break;
case "outline":
container.backgroundColor = "transparent";
container.borderWidth = 1;
container.borderColor =
buttonTokens.outline.text[state === "default" ? "default" : state];
break;
case "ghost":
container.backgroundColor = "transparent";
break;
case "destructive":
container.backgroundColor = "transparent";
break;
}
const label = {
fontFamily: buttonTokens.typography.family,
fontWeight: 500,
fontSize: size === "large" ? 16 : size === "small" ? 14 : 15,
lineHeight: size === "large" ? 20 : size === "small" ? 18 : 19,
color: type === "primary" ? buttonTokens.neutralText : undefined,
};
if (type === "outline") {
label.color =
buttonTokens.outline.text[state === "default" ? "default" : state];
}
else if (type === "ghost") {
label.color =
buttonTokens.ghost.text[state === "default" ? "default" : state];
}
else if (type === "destructive") {
label.color =
buttonTokens.destructive.text[state === "default" ? "default" : state];
}
return { container: { ...container, ...({}) }, label };
};
const Button = ({ label, type = "primary", size = "large", disabled = false, onPress, style, accessibilityLabel, testID, }) => {
const [buttonState] = useState(disabled ? "disabled" : "default");
const rnSize = (size === "large" ? "large" : "small");
const styles = computeMobileButtonStyles(type, buttonState, rnSize);
return (jsx(TouchableOpacity, { accessibilityRole: "button", accessibilityLabel: accessibilityLabel || label, disabled: disabled, testID: testID, style: [styles.container, style], onPress: () => !disabled && onPress?.(), children: jsx(Text, { style: styles.label, children: label }) }));
};
// Typography token mapping (bridge raw tokens -> component friendly sets)
// For now we access raw tokens via the facade raw escape hatch.
function px(n) {
if (n == null)
return 0;
const s = String(n).replace("px", "");
const v = parseFloat(s);
return Number.isNaN(v) ? 0 : v;
}
const typographyTokens = {
// Display
display2xl: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(DISPLAY_2XL_FONT_SIZE),
lineHeight: px(DISPLAY_2XL_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(DISPLAY_2XL_LETTER_SPACING),
textDecoration: String(DISPLAY_2XL_TEXT_DECORATION),
},
displayXl: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(DISPLAY_XL_FONT_SIZE),
lineHeight: px(DISPLAY_XL_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(DISPLAY_XL_LETTER_SPACING),
textDecoration: String(DISPLAY_XL_TEXT_DECORATION),
},
// Heading
headingXl: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_XL_FONT_SIZE),
lineHeight: px(HEADING_XL_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_XL_LETTER_SPACING),
textDecoration: String(HEADING_XL_TEXT_DECORATION),
},
headingLg: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_LG_FONT_SIZE),
lineHeight: px(HEADING_LG_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_LG_LETTER_SPACING),
textDecoration: String(HEADING_LG_TEXT_DECORATION),
},
headingMd: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_MD_FONT_SIZE),
lineHeight: px(HEADING_MD_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_MD_LETTER_SPACING),
textDecoration: String(HEADING_MD_TEXT_DECORATION),
},
headingSm: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_SM_FONT_SIZE),
lineHeight: px(HEADING_SM_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_SM_LETTER_SPACING),
textDecoration: String(HEADING_SM_TEXT_DECORATION),
},
headingXs: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_XS_FONT_SIZE),
lineHeight: px(HEADING_XS_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_XS_LETTER_SPACING),
textDecoration: String(HEADING_XS_TEXT_DECORATION),
},
heading2xs: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(HEADING_2XS_FONT_SIZE),
lineHeight: px(HEADING_2XS_LINE_HEIGHT),
fontWeight: String(SEMI_BOLD),
color: String(NEUTRAL_80$1),
letterSpacing: String(HEADING_2XS_LETTER_SPACING),
textDecoration: String(HEADING_2XS_TEXT_DECORATION),
},
// Body
bodyXl: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(BODY_XL_FONT_SIZE),
lineHeight: px(BODY_XL_LINE_HEIGHT),
fontWeight: String(BOOK),
color: String(NEUTRAL_80$1),
letterSpacing: String(BODY_XL_LETTER_SPACING),
textDecoration: String(BODY_XL_TEXT_DECORATION),
},
bodyLg: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(BODY_LG_FONT_SIZE),
lineHeight: px(BODY_LG_LINE_HEIGHT),
fontWeight: String(BOOK),
color: String(NEUTRAL_80$1),
letterSpacing: String(BODY_LG_LETTER_SPACING),
textDecoration: String(BODY_LG_TEXT_DECORATION),
},
bodyMd: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(BODY_MD_FONT_SIZE),
lineHeight: px(BODY_MD_LINE_HEIGHT),
fontWeight: String(BOOK),
color: String(NEUTRAL_80$1),
letterSpacing: String(BODY_MD_LETTER_SPACING),
textDecoration: String(BODY_MD_TEXT_DECORATION),
},
bodySm: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(BODY_SM_FONT_SIZE),
lineHeight: px(BODY_SM_LINE_HEIGHT),
fontWeight: String(BOOK),
color: String(NEUTRAL_80$1),
letterSpacing: String(BODY_SM_LETTER_SPACING),
textDecoration: String(BODY_SM_TEXT_DECORATION),
},
// Utility / labels
labelLg: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(UTILITY_BUTTON_FONT_SIZE),
lineHeight: px(UTILITY_BUTTON_LINE_HEIGHT),
fontWeight: String(UTILITY_BUTTON_FONT_WEIGHT),
color: String(NEUTRAL_80$1),
letterSpacing: String(UTILITY_BUTTON_LETTER_SPACING),
textDecoration: String(UTILITY_BUTTON_TEXT_DECORATION),
},
labelMd: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(UTILITY_LINK_FONT_SIZE),
lineHeight: px(UTILITY_LINK_LINE_HEIGHT),
fontWeight: String(UTILITY_LINK_FONT_WEIGHT),
color: String(NEUTRAL_80$1),
letterSpacing: String(UTILITY_LINK_LETTER_SPACING),
textDecoration: String(UTILITY_LINK_TEXT_DECORATION),
},
labelSm: {
fontFamily: String(FONT_FAMILIES_CAMPTON$1),
fontSize: px(UTILITY_CAPTION_FONT_SIZE),
lineHeight: px(UTILITY_CAPTION_LINE_HEIGHT),
fontWeight: String(UTILITY_CAPTION_FONT_WEIGHT),
color: String(NEUTRAL_80$1),
letterSpacing: String(UTILITY_CAPTION_LETTER_SPACING),
textDecoration: String(UTILITY_CAPTION_TEXT_DECORATION),
},
};
const Display = ({ size = "2xl", align = "left", color, truncate = false, lineClamp, children, style, onPress, testID, }) => {
const tokenSet = size === "2xl" ? typographyTokens.display2xl : typographyTokens.displayXl;
const fontWeightValue = parseInt(tokenSet.fontWeight);
const textStyle = {
fontFamily: tokenSet.fontFamily,
fontSize: tokenSet.fontSize,
lineHeight: tokenSet.lineHeight,
fontWeight: fontWeightValue,
color: color || tokenSet.color,
textAlign: align,
letterSpacing: tokenSet.letterSpacing,
};
const textProps = {
style: [textStyle, style],
numberOfLines: truncate ? 1 : lineClamp,
ellipsizeMode: truncate || lineClamp ? "tail" : undefined,
testID,
};
if (onPress) {
return (jsx(Pressable, { onPress: onPress, children: jsx(Text, { ...textProps, children: children }) }));
}
return jsx(Text, { ...textProps, children: children });
};
const headingTokenKey = {
xl: "headingXl",
lg: "headingLg",
md: "headingMd",
sm: "headingSm",
xs: "headingXs",
"2xs": "heading2xs",
};
const Heading = ({ size = "xl", align = "left", color, truncate = false, lineClamp, children, style, onPress, testID, }) => {
const tokenSet = typographyTokens[headingTokenKey[size]];
const fontWeightValue = parseInt(tokenSet.fontWeight);
const textStyle = {
fontFamily: tokenSet.fontFamily,
fontSize: tokenSet.fontSize,
lineHeight: tokenSet.lineHeight,
fontWeight: fontWeightValue,
color: color || tokenSet.color,
textAlign: align,
letterSpacing: tokenSet.letterSpacing,
};
const textProps = {
style: [textStyle, style],
numberOfLines: truncate ? 1 : lineClamp,
ellipsizeMode: truncate || lineClamp ? "tail" : undefined,
testID,
};
if (onPress) {
return (jsx(Pressable, { onPress: onPress, children: jsx(Text, { ...textProps, children: children }) }));
}
return jsx(Text, { ...textProps, children: children });
};
const Body = ({ size = "lg", align = "left", color, truncate = false, lineClamp, children, style, onPress, testID, }) => {
const tokenMap = {
xl: typographyTokens.bodyXl,
lg: typographyTokens.bodyLg,
md: typographyTokens.bodyMd,
sm: typographyTokens.bodySm,
};
const tokenSet = tokenMap[size];
const fontWeightValue = parseInt(tokenSet.fontWeight);
const textStyle = {
fontFamily: tokenSet.fontFamily,
fontSize: tokenSet.fontSize,
lineHeight: tokenSet.lineHeight,
fontWeight: fontWeightValue,
color: color || tokenSet.color,
textAlign: align,
letterSpacing: tokenSet.letterSpacing,
};
const textProps = {
style: [textStyle, style],
numberOfLines: truncate ? 1 : lineClamp,
ellipsizeMode: truncate || lineClamp ? "tail" : undefined,
testID,
};
if (onPress) {
return (jsx(Pressable, { onPress: onPress, children: jsx(Text, { ...textProps, children: children }) }));
}
return jsx(Text, { ...textProps, children: children });
};
const Utility = ({ variant = "button", align = "left", color, truncate = false, lineClamp, children, style, onPress, testID, }) => {
const tokenMap = {
button: typographyTokens.labelLg,
link: typographyTokens.labelMd,
caption: typographyTokens.labelSm,
};
const tokenSet = tokenMap[variant];
const fontWeightValue = parseInt(tokenSet.fontWeight);
const textStyle = {
fontFamily: tokenSet.fontFamily,
fontSize: tokenSet.fontSize,
lineHeight: tokenSet.lineHeight,
fontWeight: fontWeightValue,
color: color || tokenSet.color,
textAlign: align,
letterSpacing: tokenSet.letterSpacing,
textDecorationLine: variant === "link" ? "underline" : "none",
};
const textProps = {
style: [textStyle, style],
numberOfLines: truncate ? 1 : lineClamp,
ellipsizeMode: truncate || lineClamp ? "tail" : undefined,
testID,
};
if (onPress) {
return (jsx(Pressable, { onPress: onPress, children: jsx(Text, { ...textProps, children: children }) }));
}
return jsx(Text, { ...textProps, children: children });
};
export { Body, Button, Display, Heading, Utility };
//# sourceMappingURL=index.mobile.js.map