index.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import {
  2. type FC
  3. } from "react";
  4. import {
  5. TouchableOpacity,
  6. View
  7. } from "react-native";
  8. import type IButtonProps from "./type";
  9. import stylesheet, {
  10. getButtonVariant,
  11. getButtonSize,
  12. getButtonType,
  13. useStyles
  14. } from "./stylesheet";
  15. import {
  16. NCoreUIKitTheme
  17. } from "../../core/hooks";
  18. import type ITextProps from "../text/type";
  19. import Loading from "../loading";
  20. import Text from "../text";
  21. /**
  22. * A generic button
  23. * @param props {@link IButtonProps}
  24. * @returns Element
  25. */
  26. const Button: FC<IButtonProps> = ({
  27. displayBehaviourWhileLoading = "disabled",
  28. spreadBehaviour = "baseline",
  29. isCustomPadding = false,
  30. icon: IconComponentProp,
  31. iconDirection = "left",
  32. variant = "filled",
  33. isDisabled = false,
  34. customBorderColor,
  35. type = "primary",
  36. customIconColor,
  37. customTextColor,
  38. size = "medium",
  39. renderLoading,
  40. customColor,
  41. customTheme,
  42. titleStyle,
  43. isLoading,
  44. iconSize,
  45. onPress,
  46. title,
  47. style,
  48. ...props
  49. }) => {
  50. const {
  51. typography,
  52. radiuses,
  53. borders,
  54. colors,
  55. spaces
  56. } = NCoreUIKitTheme.useContext(customTheme);
  57. const currentSize = getButtonSize({
  58. spaces,
  59. size
  60. });
  61. const currentVariant = getButtonVariant({
  62. variant,
  63. });
  64. const currentType = getButtonType({
  65. type,
  66. });
  67. const {
  68. container: containerDynamicStyle,
  69. loading: loadingDynamicStyle,
  70. overlay: overlayDynamicStyle,
  71. title: titleDynamicStyle
  72. } = useStyles({
  73. displayBehaviourWhileLoading,
  74. icon: IconComponentProp,
  75. customBorderColor,
  76. isCustomPadding,
  77. spreadBehaviour,
  78. currentVariant,
  79. iconDirection,
  80. currentType,
  81. currentSize,
  82. customColor,
  83. isDisabled,
  84. isLoading,
  85. radiuses,
  86. variant,
  87. borders,
  88. colors,
  89. spaces,
  90. title,
  91. type
  92. });
  93. const titleProps: ITextProps = {
  94. color: currentType.titleColor
  95. };
  96. const iconProps: NCoreUIKit.IconCallbackProps = {
  97. size: iconSize ? iconSize : Number(typography[currentSize.fontSize].fontSize),
  98. color: currentType.iconColor
  99. };
  100. if (currentVariant.titleColor !== "type") {
  101. titleProps.color = currentType.titleColor;
  102. }
  103. if (currentVariant.iconColor !== "type") {
  104. iconProps.color = currentType.iconColor;
  105. }
  106. if (type === "primary" && variant === "filled") {
  107. iconProps.color = "onPrimary";
  108. titleProps.color = "onPrimary";
  109. }
  110. if (type === "primary" && variant !== "filled") {
  111. iconProps.color = "emphasized";
  112. titleProps.color = "emphasized";
  113. }
  114. if (isDisabled || isLoading) {
  115. const stateType = type === "danger" ? "error" : type;
  116. titleProps.customColor = colors.system.state.content.disabled[stateType];
  117. iconProps.customColor = colors.system.state.content.disabled[stateType];
  118. }
  119. const renderIcon = () => {
  120. if(!isDisabled && !isLoading) {
  121. if(customTextColor) {
  122. const _customTextColor = customTextColor as keyof NCoreUIKit.ProjectColorPalette;
  123. iconProps.customColor = colors.project[_customTextColor] ? colors.project[_customTextColor] : customTextColor;
  124. }
  125. if(customIconColor) {
  126. const _customIconColor = customIconColor as keyof NCoreUIKit.ProjectColorPalette;
  127. iconProps.customColor = colors.project[_customIconColor] ? colors.project[_customIconColor] : customIconColor;
  128. }
  129. }
  130. if (isLoading) {
  131. if(renderLoading) {
  132. return renderLoading();
  133. }
  134. return <Loading
  135. {...iconProps}
  136. style={{
  137. ...loadingDynamicStyle
  138. }}
  139. />;
  140. }
  141. if (!IconComponentProp) {
  142. return null;
  143. }
  144. return <IconComponentProp {...iconProps} />;
  145. };
  146. const renderTitle = () => {
  147. if (!title) {
  148. return null;
  149. }
  150. if(!isDisabled && !isLoading) {
  151. if(customTextColor) {
  152. titleProps.customColor = customTextColor;
  153. }
  154. }
  155. return <Text
  156. variant={currentSize.fontSize}
  157. style={[
  158. titleStyle,
  159. stylesheet.title,
  160. titleDynamicStyle
  161. ]}
  162. {...titleProps}
  163. >
  164. {title}
  165. </Text>;
  166. };
  167. const renderOverlay = () => {
  168. return <View
  169. style={[
  170. stylesheet.loading,
  171. stylesheet.overlay,
  172. overlayDynamicStyle
  173. ]}
  174. />;
  175. };
  176. return <TouchableOpacity
  177. {...props}
  178. onPress={isDisabled || isLoading ? () => null : onPress}
  179. disabled={isDisabled || isLoading}
  180. style={[
  181. style,
  182. stylesheet.container,
  183. containerDynamicStyle
  184. ]}
  185. >
  186. {renderIcon()}
  187. {renderTitle()}
  188. {renderOverlay()}
  189. </TouchableOpacity>;
  190. };
  191. export default Button;