@bravostudioai/react 0.1.45 → 0.1.47

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.
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/components.tsx"],"names":[],"mappings":"AACA,OAAO,KAMN,MAAM,OAAO,CAAC;AAkvGf,QAAA,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAwDxD,CAAC;AAEF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/components.tsx"],"names":[],"mappings":"AACA,OAAO,KAMN,MAAM,OAAO,CAAC;AA+uGf,QAAA,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAwDxD,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "0.1.45";
1
+ export declare const PACKAGE_VERSION = "0.1.47";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- const o = "0.1.45";
1
+ const o = "0.1.47";
2
2
  export {
3
3
  o as PACKAGE_VERSION
4
4
  };
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"0.1.45\";\n"],"names":["PACKAGE_VERSION"],"mappings":"AAAO,MAAMA,IAAkB;"}
1
+ {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"0.1.47\";\n"],"names":["PACKAGE_VERSION"],"mappings":"AAAO,MAAMA,IAAkB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bravostudioai/react",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/src/index.d.ts",
@@ -40,7 +40,7 @@ interface ComponentProps {
40
40
 
41
41
  const EncorePageContext = React.createContext<EncorePageContextType>({});
42
42
  const EncoreContainerContext = React.createContext<EncoreContainerContextType>(
43
- {}
43
+ {},
44
44
  );
45
45
 
46
46
  const argbAlphaToOpacity = (color: string): number => {
@@ -58,7 +58,7 @@ const argbIsFullyTransparent = (color: string): boolean => {
58
58
 
59
59
  // Parse input-group tag: "input-group:single:product_purpose" -> { type: "single", groupName: "product_purpose" }
60
60
  const parseInputGroupTag = (
61
- tags: string[] | undefined
61
+ tags: string[] | undefined,
62
62
  ): { type: string; groupName: string } | null => {
63
63
  if (!Array.isArray(tags)) return null;
64
64
  const inputGroupTag = tags.find((tag) => tag.startsWith("input-group:"));
@@ -111,7 +111,7 @@ const useContainerDimensions = (): {
111
111
 
112
112
  const useEncoreStyle = (
113
113
  style: any,
114
- opts: { debug?: boolean } = {}
114
+ opts: { debug?: boolean } = {},
115
115
  ): React.CSSProperties | undefined => {
116
116
  let shouldCenterHorizontally = false; // Track if element should be centered
117
117
  const pageContext = useContext(EncorePageContext);
@@ -125,7 +125,7 @@ const useEncoreStyle = (
125
125
  (v: number) => {
126
126
  return (containerContext.dimensions?.width ?? 0) * 0.01 * v;
127
127
  },
128
- [containerContext.dimensions?.width]
128
+ [containerContext.dimensions?.width],
129
129
  );
130
130
 
131
131
  const result: React.CSSProperties = {};
@@ -279,7 +279,7 @@ const useEncoreStyle = (
279
279
 
280
280
  // Map Figma primaryAxisAlignItems values to CSS justify-content values
281
281
  const mapJustifyContent = (
282
- figmaValue: string | undefined
282
+ figmaValue: string | undefined,
283
283
  ): string | undefined => {
284
284
  if (!figmaValue) return undefined;
285
285
  const mapping: Record<string, string> = {
@@ -300,13 +300,13 @@ const useEncoreStyle = (
300
300
  result.flexWrap = style.layout.flexWrap;
301
301
  }
302
302
  result.justifyContent = mapJustifyContent(
303
- style.layout.primaryAxisAlignItems
303
+ style.layout.primaryAxisAlignItems,
304
304
  );
305
305
  result.alignItems = style.layout.counterAxisAlignItems;
306
306
  } else {
307
307
  result.flexDirection = "column";
308
308
  result.justifyContent = mapJustifyContent(
309
- style.layout.primaryAxisAlignItems
309
+ style.layout.primaryAxisAlignItems,
310
310
  );
311
311
  result.alignItems = style.layout.counterAxisAlignItems;
312
312
  }
@@ -372,7 +372,7 @@ const useEncoreStyle = (
372
372
  "[useEncoreStyle] No gap properties set",
373
373
  opts.debug,
374
374
  style.layout?.mode,
375
- itemSpacing
375
+ itemSpacing,
376
376
  );
377
377
  }
378
378
 
@@ -776,7 +776,7 @@ const EncoreLinkActionWrapper: React.FC<{
776
776
  const pageId = useEncoreState((state) => state.pageId);
777
777
  const { onAction } = React.useContext(EncoreActionContext);
778
778
  const { statefulSetId: parentStatefulSetIdFromContext } = React.useContext(
779
- EncoreComponentIdContext
779
+ EncoreComponentIdContext,
780
780
  );
781
781
  // Prefer prop over context (more reliable)
782
782
  const parentStatefulSetId =
@@ -785,10 +785,10 @@ const EncoreLinkActionWrapper: React.FC<{
785
785
  // const [searchParams] = useSearchParams();
786
786
  const { patchedNodeData } = useEncoreBinding({ id, nodeData });
787
787
  const setStatefulSetVariant = useEncoreState(
788
- (state) => state.setStatefulSetVariant
788
+ (state) => state.setStatefulSetVariant,
789
789
  );
790
790
  const setInputGroupValue = useEncoreState(
791
- (state) => state.setInputGroupValue
791
+ (state) => state.setInputGroupValue,
792
792
  );
793
793
  const setAccessToken = useEncoreState((state) => state.setAccessToken);
794
794
  const { app } = useEncoreState((state) => state.app);
@@ -796,30 +796,6 @@ const EncoreLinkActionWrapper: React.FC<{
796
796
  const startPageId = app.data?.app?.startPageId;
797
797
  const loginPageId = app.data?.app?.PageId;
798
798
 
799
- const style = useEncoreStyle(
800
- {
801
- positioning: nodeData.style?.positioning,
802
- },
803
- { debug: false }
804
- );
805
-
806
- // Make the wrapper div cover the entire button area
807
- // Use a very high z-index to ensure it's above all children
808
- // IMPORTANT: The overlay should be scoped to the immediate parent (the button),
809
- // not the entire StatefulSetComponent, to avoid overlapping with other buttons
810
- style.zIndex = 99999;
811
- style.backgroundColor = "transparent";
812
- style.position = "absolute";
813
- style.top = "0";
814
- style.left = "0";
815
- style.right = "0";
816
- style.bottom = "0";
817
- style.width = "100%";
818
- style.height = "100%";
819
- style.pointerEvents = "auto";
820
- // Ensure the overlay is contained within its parent button element
821
- style.isolation = "isolate";
822
-
823
799
  const handleAction = async (action: any) => {
824
800
  let proceed = false;
825
801
  const cancel = () => {
@@ -968,27 +944,23 @@ const EncoreLinkActionWrapper: React.FC<{
968
944
 
969
945
  if (nodeData.href) {
970
946
  return (
971
- <>
972
- <button
973
- type="button"
974
- onClick={() =>
975
- handleAction({
976
- action: "goto",
977
- params: { href: nodeData.href },
978
- event: "tap",
979
- })
980
- }
981
- style={{
982
- ...style,
983
- cursor: "pointer",
984
- background: "transparent",
985
- border: "none",
986
- padding: 0,
987
- }}
988
- aria-label={`Go to ${nodeData.href}`}
989
- ></button>
947
+ <div
948
+ onClick={() =>
949
+ handleAction({
950
+ action: "goto",
951
+ params: { href: nodeData.href },
952
+ event: "tap",
953
+ })
954
+ }
955
+ style={{
956
+ display: "contents",
957
+ cursor: "pointer",
958
+ }}
959
+ role="button"
960
+ aria-label={`Go to ${nodeData.href}`}
961
+ >
990
962
  {children}
991
- </>
963
+ </div>
992
964
  );
993
965
  }
994
966
 
@@ -1049,7 +1021,7 @@ const EncoreLinkActionWrapper: React.FC<{
1049
1021
  if (!targetStateSetId) {
1050
1022
  console.warn(
1051
1023
  "⚠️ No stateSetId available for stateful compound component",
1052
- { id, name: nodeData.name }
1024
+ { id, name: nodeData.name },
1053
1025
  );
1054
1026
  } else {
1055
1027
  const currentVariant =
@@ -1074,24 +1046,45 @@ const EncoreLinkActionWrapper: React.FC<{
1074
1046
 
1075
1047
  if (actions && actions.length > 0) {
1076
1048
  const action = actions[0];
1077
- if (action.event !== "tap") {
1078
- return children;
1079
- }
1049
+ if (action.event === "tap") {
1050
+ const clickHandler = (e: React.MouseEvent) => {
1051
+ // e.stopPropagation(); // Allow bubbling if needed, but usually we want to stop here to prevent parent actions?
1052
+ // Actually, for a button, we usually stop propagation.
1053
+ e.stopPropagation();
1054
+ handleAction(action);
1055
+ };
1080
1056
 
1081
- return (
1082
- <>
1083
- {children}
1084
- <div
1085
- onClick={(e) => {
1086
- e.stopPropagation();
1087
- handleAction(action);
1088
- }}
1089
- onMouseDown={(e) => e.stopPropagation()}
1090
- onMouseUp={(e) => e.stopPropagation()}
1091
- style={{ ...style, cursor: "pointer", pointerEvents: "auto" }}
1092
- ></div>
1093
- </>
1094
- );
1057
+ const wrapperStyle: React.CSSProperties = {
1058
+ display: "contents",
1059
+ cursor: "pointer",
1060
+ // Ensure the wrapper doesn't block pointer events, but its children should capture them.
1061
+ // pointerEvents: 'auto' is default.
1062
+ };
1063
+
1064
+ if (action.action === "openurl" && action.params?.url) {
1065
+ return (
1066
+ <a
1067
+ href={action.params.url}
1068
+ target="_blank"
1069
+ rel="noopener noreferrer"
1070
+ onClick={(e) => {
1071
+ e.stopPropagation();
1072
+ // handleAction(action); // Optional side effect
1073
+ }}
1074
+ style={wrapperStyle}
1075
+ aria-label={nodeData.name || "Open Link"}
1076
+ >
1077
+ {children}
1078
+ </a>
1079
+ );
1080
+ }
1081
+
1082
+ return (
1083
+ <div onClick={clickHandler} style={wrapperStyle}>
1084
+ {children}
1085
+ </div>
1086
+ );
1087
+ }
1095
1088
  }
1096
1089
 
1097
1090
  return children;
@@ -1722,11 +1715,11 @@ const TextComponent: React.FC<ComponentProps> = ({ id, name, nodeData }) => {
1722
1715
  textContent && (textContent.includes("\n") || textContent.includes("\r"));
1723
1716
  let renderedContent;
1724
1717
  if (hasLineBreaks && style.flexDirection === "column") {
1725
- // Split by newlines and carriage returns, filter out empty strings from \r\n combinations
1726
- const lines = textContent.split(/\r?\n/).filter((line) => line.length > 0);
1718
+ // Split by newlines and carriage returns, preserve empty lines for "double spacing"
1719
+ const lines = textContent.split(/\r?\n/);
1727
1720
  renderedContent = lines.map((line, index) => (
1728
1721
  <div key={index} style={{ lineHeight: "inherit" }}>
1729
- {line}
1722
+ {line || "\u00A0"}
1730
1723
  </div>
1731
1724
  ));
1732
1725
  } else {
@@ -1934,7 +1927,7 @@ const ContainerComponent = ({
1934
1927
  if (id === "01KB929X1KK5TX0K8VBNP6ZDPG") {
1935
1928
  console.log(
1936
1929
  `[DEBUG] ContainerComponent ${id} (Hero) FULL nodeData:`,
1937
- JSON.stringify(nodeData, null, 2)
1930
+ JSON.stringify(nodeData, null, 2),
1938
1931
  );
1939
1932
  }
1940
1933
  const bindingContext = useContext(EncoreBindingContext);
@@ -2044,15 +2037,18 @@ const ContainerComponent = ({
2044
2037
  nodeData.style.layout?.layoutSizingHorizontal ||
2045
2038
  nodeData.style.layout?.layoutSizingVertical;
2046
2039
  const shouldBeAbsolute =
2047
- nodeData.style.positioning && !isFlex && (hasLayoutSizing || true);
2040
+ nodeData.style.positioning &&
2041
+ !isFlex &&
2042
+ !parentIsFlex &&
2043
+ (hasLayoutSizing || true);
2048
2044
 
2049
2045
  // Only force position: relative if the element shouldn't be absolutely positioned.
2050
2046
  // This allows absolutely positioned children (with layout sizing) to remain absolute.
2051
2047
  const finalStyle = shouldBeAbsolute
2052
2048
  ? { ...style, position: "absolute" }
2053
2049
  : style.position === "absolute"
2054
- ? style
2055
- : { ...style, position: style.position || "relative" };
2050
+ ? style
2051
+ : { ...style, position: style.position || "relative" };
2056
2052
 
2057
2053
  // For containers with explicit dimensions from layout.size, use the scaled dimensions
2058
2054
  // from style (which are calculated from layout.size * scaleFactor) for child context.
@@ -2187,7 +2183,7 @@ const ContainerComponent = ({
2187
2183
  ...(typeof actionData === "object" && actionData !== null
2188
2184
  ? actionData
2189
2185
  : {}),
2190
- })
2186
+ }),
2191
2187
  );
2192
2188
  }
2193
2189
  const hasActions = Array.isArray(actions) && actions.length > 0;
@@ -2297,7 +2293,7 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2297
2293
  if (id === "01KB929X1DQJN954WNGF5AH38B") {
2298
2294
  console.log(
2299
2295
  `[DEBUG] SliderComponent ${id} FULL nodeData:`,
2300
- JSON.stringify(nodeData, null, 2)
2296
+ JSON.stringify(nodeData, null, 2),
2301
2297
  );
2302
2298
  }
2303
2299
  // Log slider component data for inspection
@@ -2369,8 +2365,8 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2369
2365
  const animation = shouldBeVertical
2370
2366
  ? "vertical"
2371
2367
  : params.animation === "default"
2372
- ? "horizontal"
2373
- : params.animation || "horizontal";
2368
+ ? "horizontal"
2369
+ : params.animation || "horizontal";
2374
2370
 
2375
2371
  const style = useEncoreStyle(nodeData.style, {
2376
2372
  debug: false,
@@ -2426,7 +2422,7 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2426
2422
  // ContainerComponent will use this to know which item to render
2427
2423
  _arrayItemIndex: i,
2428
2424
  _arrayItemData: item,
2429
- })
2425
+ }),
2430
2426
  );
2431
2427
  });
2432
2428
  } else {
@@ -2580,7 +2576,7 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2580
2576
  });
2581
2577
  }
2582
2578
  },
2583
- [slideWidth, slideHeight, infinite, childList.length, isVertical]
2579
+ [slideWidth, slideHeight, infinite, childList.length, isVertical],
2584
2580
  );
2585
2581
 
2586
2582
  // Handle infinite scroll position adjustment
@@ -2776,7 +2772,7 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2776
2772
  }
2777
2773
  }
2778
2774
  },
2779
- [onAction, id] // Depend on onAction to ensure we call the latest version
2775
+ [onAction, id], // Depend on onAction to ensure we call the latest version
2780
2776
  );
2781
2777
 
2782
2778
  // Set up scroll event listeners
@@ -2860,7 +2856,7 @@ const SliderComponent = ({ id, name, nodeData, children }) => {
2860
2856
  ) {
2861
2857
  const targetIndex = Math.max(
2862
2858
  0,
2863
- Math.min(controlProps.currentIndex, childList.length - 1)
2859
+ Math.min(controlProps.currentIndex, childList.length - 1),
2864
2860
  );
2865
2861
  const currentIndex = calculateCurrentIndex();
2866
2862
  if (targetIndex !== currentIndex) {
@@ -3119,7 +3115,7 @@ const PageComponent = ({ id, name, nodeData, children }) => {
3119
3115
  {
3120
3116
  scrollableChildren: [],
3121
3117
  nonScrollableChildren: [],
3122
- }
3118
+ },
3123
3119
  );
3124
3120
 
3125
3121
  // Determine the layout direction from nodeData
@@ -3160,7 +3156,7 @@ const PageComponent = ({ id, name, nodeData, children }) => {
3160
3156
 
3161
3157
  if (shouldPatch) {
3162
3158
  console.log(
3163
- `[PATCH] Detected HORIZONTAL WRAP layout for page ${id} (Partial width children: ${partialWidthChildren}, Total width: ${totalWidth})`
3159
+ `[PATCH] Detected HORIZONTAL WRAP layout for page ${id} (Partial width children: ${partialWidthChildren}, Total width: ${totalWidth})`,
3164
3160
  );
3165
3161
  pageLayoutMode = "HORIZONTAL";
3166
3162
 
@@ -3180,7 +3176,7 @@ const PageComponent = ({ id, name, nodeData, children }) => {
3180
3176
  // Check if we have nonScrollableChildren that actually need flex positioning
3181
3177
  // BackgroundContainerComponent is absolutely positioned, so it doesn't need flex
3182
3178
  const needsFlexContainer = nonScrollableChildren.some(
3183
- (child) => child?.props?.nodeData?.type !== "container:background"
3179
+ (child) => child?.props?.nodeData?.type !== "container:background",
3184
3180
  );
3185
3181
 
3186
3182
  return (
@@ -3212,7 +3208,7 @@ const PageComponent = ({ id, name, nodeData, children }) => {
3212
3208
  {/* Render backgrounds directly - they're absolutely positioned */}
3213
3209
  {nonScrollableChildren
3214
3210
  .filter(
3215
- (child) => child?.props?.nodeData?.type === "container:background"
3211
+ (child) => child?.props?.nodeData?.type === "container:background",
3216
3212
  )
3217
3213
  .map((child, index) => (
3218
3214
  <EncoreContainerContext.Provider
@@ -3232,7 +3228,8 @@ const PageComponent = ({ id, name, nodeData, children }) => {
3232
3228
  {needsFlexContainer &&
3233
3229
  nonScrollableChildren
3234
3230
  .filter(
3235
- (child) => child?.props?.nodeData?.type !== "container:background"
3231
+ (child) =>
3232
+ child?.props?.nodeData?.type !== "container:background",
3236
3233
  )
3237
3234
  .map((child, index) => (
3238
3235
  <EncoreContainerContext.Provider
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = "0.1.45";
1
+ export const PACKAGE_VERSION = "0.1.47";