@app-studio/web 0.9.12 → 0.9.14

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.
@@ -61,11 +61,27 @@ export interface TitleProps extends ViewProps {
61
61
  * This should be an animation object with properties like from, to, duration, etc.
62
62
  */
63
63
  animate?: AnimationProps | AnimationProps[];
64
+ /**
65
+ * Controls the animation loop behavior for the title animation
66
+ * @default '1' (play once)
67
+ */
68
+ animationLoop?: number | 'infinite';
69
+ /**
70
+ * Controls the animation loop behavior for the highlight animation
71
+ * @default '1' (play once)
72
+ */
73
+ highlightAnimationLoop?: number | 'infinite';
64
74
  /**
65
75
  * Size of the title
66
76
  * @default 'xl'
67
77
  */
68
78
  size?: TitleSize;
79
+ /**
80
+ * Whether to enable responsive sizing based on breakpoints
81
+ * When true, the title will automatically adapt its size across mobile/tablet/desktop
82
+ * @default false
83
+ */
84
+ responsive?: boolean;
69
85
  /**
70
86
  * Whether to center the title
71
87
  * @default false
@@ -14,6 +14,33 @@ export declare const TitleSizes: {
14
14
  * Line heights for different title sizes
15
15
  */
16
16
  export declare const LineHeights: Record<TitleSize, number>;
17
+ /**
18
+ * Responsive typography system that maps title sizes to responsive breakpoints
19
+ * Based on the Typography system with dynamic breakpoint sizing
20
+ */
21
+ export declare const ResponsiveTypography: Record<TitleSize, {
22
+ lineHeight: string;
23
+ fontWeight: number;
24
+ marginBottom?: number;
25
+ letterSpacing?: number;
26
+ media: {
27
+ mobile: {
28
+ fontSize: number;
29
+ width?: string;
30
+ minWidth?: string;
31
+ };
32
+ tablet: {
33
+ fontSize: number;
34
+ width?: string;
35
+ minWidth?: string;
36
+ };
37
+ desktop: {
38
+ fontSize: number;
39
+ width?: string;
40
+ minWidth?: string;
41
+ };
42
+ };
43
+ }>;
17
44
  /**
18
45
  * Default styles for different highlight types
19
46
  */
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ /**
3
+ * Examples of Title with different animation loop controls
4
+ */
5
+ export declare const AnimationLoopTitle: () => React.JSX.Element;
@@ -1,6 +1,7 @@
1
1
  export * from './default';
2
2
  export * from './highlighted';
3
3
  export * from './animated';
4
+ export * from './animationLoop';
4
5
  export * from './hero';
5
6
  export * from './responsive';
6
7
  export * from './custom';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
2
  /**
3
- * Example of responsive Title using media queries
3
+ * Example of responsive Title using the new responsive prop
4
4
  */
5
5
  export declare const ResponsiveTitle: () => React.JSX.Element;
@@ -1,2 +1,8 @@
1
- import { Shape } from './Toggle.type';
1
+ import { ViewProps } from 'app-studio';
2
+ import { Shape, Variant } from './Toggle.type';
2
3
  export declare const ToggleShapes: Record<Shape, number | string>;
4
+ /**
5
+ * Generate toggle variants with proper color combinations based on main color and contrast
6
+ * Similar to Button's getButtonVariants function
7
+ */
8
+ export declare const getToggleVariants: (color: string, isLight: boolean) => Record<Variant, ViewProps>;
@@ -5,6 +5,9 @@ interface Props extends ToggleViewProps {
5
5
  views?: {
6
6
  container?: ViewProps;
7
7
  };
8
+ backgroundColor?: string;
9
+ color?: string;
10
+ themeMode?: 'light' | 'dark';
8
11
  }
9
12
  declare const ToggleView: React.FC<Props>;
10
13
  export default ToggleView;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ /**
3
+ * Demo page showcasing the responsive Title component functionality
4
+ */
5
+ export declare const ResponsiveTitleDemoPage: () => React.JSX.Element;
6
+ export default ResponsiveTitleDemoPage;
@@ -16604,6 +16604,99 @@ var LineHeights$1 = {
16604
16604
  lg: 72,
16605
16605
  xl: 80
16606
16606
  };
16607
+ /**
16608
+ * Responsive typography system that maps title sizes to responsive breakpoints
16609
+ * Based on the Typography system with dynamic breakpoint sizing
16610
+ */
16611
+ var ResponsiveTypography = {
16612
+ // xl maps to H1 - Largest heading
16613
+ xl: {
16614
+ lineHeight: '120%',
16615
+ fontWeight: 500,
16616
+ marginBottom: 20,
16617
+ letterSpacing: 1.25,
16618
+ media: {
16619
+ mobile: {
16620
+ fontSize: 42,
16621
+ width: '100%'
16622
+ },
16623
+ tablet: {
16624
+ fontSize: 50,
16625
+ width: '100%'
16626
+ },
16627
+ desktop: {
16628
+ fontSize: 58,
16629
+ minWidth: '60%'
16630
+ }
16631
+ }
16632
+ },
16633
+ // lg maps to H2 - Large heading
16634
+ lg: {
16635
+ lineHeight: '100%',
16636
+ fontWeight: 500,
16637
+ media: {
16638
+ mobile: {
16639
+ fontSize: 32
16640
+ },
16641
+ tablet: {
16642
+ fontSize: 40
16643
+ },
16644
+ desktop: {
16645
+ fontSize: 48
16646
+ }
16647
+ }
16648
+ },
16649
+ // md maps to H3 - Medium heading
16650
+ md: {
16651
+ lineHeight: '100%',
16652
+ fontWeight: 500,
16653
+ media: {
16654
+ mobile: {
16655
+ fontSize: 20
16656
+ },
16657
+ tablet: {
16658
+ fontSize: 30
16659
+ },
16660
+ desktop: {
16661
+ fontSize: 40
16662
+ }
16663
+ }
16664
+ },
16665
+ // sm maps to T1 - Title text
16666
+ sm: {
16667
+ lineHeight: '100%',
16668
+ fontWeight: 400,
16669
+ letterSpacing: -0.2,
16670
+ media: {
16671
+ mobile: {
16672
+ fontSize: 16
16673
+ },
16674
+ tablet: {
16675
+ fontSize: 28
16676
+ },
16677
+ desktop: {
16678
+ fontSize: 32
16679
+ }
16680
+ }
16681
+ },
16682
+ // xs maps to S1 - Subtitle text
16683
+ xs: {
16684
+ lineHeight: '120%',
16685
+ fontWeight: 400,
16686
+ letterSpacing: -0.2,
16687
+ media: {
16688
+ mobile: {
16689
+ fontSize: 12
16690
+ },
16691
+ tablet: {
16692
+ fontSize: 18
16693
+ },
16694
+ desktop: {
16695
+ fontSize: 24
16696
+ }
16697
+ }
16698
+ }
16699
+ };
16607
16700
  /**
16608
16701
  * Default styles for different highlight types
16609
16702
  */
@@ -16722,7 +16815,7 @@ var TypewriterEffect = _ref => {
16722
16815
  }))))));
