@bravostudioai/react 0.1.0
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.
- package/bin/encore-lib.js +3 -0
- package/dist/_virtual/_commonjsHelpers.js +7 -0
- package/dist/_virtual/_commonjsHelpers.js.map +1 -0
- package/dist/_virtual/main.js +8 -0
- package/dist/_virtual/main.js.map +1 -0
- package/dist/_virtual/main2.js +5 -0
- package/dist/_virtual/main2.js.map +1 -0
- package/dist/app.js +9 -0
- package/dist/app.js.map +1 -0
- package/dist/cli/commands/download.js +82 -0
- package/dist/cli/commands/download.js.map +1 -0
- package/dist/cli/commands/generate.js +1526 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/components/DynamicComponent.js +24 -0
- package/dist/components/DynamicComponent.js.map +1 -0
- package/dist/components/EncoreApp.js +259 -0
- package/dist/components/EncoreApp.js.map +1 -0
- package/dist/components/EncoreErrorBoundary.js +33 -0
- package/dist/components/EncoreErrorBoundary.js.map +1 -0
- package/dist/components/EncoreLoadingFallback.js +20 -0
- package/dist/components/EncoreLoadingFallback.js.map +1 -0
- package/dist/components.js +1454 -0
- package/dist/components.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/contexts/EncoreActionContext.js +6 -0
- package/dist/contexts/EncoreActionContext.js.map +1 -0
- package/dist/contexts/EncoreAppContext.js +9 -0
- package/dist/contexts/EncoreAppContext.js.map +1 -0
- package/dist/contexts/EncoreBindingContext.js +6 -0
- package/dist/contexts/EncoreBindingContext.js.map +1 -0
- package/dist/contexts/EncoreComponentIdContext.js +8 -0
- package/dist/contexts/EncoreComponentIdContext.js.map +1 -0
- package/dist/contexts/EncoreRepeatingContainerContext.js +6 -0
- package/dist/contexts/EncoreRepeatingContainerContext.js.map +1 -0
- package/dist/hooks/usePusherUpdates.js +60 -0
- package/dist/hooks/usePusherUpdates.js.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/dynamicModules.js +132 -0
- package/dist/lib/dynamicModules.js.map +1 -0
- package/dist/lib/fetcher.js +58 -0
- package/dist/lib/fetcher.js.map +1 -0
- package/dist/lib/localMode.js +21 -0
- package/dist/lib/localMode.js.map +1 -0
- package/dist/lib/packages.js +18 -0
- package/dist/lib/packages.js.map +1 -0
- package/dist/node_modules/dotenv/lib/main.js +198 -0
- package/dist/node_modules/dotenv/lib/main.js.map +1 -0
- package/dist/node_modules/dotenv/package.json.js +8 -0
- package/dist/node_modules/dotenv/package.json.js.map +1 -0
- package/dist/packages/encore-lib/constants.js +6 -0
- package/dist/packages/encore-lib/constants.js.map +1 -0
- package/dist/src/app.d.ts +5 -0
- package/dist/src/app.d.ts.map +1 -0
- package/dist/src/cli/commands/download.d.ts +2 -0
- package/dist/src/cli/commands/download.d.ts.map +1 -0
- package/dist/src/cli/commands/generate.d.ts +2 -0
- package/dist/src/cli/commands/generate.d.ts.map +1 -0
- package/dist/src/cli/index.d.ts +2 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/components/DynamicComponent.d.ts +12 -0
- package/dist/src/components/DynamicComponent.d.ts.map +1 -0
- package/dist/src/components/EncoreApp.d.ts +27 -0
- package/dist/src/components/EncoreApp.d.ts.map +1 -0
- package/dist/src/components/EncoreErrorBoundary.d.ts +17 -0
- package/dist/src/components/EncoreErrorBoundary.d.ts.map +1 -0
- package/dist/src/components/EncoreLoadingFallback.d.ts +4 -0
- package/dist/src/components/EncoreLoadingFallback.d.ts.map +1 -0
- package/dist/src/components.d.ts +4 -0
- package/dist/src/components.d.ts.map +1 -0
- package/dist/src/contexts/EncoreActionContext.d.ts +13 -0
- package/dist/src/contexts/EncoreActionContext.d.ts.map +1 -0
- package/dist/src/contexts/EncoreAppContext.d.ts +8 -0
- package/dist/src/contexts/EncoreAppContext.d.ts.map +1 -0
- package/dist/src/contexts/EncoreBindingContext.d.ts +5 -0
- package/dist/src/contexts/EncoreBindingContext.d.ts.map +1 -0
- package/dist/src/contexts/EncoreComponentIdContext.d.ts +8 -0
- package/dist/src/contexts/EncoreComponentIdContext.d.ts.map +1 -0
- package/dist/src/contexts/EncoreRepeatingContainerContext.d.ts +21 -0
- package/dist/src/contexts/EncoreRepeatingContainerContext.d.ts.map +1 -0
- package/dist/src/hooks/useAuthRedirect.d.ts +3 -0
- package/dist/src/hooks/useAuthRedirect.d.ts.map +1 -0
- package/dist/src/hooks/usePusherUpdates.d.ts +18 -0
- package/dist/src/hooks/usePusherUpdates.d.ts.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/lib/dynamicModules.d.ts +8 -0
- package/dist/src/lib/dynamicModules.d.ts.map +1 -0
- package/dist/src/lib/fetcher.d.ts +5 -0
- package/dist/src/lib/fetcher.d.ts.map +1 -0
- package/dist/src/lib/localMode.d.ts +3 -0
- package/dist/src/lib/localMode.d.ts.map +1 -0
- package/dist/src/lib/packages.d.ts +6 -0
- package/dist/src/lib/packages.d.ts.map +1 -0
- package/dist/src/stores/useEncoreState.d.ts +33 -0
- package/dist/src/stores/useEncoreState.d.ts.map +1 -0
- package/dist/stores/useEncoreState.js +70 -0
- package/dist/stores/useEncoreState.js.map +1 -0
- package/package.json +60 -0
- package/src/AGENTS.md +161 -0
- package/src/README.md +110 -0
- package/src/app.ts +5 -0
- package/src/cli/commands/download.ts +133 -0
- package/src/cli/commands/generate.ts +3045 -0
- package/src/cli/index.ts +35 -0
- package/src/components/DynamicComponent.tsx +40 -0
- package/src/components/EncoreApp.tsx +759 -0
- package/src/components/EncoreErrorBoundary.tsx +49 -0
- package/src/components/EncoreLoadingFallback.tsx +25 -0
- package/src/components.tsx +3155 -0
- package/src/contexts/EncoreActionContext.ts +18 -0
- package/src/contexts/EncoreAppContext.ts +13 -0
- package/src/contexts/EncoreBindingContext.ts +6 -0
- package/src/contexts/EncoreComponentIdContext.ts +12 -0
- package/src/contexts/EncoreRepeatingContainerContext.ts +30 -0
- package/src/hooks/useAuthRedirect.ts +63 -0
- package/src/hooks/usePusherUpdates.ts +156 -0
- package/src/index.ts +16 -0
- package/src/lib/dynamicModules.ts +193 -0
- package/src/lib/fetcher.ts +108 -0
- package/src/lib/localMode.ts +30 -0
- package/src/lib/moduleRegistry.ts +24 -0
- package/src/lib/packages.ts +33 -0
- package/src/stores/useEncoreState.ts +121 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
type Props = {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
fallback?: React.ReactNode;
|
|
5
|
+
};
|
|
6
|
+
type State = {
|
|
7
|
+
hasError: boolean;
|
|
8
|
+
error: unknown;
|
|
9
|
+
};
|
|
10
|
+
export default class EncoreErrorBoundary extends React.Component<Props, State> {
|
|
11
|
+
constructor(props: Props);
|
|
12
|
+
static getDerivedStateFromError(error: unknown): State;
|
|
13
|
+
componentDidCatch(error: unknown): void;
|
|
14
|
+
render(): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element | null | undefined;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=EncoreErrorBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreErrorBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/EncoreErrorBoundary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,KAAK,GAAG;IACT,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B,CAAC;AAEF,KAAK,KAAK,GAAG;IACT,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,mBAAoB,SAAQ,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC;gBAC9D,KAAK,EAAE,KAAK;IAKxB,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK;IAItD,iBAAiB,CAAC,KAAK,EAAE,OAAO;IAKhC,MAAM;CAqBT"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreLoadingFallback.d.ts","sourceRoot":"","sources":["../../../src/components/EncoreLoadingFallback.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAoBlC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/components.tsx"],"names":[],"mappings":"AACA,OAAO,KAMN,MAAM,OAAO,CAAC;AAqhGf,QAAA,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAoDxD,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type EncoreActionPayload = {
|
|
3
|
+
bravo: {
|
|
4
|
+
cancel: () => void;
|
|
5
|
+
action: any;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
type EncoreActionContextType = {
|
|
9
|
+
onAction?: (payload: EncoreActionPayload) => void | Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
declare const EncoreActionContext: React.Context<EncoreActionContextType>;
|
|
12
|
+
export default EncoreActionContext;
|
|
13
|
+
//# sourceMappingURL=EncoreActionContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreActionContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/EncoreActionContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE;QACL,MAAM,EAAE,MAAM,IAAI,CAAC;QACnB,MAAM,EAAE,GAAG,CAAC;KACb,CAAC;CACH,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CAAC;AAEF,QAAA,MAAM,mBAAmB,wCAAmD,CAAC;AAE7E,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreAppContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/EncoreAppContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,QAAA,MAAM,gBAAgB,iCAGpB,CAAC;AAEH,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreBindingContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/EncoreBindingContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,oBAAoB,GAAG,EAAE,CAAC;AAC/B,QAAA,MAAM,oBAAoB,mBAA0B,CAAC;AAErD,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
type EncoreComponentIdContext = {
|
|
3
|
+
componentId?: string;
|
|
4
|
+
statefulSetId?: string;
|
|
5
|
+
};
|
|
6
|
+
declare const EncoreComponentIdContext: React.Context<EncoreComponentIdContext>;
|
|
7
|
+
export default EncoreComponentIdContext;
|
|
8
|
+
//# sourceMappingURL=EncoreComponentIdContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreComponentIdContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/EncoreComponentIdContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,KAAK,wBAAwB,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,QAAA,MAAM,wBAAwB,yCAE7B,CAAC;AAEF,eAAe,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export type RepeatingContainerControl = {
|
|
3
|
+
currentIndex?: number;
|
|
4
|
+
onIndexChange?: (index: number, containerId: string) => void;
|
|
5
|
+
goToIndex: (index: number) => void;
|
|
6
|
+
getCurrentIndex: () => number;
|
|
7
|
+
};
|
|
8
|
+
type ControlProps = {
|
|
9
|
+
currentIndex?: number;
|
|
10
|
+
onIndexChange?: (index: number) => void;
|
|
11
|
+
};
|
|
12
|
+
type EncoreRepeatingContainerContextValue = {
|
|
13
|
+
registerContainer: (id: string, control: RepeatingContainerControl) => void;
|
|
14
|
+
unregisterContainer: (id: string) => void;
|
|
15
|
+
getControl: (id: string) => RepeatingContainerControl | undefined;
|
|
16
|
+
setControlProps: (id: string, props: ControlProps | ((prev: ControlProps) => ControlProps)) => void;
|
|
17
|
+
getControlProps: (id: string) => ControlProps | undefined;
|
|
18
|
+
};
|
|
19
|
+
declare const EncoreRepeatingContainerContext: React.Context<EncoreRepeatingContainerContextValue | null>;
|
|
20
|
+
export default EncoreRepeatingContainerContext;
|
|
21
|
+
//# sourceMappingURL=EncoreRepeatingContainerContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EncoreRepeatingContainerContext.d.ts","sourceRoot":"","sources":["../../../src/contexts/EncoreRepeatingContainerContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,eAAe,EAAE,MAAM,MAAM,CAAC;CAC/B,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF,KAAK,oCAAoC,GAAG;IAC1C,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAC5E,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,yBAAyB,GAAG,SAAS,CAAC;IAClE,eAAe,EAAE,CACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,GAAG,CAAC,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC,KACzD,IAAI,CAAC;IACV,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;CAC3D,CAAC;AAEF,QAAA,MAAM,+BAA+B,4DACmC,CAAC;AAEzE,eAAe,+BAA+B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAuthRedirect.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAuthRedirect.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,eAAe,YAuDpB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Pusher from "pusher-js";
|
|
2
|
+
type UsePusherUpdatesOptions = {
|
|
3
|
+
appId: string;
|
|
4
|
+
pageId?: string;
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
onUpdate?: () => void;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Hook to listen for EncoreApp component updates via Pusher
|
|
10
|
+
* Channel name format: `${appId}-${pageId}`
|
|
11
|
+
* When an update event is received, it invalidates SWR cache and triggers a reload
|
|
12
|
+
*/
|
|
13
|
+
export declare function usePusherUpdates({ appId, pageId, enabled, onUpdate, }: UsePusherUpdatesOptions): {
|
|
14
|
+
channel: import("pusher-js").Channel | null;
|
|
15
|
+
pusher: Pusher | null;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=usePusherUpdates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePusherUpdates.d.ts","sourceRoot":"","sources":["../../../src/hooks/usePusherUpdates.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,WAAW,CAAC;AAU/B,KAAK,uBAAuB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAWF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,OAAc,EACd,QAAQ,GACT,EAAE,uBAAuB;;;EAsHzB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import EncoreApp from "./components/EncoreApp";
|
|
2
|
+
import EncoreErrorBoundary from "./components/EncoreErrorBoundary";
|
|
3
|
+
import EncoreLoadingFallback from "./components/EncoreLoadingFallback";
|
|
4
|
+
import EncoreAppContext from "./contexts/EncoreAppContext";
|
|
5
|
+
import EncoreBindingContext from "./contexts/EncoreBindingContext";
|
|
6
|
+
import useEncoreState from "./stores/useEncoreState";
|
|
7
|
+
export { EncoreApp, EncoreErrorBoundary, EncoreLoadingFallback, EncoreAppContext, EncoreBindingContext, useEncoreState, };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,mBAAmB,MAAM,kCAAkC,CAAC;AACnE,OAAO,qBAAqB,MAAM,oCAAoC,CAAC;AACvE,OAAO,gBAAgB,MAAM,6BAA6B,CAAC;AAC3D,OAAO,oBAAoB,MAAM,iCAAiC,CAAC;AACnE,OAAO,cAAc,MAAM,yBAAyB,CAAC;AAErD,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,GACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function loadAMDModule(name: string, code: string): Promise<any>;
|
|
2
|
+
export declare function fetchDep(name: string): Promise<any>;
|
|
3
|
+
/**
|
|
4
|
+
* Clear a module from the cache to force reload on next fetch
|
|
5
|
+
* @param name Module name (e.g., `${appId}/draft/components/${pageId}`)
|
|
6
|
+
*/
|
|
7
|
+
export declare function clearModuleCache(name: string): void;
|
|
8
|
+
//# sourceMappingURL=dynamicModules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamicModules.d.ts","sourceRoot":"","sources":["../../../src/lib/dynamicModules.ts"],"names":[],"mappings":"AAwBA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAyGvD;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,gBAoE1C;AAOD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAKnD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../../src/lib/fetcher.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,iBAAiB,cAEtB,CAAC;AAIF,QAAA,MAAM,OAAO,GAAI,KAAK,MAAM,QA6F3B,CAAC;AAEF,eAAe,OAAO,CAAC;AACvB,OAAO,EAAE,iBAAiB,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localMode.d.ts","sourceRoot":"","sources":["../../../src/lib/localMode.ts"],"names":[],"mappings":"AAGA,wBAAgB,oBAAoB,CAChC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,GACjC,IAAI,CAEN;AAED,wBAAgB,WAAW,IAAI,OAAO,CAkBrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packages.d.ts","sourceRoot":"","sources":["../../../src/lib/packages.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,OAAO,GAAG;IAClB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAGF,QAAA,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAO3C,CAAC;AAQF,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
type EncoreState = {
|
|
2
|
+
app: any;
|
|
3
|
+
baseURL: string;
|
|
4
|
+
accessToken?: {
|
|
5
|
+
expireAt: number;
|
|
6
|
+
token: string;
|
|
7
|
+
refreshToken: string;
|
|
8
|
+
params: string;
|
|
9
|
+
};
|
|
10
|
+
appId?: string;
|
|
11
|
+
formInputs: Record<string, Record<string, any>>;
|
|
12
|
+
pageId?: string;
|
|
13
|
+
statefulSetVariants: Record<string, string>;
|
|
14
|
+
inputGroups: Record<string, string>;
|
|
15
|
+
assetsById: Record<string, any>;
|
|
16
|
+
fontsById: Record<string, string>;
|
|
17
|
+
fontsByIdFull: Record<string, {
|
|
18
|
+
family: string;
|
|
19
|
+
postScriptName?: string;
|
|
20
|
+
}>;
|
|
21
|
+
resetFormInputs: () => void;
|
|
22
|
+
setAccessToken: (accessToken: EncoreState["accessToken"]) => void;
|
|
23
|
+
setApp: (app: any) => void;
|
|
24
|
+
setAppId: (appId: string) => void;
|
|
25
|
+
setFormInputValue: (nodeId: string, value: any) => void;
|
|
26
|
+
setPageId: (pageId: string) => void;
|
|
27
|
+
setStatefulSetVariant: (statefulSetId: string, variant: string) => void;
|
|
28
|
+
setInputGroupValue: (groupName: string, elementName: string) => void;
|
|
29
|
+
setBaseURL: (baseURL: string) => void;
|
|
30
|
+
};
|
|
31
|
+
declare const useEncoreState: import("zustand").UseBoundStore<import("zustand").StoreApi<EncoreState>>;
|
|
32
|
+
export default useEncoreState;
|
|
33
|
+
//# sourceMappingURL=useEncoreState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEncoreState.d.ts","sourceRoot":"","sources":["../../../src/stores/useEncoreState.ts"],"names":[],"mappings":"AAGA,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE;QACZ,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE3E,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IAClE,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACxD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,qBAAqB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,QAAA,MAAM,cAAc,0EAsFjB,CAAC;AAEJ,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { create as u } from "zustand";
|
|
2
|
+
import { CONST_APPS_SERVICE_URL as r } from "../packages/encore-lib/constants.js";
|
|
3
|
+
const f = u((o) => ({
|
|
4
|
+
app: void 0,
|
|
5
|
+
baseURL: r,
|
|
6
|
+
accessToken: void 0,
|
|
7
|
+
appId: void 0,
|
|
8
|
+
formInputs: {},
|
|
9
|
+
pageId: void 0,
|
|
10
|
+
statefulSetVariants: {},
|
|
11
|
+
inputGroups: {},
|
|
12
|
+
assetsById: {},
|
|
13
|
+
fontsById: {},
|
|
14
|
+
fontsByIdFull: {},
|
|
15
|
+
resetFormInputs: () => o((s) => ({ ...s, formInputs: {} })),
|
|
16
|
+
setAccessToken: (s) => o((t) => ({ ...t, accessToken: s })),
|
|
17
|
+
setApp: (s) => o((t) => ({
|
|
18
|
+
...t,
|
|
19
|
+
app: s,
|
|
20
|
+
assetsById: s.app?.assets?.reduce?.(
|
|
21
|
+
(e, n) => ({
|
|
22
|
+
...e,
|
|
23
|
+
[n.id]: n
|
|
24
|
+
}),
|
|
25
|
+
{}
|
|
26
|
+
) ?? {},
|
|
27
|
+
fontsById: s.app?.fonts?.reduce?.(
|
|
28
|
+
(e, n) => ({
|
|
29
|
+
...e,
|
|
30
|
+
[n.id]: n.fontName?.family || "sans-serif"
|
|
31
|
+
}),
|
|
32
|
+
{}
|
|
33
|
+
) ?? {},
|
|
34
|
+
fontsByIdFull: s.app?.fonts?.reduce?.(
|
|
35
|
+
(e, n) => ({
|
|
36
|
+
...e,
|
|
37
|
+
[n.id]: {
|
|
38
|
+
family: n.fontName?.family || "sans-serif",
|
|
39
|
+
postScriptName: n.fontName?.postScriptName
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
{}
|
|
43
|
+
) ?? {}
|
|
44
|
+
})),
|
|
45
|
+
setAppId: (s) => o((t) => ({ ...t, appId: s })),
|
|
46
|
+
setFormInputValue: (s, t) => o((e) => {
|
|
47
|
+
const p = { ...e.formInputs[e.pageId] || {}, [s]: t }, a = { ...e.formInputs, [e.pageId]: p };
|
|
48
|
+
return { ...e, formInputs: a };
|
|
49
|
+
}),
|
|
50
|
+
setPageId: (s) => o((t) => ({ ...t, pageId: s })),
|
|
51
|
+
setStatefulSetVariant: (s, t) => o((e) => ({
|
|
52
|
+
...e,
|
|
53
|
+
statefulSetVariants: {
|
|
54
|
+
...e.statefulSetVariants,
|
|
55
|
+
[s]: t
|
|
56
|
+
}
|
|
57
|
+
})),
|
|
58
|
+
setInputGroupValue: (s, t) => o((e) => ({
|
|
59
|
+
...e,
|
|
60
|
+
inputGroups: {
|
|
61
|
+
...e.inputGroups,
|
|
62
|
+
[s]: t
|
|
63
|
+
}
|
|
64
|
+
})),
|
|
65
|
+
setBaseURL: (s) => o((t) => ({ ...t, baseURL: s }))
|
|
66
|
+
}));
|
|
67
|
+
export {
|
|
68
|
+
f as default
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=useEncoreState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEncoreState.js","sources":["../../src/stores/useEncoreState.ts"],"sourcesContent":["import { create } from \"zustand\";\nimport { CONST_APPS_SERVICE_URL } from \"../../constants\";\n\ntype EncoreState = {\n app: any;\n baseURL: string;\n accessToken?: {\n expireAt: number;\n token: string;\n refreshToken: string;\n params: string;\n };\n appId?: string;\n formInputs: Record<string, Record<string, any>>;\n pageId?: string;\n statefulSetVariants: Record<string, string>;\n inputGroups: Record<string, string>; // Maps group name to active element name\n assetsById: Record<string, any>;\n fontsById: Record<string, string>;\n fontsByIdFull: Record<string, { family: string; postScriptName?: string }>;\n\n resetFormInputs: () => void;\n setAccessToken: (accessToken: EncoreState[\"accessToken\"]) => void;\n setApp: (app: any) => void;\n setAppId: (appId: string) => void;\n setFormInputValue: (nodeId: string, value: any) => void;\n setPageId: (pageId: string) => void;\n setStatefulSetVariant: (statefulSetId: string, variant: string) => void;\n setInputGroupValue: (groupName: string, elementName: string) => void;\n setBaseURL: (baseURL: string) => void;\n};\n\nconst useEncoreState = create<EncoreState>((set) => ({\n app: undefined,\n baseURL:\n import.meta.env.VITE_APPS_SERVICE_URL || CONST_APPS_SERVICE_URL || \n \"https://apps-service-dev.bravostudio.app\",\n accessToken: undefined,\n appId: undefined,\n formInputs: {},\n pageId: undefined,\n statefulSetVariants: {},\n inputGroups: {},\n assetsById: {},\n fontsById: {},\n fontsByIdFull: {},\n\n resetFormInputs: () => set((state) => ({ ...state, formInputs: {} })),\n\n setAccessToken: (accessToken) => set((state) => ({ ...state, accessToken })),\n\n setApp: (app: any) =>\n set((state) => ({\n ...state,\n app,\n assetsById:\n app.app?.assets?.reduce?.(\n (acc: Record<string, any>, asset: any) => ({\n ...acc,\n [asset.id]: asset,\n }),\n {}\n ) ?? {},\n fontsById:\n app.app?.fonts?.reduce?.(\n (acc: Record<string, string>, font: any) => ({\n ...acc,\n [font.id]: font.fontName?.family || \"sans-serif\",\n }),\n {}\n ) ?? {},\n fontsByIdFull:\n app.app?.fonts?.reduce?.(\n (\n acc: Record<string, { family: string; postScriptName?: string }>,\n font: any\n ) => ({\n ...acc,\n [font.id]: {\n family: font.fontName?.family || \"sans-serif\",\n postScriptName: font.fontName?.postScriptName,\n },\n }),\n {}\n ) ?? {},\n })),\n\n setAppId: (appId) => set((state) => ({ ...state, appId })),\n\n setFormInputValue: (nodeId, value) =>\n set((state) => {\n const oldPageInputs = state.formInputs[state.pageId!] || {};\n const newPageInputs = { ...oldPageInputs, [nodeId]: value };\n const newInputs = { ...state.formInputs, [state.pageId!]: newPageInputs };\n return { ...state, formInputs: newInputs };\n }),\n\n setPageId: (pageId) => set((state) => ({ ...state, pageId })),\n\n setStatefulSetVariant: (statefulSetId, variant) =>\n set((state) => ({\n ...state,\n statefulSetVariants: {\n ...state.statefulSetVariants,\n [statefulSetId]: variant,\n },\n })),\n\n setInputGroupValue: (groupName, elementName) =>\n set((state) => ({\n ...state,\n inputGroups: {\n ...state.inputGroups,\n [groupName]: elementName,\n },\n })),\n\n setBaseURL: (baseURL) => set((state) => ({ ...state, baseURL })),\n}));\n\nexport default useEncoreState;\n"],"names":["useEncoreState","create","set","CONST_APPS_SERVICE_URL","state","accessToken","app","acc","asset","font","appId","nodeId","value","newPageInputs","newInputs","pageId","statefulSetId","variant","groupName","elementName","baseURL"],"mappings":";;AAgCA,MAAMA,IAAiBC,EAAoB,CAACC,OAAS;AAAA,EACnD,KAAK;AAAA,EACL,SAC2CC;AAAA,EAE3C,aAAa;AAAA,EACb,OAAO;AAAA,EACP,YAAY,CAAA;AAAA,EACZ,QAAQ;AAAA,EACR,qBAAqB,CAAA;AAAA,EACrB,aAAa,CAAA;AAAA,EACb,YAAY,CAAA;AAAA,EACZ,WAAW,CAAA;AAAA,EACX,eAAe,CAAA;AAAA,EAEf,iBAAiB,MAAMD,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,YAAY,CAAA,EAAC,EAAI;AAAA,EAEpE,gBAAgB,CAACC,MAAgBH,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,aAAAC,EAAA,EAAc;AAAA,EAE3E,QAAQ,CAACC,MACPJ,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,KAAAE;AAAA,IACA,YACEA,EAAI,KAAK,QAAQ;AAAA,MACf,CAACC,GAA0BC,OAAgB;AAAA,QACzC,GAAGD;AAAA,QACH,CAACC,EAAM,EAAE,GAAGA;AAAA,MAAA;AAAA,MAEd,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,WACEF,EAAI,KAAK,OAAO;AAAA,MACd,CAACC,GAA6BE,OAAe;AAAA,QAC3C,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GAAGA,EAAK,UAAU,UAAU;AAAA,MAAA;AAAA,MAEtC,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,IACP,eACEH,EAAI,KAAK,OAAO;AAAA,MACd,CACEC,GACAE,OACI;AAAA,QACJ,GAAGF;AAAA,QACH,CAACE,EAAK,EAAE,GAAG;AAAA,UACT,QAAQA,EAAK,UAAU,UAAU;AAAA,UACjC,gBAAgBA,EAAK,UAAU;AAAA,QAAA;AAAA,MACjC;AAAA,MAEF,CAAA;AAAA,IAAC,KACE,CAAA;AAAA,EAAC,EACR;AAAA,EAEJ,UAAU,CAACC,MAAUR,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,OAAAM,EAAA,EAAQ;AAAA,EAEzD,mBAAmB,CAACC,GAAQC,MAC1BV,EAAI,CAACE,MAAU;AAEb,UAAMS,IAAgB,EAAE,GADFT,EAAM,WAAWA,EAAM,MAAO,KAAK,CAAA,GACf,CAACO,CAAM,GAAGC,EAAA,GAC9CE,IAAY,EAAE,GAAGV,EAAM,YAAY,CAACA,EAAM,MAAO,GAAGS,EAAA;AAC1D,WAAO,EAAE,GAAGT,GAAO,YAAYU,EAAA;AAAA,EACjC,CAAC;AAAA,EAEH,WAAW,CAACC,MAAWb,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,QAAAW,EAAA,EAAS;AAAA,EAE5D,uBAAuB,CAACC,GAAeC,MACrCf,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,qBAAqB;AAAA,MACnB,GAAGA,EAAM;AAAA,MACT,CAACY,CAAa,GAAGC;AAAA,IAAA;AAAA,EACnB,EACA;AAAA,EAEJ,oBAAoB,CAACC,GAAWC,MAC9BjB,EAAI,CAACE,OAAW;AAAA,IACd,GAAGA;AAAA,IACH,aAAa;AAAA,MACX,GAAGA,EAAM;AAAA,MACT,CAACc,CAAS,GAAGC;AAAA,IAAA;AAAA,EACf,EACA;AAAA,EAEJ,YAAY,CAACC,MAAYlB,EAAI,CAACE,OAAW,EAAE,GAAGA,GAAO,SAAAgB,IAAU;AACjE,EAAE;"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bravostudioai/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/src/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./components": {
|
|
13
|
+
"types": "./dist/src/components.d.ts",
|
|
14
|
+
"import": "./dist/components.js"
|
|
15
|
+
},
|
|
16
|
+
"./contexts/*": "./dist/contexts/*",
|
|
17
|
+
"./hooks/*": "./dist/hooks/*",
|
|
18
|
+
"./stores/*": "./dist/stores/*",
|
|
19
|
+
"./lib/*": "./dist/lib/*"
|
|
20
|
+
},
|
|
21
|
+
"bin": "./bin/encore-lib.js",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"src",
|
|
25
|
+
"bin"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "vite build && tsc --emitDeclarationOnly",
|
|
29
|
+
"download-bravo": "tsx scripts/download-bravo.ts",
|
|
30
|
+
"reverse-bravo": "tsx scripts/reverse-bravo.ts",
|
|
31
|
+
"generate-wrapper": "tsx scripts/generate-wrapper.ts",
|
|
32
|
+
"lint": "eslint ."
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"axios": "^1.13.0",
|
|
36
|
+
"dotenv": "^16.0.0",
|
|
37
|
+
"pusher-js": "^8.4.0",
|
|
38
|
+
"swr": "^2.3.6",
|
|
39
|
+
"zustand": "^5.0.8"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@eslint/js": "^9.39.1",
|
|
43
|
+
"@types/node": "^24.6.0",
|
|
44
|
+
"@types/react": "^19.1.16",
|
|
45
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
46
|
+
"eslint": "^9.39.1",
|
|
47
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
48
|
+
"eslint-plugin-react-refresh": "^0.4.24",
|
|
49
|
+
"globals": "^16.5.0",
|
|
50
|
+
"react-element-to-jsx-string": "^17.0.1",
|
|
51
|
+
"tsx": "^4.19.2",
|
|
52
|
+
"typescript": "~5.9.3",
|
|
53
|
+
"typescript-eslint": "^8.46.4",
|
|
54
|
+
"vite": "^7.2.4"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"react": "^19.2.0",
|
|
58
|
+
"react-dom": "^19.2.0"
|
|
59
|
+
}
|
|
60
|
+
}
|
package/src/AGENTS.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Guidance for AI Agents working in `src/bravo/`
|
|
2
|
+
|
|
3
|
+
This document lists practical rules and gotchas observed while implementing the Bravo renderer. Follow these to avoid layout regressions and broken renders.
|
|
4
|
+
|
|
5
|
+
## Golden Rules
|
|
6
|
+
|
|
7
|
+
- Do NOT use Tailwind here. All styling must be inline (see `README.md`).
|
|
8
|
+
- Respect the library boundary: changes in `src/bravo/**` should not depend on app-only tooling.
|
|
9
|
+
- Prefer small, local changes and verify with the default app (`01KA23JMNBQ2V9NR7K0VXKT5TF`).
|
|
10
|
+
|
|
11
|
+
## Build Process (CRITICAL)
|
|
12
|
+
|
|
13
|
+
> **⚠️ Changes to `encore-lib` are NOT automatically reflected in consuming apps!**
|
|
14
|
+
|
|
15
|
+
- After making changes to any file in `packages/encore-lib/src/`, you **MUST** run:
|
|
16
|
+
```bash
|
|
17
|
+
cd packages/encore-lib
|
|
18
|
+
yarn build
|
|
19
|
+
```
|
|
20
|
+
- The library builds to `packages/encore-lib/dist/` which is what consuming apps (like `test-app-2`, `test-app-3`) import.
|
|
21
|
+
- Dev servers in consuming apps will pick up the rebuilt library after a browser refresh.
|
|
22
|
+
- **No restart** of the consuming app's dev server is required, just rebuild `encore-lib` and refresh the browser.
|
|
23
|
+
- If you're not seeing your changes reflected, the most likely cause is forgetting to rebuild `encore-lib`.
|
|
24
|
+
|
|
25
|
+
## Layout & Positioning
|
|
26
|
+
|
|
27
|
+
- Positioning context:
|
|
28
|
+
- Containers that host absolutely positioned children must set `position: 'relative'`.
|
|
29
|
+
- Background layers must be `position: 'absolute'` with `zIndex: -1` and should not participate in layout.
|
|
30
|
+
- Prevent zero‑size containers:
|
|
31
|
+
- Use `ResizeObserver` to measure and pass dimensions via `BravoContainerContext`.
|
|
32
|
+
- For container wrappers, default `width: '100%'`, `height: '100%'` if computed size is not yet known.
|
|
33
|
+
- Percent sizing:
|
|
34
|
+
- Convert percentages using the nearest container’s measured width/height, not `window.innerWidth/innerHeight`.
|
|
35
|
+
- Guard conversions when dimensions are `0` to avoid collapsing to `0px`.
|
|
36
|
+
|
|
37
|
+
## Typography & Units
|
|
38
|
+
|
|
39
|
+
- When mapping numeric style fields to CSS, add units where required:
|
|
40
|
+
- `lineHeightPx` → `lineHeight = (value * scaleFactor) + 'px'`
|
|
41
|
+
- `fontSize` uses numeric pixels (React handles units when used directly as numbers).
|
|
42
|
+
- Re-check any new numeric style property; if it corresponds to a CSS length, ensure a unit.
|
|
43
|
+
|
|
44
|
+
## Backgrounds & Layers
|
|
45
|
+
|
|
46
|
+
- Color layers:
|
|
47
|
+
- Never skip rendering color layers by name (e.g., “SOLID”). Honor background color if not fully transparent.
|
|
48
|
+
- Z-order:
|
|
49
|
+
- Action hit-areas or overlays should use explicit `zIndex` to avoid covering content unintentionally.
|
|
50
|
+
|
|
51
|
+
## Scaffolding & Scrolling
|
|
52
|
+
|
|
53
|
+
- Page structure:
|
|
54
|
+
- Keep a non-scrollable group (backgrounds, top bars) separate from the scrollable page area.
|
|
55
|
+
- The scrollable container should fill its parent: `width: '100%'`, `height: '100%'`, `overflow: 'auto'`.
|
|
56
|
+
- Scale factor:
|
|
57
|
+
- `scaleFactor` must be derived from the measured container rectangle (via `ResizeObserver`), not the window.
|
|
58
|
+
- Use a fit strategy: `min(containerWidth / originalWidth, containerHeight / originalHeight)`.
|
|
59
|
+
- This guarantees the render scales responsively to whatever rectangle it is placed in, with edge-to-edge layout.
|
|
60
|
+
|
|
61
|
+
## Spacing & Layout Mapping
|
|
62
|
+
|
|
63
|
+
- Scale layout paddings and gaps by `scaleFactor`:
|
|
64
|
+
- In `useBravoStyle`, map `style.layout.padding.{top,right,bottom,left}` and `style.layout.itemSpacing` to CSS by multiplying each by `scaleFactor`.
|
|
65
|
+
- This keeps card paddings and inter-card spacing visually consistent with Figma across container sizes.
|
|
66
|
+
- Border radii:
|
|
67
|
+
- For percent-based radii from Bravo, convert using the nearest container’s width (see `percentOfParentWidthToPx`).
|
|
68
|
+
- If `cornerRadii` is present, set per-corner radii and enable `overflow: 'hidden'` to clip content.
|
|
69
|
+
|
|
70
|
+
## Images & SVGs
|
|
71
|
+
|
|
72
|
+
- Images:
|
|
73
|
+
- Honor `scaleMode`: `fill → objectFit='cover'`, `fit → objectFit='contain'`, center with `objectPosition='center'`.
|
|
74
|
+
- Maintain aspect ratio within absolute insets when both left/right or top/bottom are set:
|
|
75
|
+
- Compute pixel width/height from container dimensions and node `aspectRatio`.
|
|
76
|
+
- Anchor from `top`/`left` and clear the opposite sides to avoid stretch.
|
|
77
|
+
- SVG “BG” layers:
|
|
78
|
+
- Treat like images only if a specific node requires aspect rules; do not apply global image-like behavior to all SVGs.
|
|
79
|
+
- Verify corner radii after percent → px conversion; adjust on a per-node basis if Figma expects masking behavior.
|
|
80
|
+
|
|
81
|
+
## Asset Loading
|
|
82
|
+
|
|
83
|
+
- Image preloading must not block rendering:
|
|
84
|
+
- Use `Promise.allSettled` and resolve on `onerror` in dev mode.
|
|
85
|
+
|
|
86
|
+
## Change Review Checklist
|
|
87
|
+
|
|
88
|
+
- Will any absolutely positioned child lack a positioned ancestor? If yes, add `position: 'relative'`.
|
|
89
|
+
- Could a wrapper render at `0×0` initially? If yes, default to `width/height: '100%'` until measured.
|
|
90
|
+
- Are you converting percent sizes using container dimensions (not window)?
|
|
91
|
+
- Are all numeric CSS lengths expressed with units?
|
|
92
|
+
- Are backgrounds visible (not fully transparent) and behind content?
|
|
93
|
+
- Do action wrappers have the correct `zIndex` and not block clicks unexpectedly?
|
|
94
|
+
|
|
95
|
+
## Debugging Tips
|
|
96
|
+
|
|
97
|
+
- Inspect `[data-type="ColorComponent"]` for `background-color`, size, and absolute insets.
|
|
98
|
+
- Inspect containers’ computed `width/height` and bounding rect; if `0×0`, confirm `ResizeObserver` and defaults.
|
|
99
|
+
- For missing text, verify computed `line-height`, `font-size`, and clipping (`overflow`).
|
|
100
|
+
|
|
101
|
+
## Local Flex-Layout Mode (for offline testing)
|
|
102
|
+
|
|
103
|
+
- Toggle via query `?useLocal=1` or env `VITE_BRAVO_LOCAL=1`.
|
|
104
|
+
- App JSON source: `/flex-layout/<appId>/<appId>.json`.
|
|
105
|
+
- Component modules: `/flex-layout/<appId>/<pageId>.jsx` (fallback to `.js`).
|
|
106
|
+
- `BravoApp` page list uses `app.data.pages[].id` when local mode is on.
|
|
107
|
+
- Keep all styling inline; no Tailwind in `src/bravo/**`.
|
|
108
|
+
|
|
109
|
+
## Interactive Components & Click Handling
|
|
110
|
+
|
|
111
|
+
### Clickable Overlay Positioning (CRITICAL)
|
|
112
|
+
|
|
113
|
+
**Problem:** When `EncoreLinkActionWrapper` creates an absolutely positioned overlay div for click handling, the overlay must be scoped to the correct parent element to avoid overlapping with other interactive elements.
|
|
114
|
+
|
|
115
|
+
**Root Cause:** If the overlay is positioned relative to a parent container (like `StatefulSetComponent`) that contains multiple buttons, all buttons' overlays will overlap at the same position, causing clicks on one button to trigger handlers on other buttons.
|
|
116
|
+
|
|
117
|
+
**Solution:**
|
|
118
|
+
- The clickable overlay div from `EncoreLinkActionWrapper` must be positioned relative to the **button element itself**, not the parent container.
|
|
119
|
+
- In `StatefulCompoundComponent`, wrap the button's content with `EncoreLinkActionWrapper`, then place the button's container div **outside** the wrapper:
|
|
120
|
+
```tsx
|
|
121
|
+
// ✅ CORRECT: Overlay is scoped to button element
|
|
122
|
+
<div style={containerStyle}>
|
|
123
|
+
<EncoreLinkActionWrapper>
|
|
124
|
+
{children}
|
|
125
|
+
</EncoreLinkActionWrapper>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
// ❌ WRONG: Overlay is scoped to parent container
|
|
129
|
+
<EncoreLinkActionWrapper>
|
|
130
|
+
<div style={containerStyle}>
|
|
131
|
+
{children}
|
|
132
|
+
</div>
|
|
133
|
+
</EncoreLinkActionWrapper>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Testing:**
|
|
137
|
+
- When debugging click handling issues, check if clickable overlays overlap by:
|
|
138
|
+
1. Inspecting the bounding boxes of overlay divs (look for `zIndex >= 9999` and `position: absolute`)
|
|
139
|
+
2. Verifying that overlays from different buttons have different positions
|
|
140
|
+
3. Using `document.elementsFromPoint()` to see which elements are at a click point
|
|
141
|
+
|
|
142
|
+
**Key Principle:** Interactive overlays should be scoped to the smallest containing element that represents the clickable area, not a parent that contains multiple interactive elements.
|
|
143
|
+
|
|
144
|
+
### StatefulSetComponent Variant Selection
|
|
145
|
+
|
|
146
|
+
- `StatefulSetComponent` uses its own `id` as the `stateSetId` for variant lookup in the Zustand store.
|
|
147
|
+
- Always use the component's `id` directly in the selector function to avoid closure issues:
|
|
148
|
+
```tsx
|
|
149
|
+
// ✅ CORRECT: Use id directly
|
|
150
|
+
const variant = useEncoreState((state) => state.statefulSetVariants[id]);
|
|
151
|
+
|
|
152
|
+
// ❌ WRONG: Using a variable can cause closure issues
|
|
153
|
+
const stateSetId = id;
|
|
154
|
+
const variant = useEncoreState((state) => state.statefulSetVariants[stateSetId]);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Parent StatefulSetId Propagation
|
|
158
|
+
|
|
159
|
+
- When `StatefulSetComponent` renders a child button (`StatefulCompoundComponent`), it must pass its own `id` as `_parentStatefulSetId` prop.
|
|
160
|
+
- This ensures the button's click handler targets the correct parent's state, not the button's own state.
|
|
161
|
+
- The `EncoreLinkActionWrapper` prioritizes `_parentStatefulSetId` prop over context values for reliability.
|