16723
16816
  };
16724
16817
 
16725
- var _excluded$S = ["children", "highlightText", "highlightStyle", "highlightColor", "highlightSecondaryColor", "size", "centered", "views", "highlightAnimate", "animate", "highlightTypewriter", "highlightTypewriterDuration"];
16818
+ var _excluded$S = ["children", "highlightText", "highlightStyle", "highlightColor", "highlightSecondaryColor", "size", "responsive", "centered", "views", "highlightAnimate", "animate", "animationLoop", "highlightAnimationLoop", "highlightTypewriter", "highlightTypewriterDuration"];
16726
16819
  function escapeRegExp(string) {
16727
16820
  return string.replace(/[.*+?^${}()|[\\]\\/g, '\\$&');
16728
16821
  }
@@ -16733,11 +16826,14 @@ var TitleView = _ref => {
16733
16826
  highlightStyle = 'background',
16734
16827
  highlightColor = 'theme.primary',
16735
16828
  highlightSecondaryColor,
16736
- size = 'xl',
16829
+ size = 'lg',
16830
+ responsive = true,
16737
16831
  centered = false,
16738
16832
  views,
16739
16833
  highlightAnimate,
16740
16834
  animate,
16835
+ animationLoop = 1,
16836
+ highlightAnimationLoop = 1,
16741
16837
  highlightTypewriter: propHighlightTypewriter = false,
16742
16838
  highlightTypewriterDuration = 3000
16743
16839
  } = _ref,
@@ -16775,8 +16871,27 @@ var TitleView = _ref => {
16775
16871
  highlightTypewriter: propHighlightTypewriter,
16776
16872
  highlightTypewriterDuration
16777
16873
  }, props));
16874
+ // Determine if we should use responsive sizing or static sizing
16875
+ var useResponsive = responsive && !props.media; // Don't override if media prop is already provided
16778
16876
  var fontSize = TitleSizes[size];
16779
16877
  var lineHeight = LineHeights$1[size];
16878
+ // Get responsive styles if responsive prop is true
16879
+ var responsiveStyles = useResponsive ? ResponsiveTypography[size] : null;
16880
+ // Helper function to apply loop control to animations
16881
+ var applyAnimationLoop = (animation, loopControl) => {
16882
+ if (!animation) return animation;
16883
+ if (Array.isArray(animation)) {
16884
+ return animation.map(anim => Object.assign({}, anim, {
16885
+ iterationCount: loopControl.toString()
16886
+ }));
16887
+ }
16888
+ return Object.assign({}, animation, {
16889
+ iterationCount: loopControl.toString()
16890
+ });
16891
+ };
16892
+ // Apply loop control to animations
16893
+ var controlledAnimate = applyAnimationLoop(animate, animationLoop);
16894
+ var controlledHighlightAnimate = applyAnimationLoop(highlightAnimate, highlightAnimationLoop);
16780
16895
  // Get the text to display
16781
16896
  var text = typeof finalDisplayedText === 'string' ? finalDisplayedText : typeof children === 'string' ? children : '';
16782
16897
  if (typeof text === 'string' && activeHighlightTarget) {
@@ -16800,16 +16915,19 @@ var TitleView = _ref => {
16800
16915
  return /*#__PURE__*/React__default.createElement(appStudio.Element, Object.assign({
16801
16916
  ref: ref,
16802
16917
  as: "h1",
16803
- fontSize: fontSize,
16804
- lineHeight: lineHeight + "px",
16805
- fontWeight: "bold",
16918
+ fontSize: useResponsive ? undefined : fontSize,
16919
+ lineHeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.lineHeight : lineHeight + "px",
16920
+ fontWeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.fontWeight : 'bold',
16921
+ letterSpacing: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.letterSpacing : undefined,
16922
+ marginBottom: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.marginBottom : undefined,
16806
16923
  textAlign: centered ? 'center' : 'left',
16807
- animate: inView ? animate : undefined
16924
+ animate: inView ? controlledAnimate : undefined,
16925
+ media: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.media : undefined
16808
16926
  }, views == null ? void 0 : views.container, props), parts.map((part, idx) => typeof part === 'string' ? part : (/*#__PURE__*/React__default.createElement(appStudio.Text, Object.assign({
16809
16927
  key: part.text + "-" + idx,
16810
16928
  as: "span",
16811
16929
  display: "inline",
16812
- animate: inView ? highlightAnimate : undefined
16930
+ animate: inView ? controlledHighlightAnimate : undefined
16813
16931
  }, HighlightStyles[highlightStyle](resolvedColor, resolvedSecondary), views == null ? void 0 : views.highlight), highlightTypewriter ? (/*#__PURE__*/React__default.createElement(TypewriterEffect, {
16814
16932
  text: part.text,
16815
16933
  typingSpeed: Math.max(30, highlightTypewriterDuration / (part.text.length * 10)),
@@ -16822,15 +16940,18 @@ var TitleView = _ref => {
16822
16940
  return /*#__PURE__*/React__default.createElement(appStudio.Element, Object.assign({
16823
16941
  ref: ref,
16824
16942
  as: "h1",
16825
- fontSize: fontSize,
16826
- lineHeight: lineHeight + "px",
16827
- fontWeight: "bold",
16943
+ fontSize: useResponsive ? undefined : fontSize,
16944
+ lineHeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.lineHeight : lineHeight + "px",
16945
+ fontWeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.fontWeight : 'bold',
16946
+ letterSpacing: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.letterSpacing : undefined,
16947
+ marginBottom: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.marginBottom : undefined,
16828
16948
  textAlign: centered ? 'center' : 'left',
16829
- animate: inView ? animate : undefined
16949
+ animate: inView ? controlledAnimate : undefined,
16950
+ media: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.media : undefined
16830
16951
  }, views == null ? void 0 : views.container, props), /*#__PURE__*/React__default.createElement(appStudio.Text, Object.assign({
16831
16952
  as: "span",
16832
16953
  display: "inline",
16833
- animate: inView ? highlightAnimate : undefined
16954
+ animate: inView ? controlledHighlightAnimate : undefined
16834
16955
  }, HighlightStyles[highlightStyle](resolvedColor, resolvedSecondary), views == null ? void 0 : views.highlight), highlightTypewriter ? (/*#__PURE__*/React__default.createElement(TypewriterEffect, {
16835
16956
  text: text,
16836
16957
  typingSpeed: Math.max(30, highlightTypewriterDuration / (text.length * 10)),
@@ -16842,11 +16963,14 @@ var TitleView = _ref => {
16842
16963
  return /*#__PURE__*/React__default.createElement(appStudio.Element, Object.assign({
16843
16964
  ref: ref,
16844
16965
  as: "h1",
16845
- fontSize: fontSize,
16846
- lineHeight: lineHeight + "px",
16847
- fontWeight: "bold",
16966
+ fontSize: useResponsive ? undefined : fontSize,
16967
+ lineHeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.lineHeight : lineHeight + "px",
16968
+ fontWeight: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.fontWeight : 'bold',
16969
+ letterSpacing: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.letterSpacing : undefined,
16970
+ marginBottom: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.marginBottom : undefined,
16848
16971
  textAlign: centered ? 'center' : 'left',
16849
- animate: inView ? animate : undefined
16972
+ animate: inView ? controlledAnimate : undefined,
16973
+ media: useResponsive ? responsiveStyles == null ? void 0 : responsiveStyles.media : undefined
16850
16974
  }, views == null ? void 0 : views.container, props), text);
16851
16975
  };
16852
16976
 
@@ -16912,8 +17036,78 @@ var useToggleState = defaultToggled => {
16912
17036
  };
16913
17037
  };
16914
17038
 
16915
- var _excluded$T = ["children", "shape", "variant", "isHovered", "setIsHovered", "isDisabled", "isToggle", "setIsToggled", "onToggle", "views"];
17039
+ var ToggleShapes = {
17040
+ sharp: 0,
17041
+ rounded: 4,
17042
+ pillShaped: 24
17043
+ };
17044
+ /**
17045
+ * Generate toggle variants with proper color combinations based on main color and contrast
17046
+ * Similar to Button's getButtonVariants function
17047
+ */
17048
+ var getToggleVariants = (color, isLight) => ({
17049
+ outline: {
17050
+ backgroundColor: 'transparent',
17051
+ color: color,
17052
+ borderWidth: 1,
17053
+ borderStyle: 'solid',
17054
+ borderColor: color,
17055
+ _hover: {
17056
+ backgroundColor: color,
17057
+ color: isLight ? 'color.black' : 'color.white',
17058
+ transform: 'translateY(-1px)'
17059
+ },
17060
+ _active: {
17061
+ backgroundColor: color,
17062
+ color: isLight ? 'color.black' : 'color.white',
17063
+ transform: 'translateY(0)'
17064
+ },
17065
+ transition: 'all 0.2s ease'
17066
+ },
17067
+ ghost: {
17068
+ backgroundColor: 'transparent',
17069
+ color: color,
17070
+ borderWidth: 0,
17071
+ borderStyle: 'none',
17072
+ borderColor: 'transparent',
17073
+ _hover: {
17074
+ backgroundColor: color,
17075
+ color: isLight ? 'color.black' : 'color.white',
17076
+ transform: 'translateY(-1px)'
17077
+ },
17078
+ _active: {
17079
+ backgroundColor: color,
17080
+ color: isLight ? 'color.black' : 'color.white',
17081
+ transform: 'translateY(0)'
17082
+ },
17083
+ transition: 'all 0.2s ease'
17084
+ },
17085
+ link: {
17086
+ backgroundColor: 'transparent',
17087
+ color: color,
17088
+ borderWidth: 1,
17089
+ borderStyle: 'solid',
17090
+ borderColor: 'transparent',
17091
+ textDecoration: 'underline',
17092
+ textUnderlineOffset: '1px',
17093
+ textDecorationThickness: '1px',
17094
+ _hover: {
17095
+ borderColor: color,
17096
+ textDecorationThickness: '2px',
17097
+ transform: 'translateY(-1px)'
17098
+ },
17099
+ _active: {
17100
+ borderColor: color,
17101
+ textDecorationThickness: '2px',
17102
+ transform: 'translateY(0)'
17103
+ },
17104
+ transition: 'all 0.2s ease'
17105
+ }
17106
+ });
17107
+
17108
+ var _excluded$T = ["children", "shape", "variant", "isHovered", "setIsHovered", "isDisabled", "isToggle", "setIsToggled", "onToggle", "views", "backgroundColor", "color", "themeMode"];
16916
17109
  var ToggleView = _ref => {
17110
+ var _ref2;
16917
17111
  var {
16918
17112
  children,
16919
17113
  shape = 'rounded',
@@ -16924,25 +17118,30 @@ var ToggleView = _ref => {
16924
17118
  isToggle,
16925
17119
  setIsToggled,
16926
17120
  onToggle,
16927
- views
17121
+ views,
17122
+ backgroundColor,
17123
+ // primary candidate for main color
17124
+ color,
17125
+ // 2nd candidate for main color
17126
+ themeMode: elementMode
16928
17127
  } = _ref,
16929
17128
  props = _objectWithoutPropertiesLoose(_ref, _excluded$T);
16930
- var toggleColor = !isDisabled ? 'color.trueGray.400' : 'theme.disabled';
17129
+ /* theme helpers */
17130
+ var {
17131
+ getColor,
17132
+ themeMode
17133
+ } = appStudio.useTheme();
17134
+ var mode = elementMode != null ? elementMode : themeMode;
17135
+ /* MAIN COLOR – determines the entire palette */
17136
+ var mainColorKey = (_ref2 = backgroundColor != null ? backgroundColor : color) != null ? _ref2 : 'theme.primary';
17137
+ var mainTone = getColor(isDisabled ? 'theme.disabled' : mainColorKey, {
17138
+ themeMode: mode
17139
+ });
17140
+ var tone = contrast(mainTone);
17141
+ /* variant palette */
17142
+ var palette = React.useMemo(() => getToggleVariants(mainTone, tone === 'light'), [mainTone, tone]);
17143
+ var base = palette[variant];
16931
17144
  var isActive = !!(isToggle || isHovered);
16932
- var toggleVariants = {
16933
- outline: {
16934
- borderWidth: 1,
16935
- borderStyle: 'solid',
16936
- borderColor: 'color.trueGray.400'
16937
- },
16938
- link: {
16939
- borderWidth: 1,
16940
- borderStyle: 'solid',
16941
- borderColor: isActive ? toggleColor : 'transparent',
16942
- textDecoration: 'underline'
16943
- },
16944
- ghost: {}
16945
- };
16946
17145
  var handleHover = () => setIsHovered(!isHovered);
16947
17146
  var handleToggle = () => {
16948
17147
  if (!isDisabled) {
@@ -16959,14 +17158,15 @@ var ToggleView = _ref => {
16959
17158
  role: "Toggle",
16960
17159
  padding: shape === 'pillShaped' ? '10px 12px' : '8px',
16961
17160
  width: "fit-content",
16962
- color: isActive ? 'color.white' : toggleColor,
16963
- backgroundColor: isActive ? toggleColor : 'transparent',
16964
- onMouseEnter: handleHover,
16965
- onMouseLeave: () => setIsHovered(false),
16966
17161
  cursor: isDisabled ? 'not-allowed' : 'pointer',
16967
- borderRadius: shape === 'pillShaped' ? '50px' : '8px',
16968
- onClick: handleToggle
16969
- }, toggleVariants[variant], props, views == null ? void 0 : views.container), children);
17162
+ borderRadius: ToggleShapes[shape],
17163
+ onClick: handleToggle,
17164
+ onMouseEnter: handleHover,
17165
+ onMouseLeave: () => setIsHovered(false)
17166
+ }, base, isActive && {
17167
+ backgroundColor: mainTone,
17168
+ color: tone === 'light' ? 'color.black' : 'color.white'
17169
+ }, props, views == null ? void 0 : views.container), children);
16970
17170
  };
16971
17171
 
16972
17172
  var _excluded$U = ["children", "shape", "variant", "isDisabled", "isToggled", "onToggle"];