@superblocksteam/library 2.0.76 → 2.0.77-next.1

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/dist/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as consoleLogAttributes, t as early_console_buffer_default } from "../early-console-buffer-D4wVuyBf.js";
2
- import { A as useSuperblocksProfiles, B as PropsCategory, C as addNewPromise, D as getAppMode, E as SuperblocksContextProvider, F as iframeMessageHandler, H as createPropertiesPanelDefinition, I as isEmbeddedBySuperblocksFirstParty, L as isEditMode, M as sendNotification, N as colors$1, O as useSuperblocksContext, P as editorBridge, R as createManagedPropsList, S as api_hmr_tracker_default, T as resolveById, U as getEditStore, V as Section, _ as root_store_default, a as FixWithClarkButton, b as createIframeSpan, c as ErrorContent, d as ErrorMessage, f as ErrorStack, g as StyledClarkIcon, h as SecondaryButton, i as getWidgetRectAnchorName, j as useSuperblocksUser, k as useSuperblocksGroups, l as ErrorDetails, m as ErrorTitle, n as useJSXContext, o as ActionsContainer, p as ErrorSummary, r as getWidgetAnchorName, s as ErrorContainer, u as ErrorIconContainer, v as startEditorSync, w as rejectById, x as getContextFromTraceHeaders, y as generateId, z as Prop } from "../jsx-wrapper-DpoYDtf8.js";
2
+ import { A as useSuperblocksProfiles, B as PropsCategory, C as addNewPromise, D as getAppMode, E as SuperblocksContextProvider, F as iframeMessageHandler, H as createPropertiesPanelDefinition, I as isEmbeddedBySuperblocksFirstParty, L as isEditMode, M as sendNotification, N as colors$1, O as useSuperblocksContext, P as editorBridge, R as createManagedPropsList, S as api_hmr_tracker_default, T as resolveById, U as getEditStore, V as Section, _ as root_store_default, a as FixWithClarkButton, b as createIframeSpan, c as ErrorContent, d as ErrorMessage, f as ErrorStack, g as StyledClarkIcon, h as SecondaryButton, i as getWidgetRectAnchorName, j as useSuperblocksUser, k as useSuperblocksGroups, l as ErrorDetails, m as ErrorTitle, n as useJSXContext, o as ActionsContainer, p as ErrorSummary, r as getWidgetAnchorName, s as ErrorContainer, u as ErrorIconContainer, v as startEditorSync, w as rejectById, x as getContextFromTraceHeaders, y as generateId, z as Prop } from "../jsx-wrapper-B2IuiyUY.js";
3
3
  import { n as initTracerProviderWithOrigin } from "../utils-Clb3lSiX.js";
4
4
  import { action, autorun, computed, makeAutoObservable, makeObservable, observable, reaction, when } from "mobx";
5
5
  import { Dim, NATIVE_COMPONENT_TYPES, NO_SELECT_ATTRIBUTE, Property, Property as Property$1, SELECTOR_ID_ATTRIBUTE, SOURCE_ID_ATTRIBUTE, generateSourceId, getBindingIdentifier } from "@superblocksteam/library-shared";
@@ -862,11 +862,13 @@ function useApiStateful(name) {
862
862
  run: useCallback(async (inputs) => {
863
863
  const apiPath = getApiPath(name);
864
864
  const editMode = isEditMode();
865
- return (await root_store_default.apis.runApiByPath({
865
+ const result = await root_store_default.apis.runApiByPath({
866
866
  path: apiPath,
867
867
  inputs: inputs ?? {},
868
868
  ...editMode ? { injectedCallerId: sourceId } : {}
869
- })).data;
869
+ });
870
+ if (result?.error != null) console.error(`[useApi] [${name}]`, result.error);
871
+ return result.data;
870
872
  }, [name, sourceId]),
871
873
  cancel: useCallback(async () => {
872
874
  await root_store_default.apis.cancelApi(name);
@@ -874,6 +876,130 @@ function useApiStateful(name) {
874
876
  };
875
877
  }
876
878
 
879
+ //#endregion
880
+ //#region src/lib/internal-details/embed-store.ts
881
+ /**
882
+ * Store for managing embed properties and events.
883
+ * Used when the library is embedded in an external application (third-party embedding).
884
+ *
885
+ * Properties can be set by the parent window via postMessage, and events can be
886
+ * emitted back to the parent window.
887
+ */
888
+ var EmbedStore = class {
889
+ properties = {};
890
+ constructor() {
891
+ makeAutoObservable(this);
892
+ }
893
+ /**
894
+ * Update the embed properties. Called when the parent window sends updated properties.
895
+ */
896
+ setProperties(properties) {
897
+ this.properties = properties;
898
+ }
899
+ /**
900
+ * Emit an event to the parent window.
901
+ * The parent can listen for these events using window.addEventListener("message", ...).
902
+ */
903
+ emitEvent(eventName, payload = {}) {
904
+ if (typeof window === "undefined" || window.parent === window) return;
905
+ window.parent.postMessage({
906
+ type: "embed-emit-event",
907
+ payload: {
908
+ eventName,
909
+ payload
910
+ }
911
+ }, "*");
912
+ }
913
+ };
914
+ const embedStore = new EmbedStore();
915
+
916
+ //#endregion
917
+ //#region src/lib/internal-details/use-embed-message-listeners.ts
918
+ /**
919
+ * Hook that sets up common message listeners for embedded apps.
920
+ * Used by both edit-mode and deployed-mode EmbedWrapper components.
921
+ */
922
+ function useEmbedMessageListeners(navigate, superblocksContext) {
923
+ useEffect(() => {
924
+ const globalSyncListener = (event) => {
925
+ const { global } = event.data.payload;
926
+ superblocksContext.updateContext(global);
927
+ };
928
+ iframeMessageHandler.addEventListener("sb-global-sync", globalSyncListener);
929
+ const navigateToListener = async (event) => {
930
+ const { route, routeParams, queryParams } = event.data.payload;
931
+ const eventSearch = new URLSearchParams(queryParams);
932
+ const nextSearch = new URLSearchParams(window.location.search);
933
+ for (const [key, value] of eventSearch.entries()) nextSearch.set(key, value);
934
+ await navigate({
935
+ pathname: generatePath(route, routeParams),
936
+ search: nextSearch.toString()
937
+ });
938
+ };
939
+ iframeMessageHandler.addEventListener("route-change", navigateToListener);
940
+ const embedPropertyChangeListener = (event) => {
941
+ const { properties } = event.data.payload;
942
+ embedStore.setProperties(properties);
943
+ };
944
+ iframeMessageHandler.addEventListener("embed-property-change", embedPropertyChangeListener);
945
+ const embedTriggerEventListener = (event) => {
946
+ const { eventName, payload } = event.data.payload;
947
+ window.dispatchEvent(new CustomEvent(`superblocks:${eventName}`, { detail: payload }));
948
+ };
949
+ iframeMessageHandler.addEventListener("embed-trigger-event", embedTriggerEventListener);
950
+ return () => {
951
+ iframeMessageHandler.removeEventListener("sb-global-sync", globalSyncListener);
952
+ iframeMessageHandler.removeEventListener("route-change", navigateToListener);
953
+ iframeMessageHandler.removeEventListener("embed-property-change", embedPropertyChangeListener);
954
+ iframeMessageHandler.removeEventListener("embed-trigger-event", embedTriggerEventListener);
955
+ };
956
+ }, [navigate, superblocksContext]);
957
+ }
958
+
959
+ //#endregion
960
+ //#region src/lib/internal-details/utils/link-modifiers-interceptor.ts
961
+ /**
962
+ * Intercepts cmd/ctrl/shift+click and middle-click on local links inside an iframe
963
+ * to open them in a new tab using the parent URL.
964
+ *
965
+ * When `isEmbedMode` is true, modified clicks are converted into normal in-iframe
966
+ * navigation (no new tab).
967
+ */
968
+ function linkModifierInterceptor({ isEmbedMode = false, isEditMode: isEditMode$1 = false } = {}) {
969
+ if (typeof window === "undefined") return () => {};
970
+ if (window === window.parent) return () => {};
971
+ const handleClick = (ev) => {
972
+ const isMiddleClick = ev.button === 1;
973
+ const isModifierClick = ev.button === 0 && (ev.metaKey || ev.ctrlKey || ev.shiftKey);
974
+ if (isEditMode$1) {
975
+ if (!(ev.button === 0 && ev.shiftKey)) return;
976
+ } else if (!isMiddleClick && !isModifierClick) return;
977
+ if (ev.defaultPrevented) return;
978
+ const target = ev.target;
979
+ if (!(target instanceof Element)) return;
980
+ const anchor = target.closest?.("a[href]");
981
+ if (!(anchor instanceof HTMLAnchorElement)) return;
982
+ const href = anchor.getAttribute("href");
983
+ if (!href) return;
984
+ if (href.startsWith("#")) return;
985
+ if (href.startsWith("http://") || href.startsWith("https://") || href.startsWith("//")) return;
986
+ const appId = root_store_default.applicationId;
987
+ if (!appId) return;
988
+ ev.preventDefault();
989
+ ev.stopPropagation();
990
+ const resolvedUrl = new URL(href, window.location.href);
991
+ const targetPath = resolvedUrl.pathname + resolvedUrl.search + resolvedUrl.hash;
992
+ if (isEmbedMode) {
993
+ anchor.click();
994
+ return;
995
+ }
996
+ const parentUrl = `/code-mode/applications/${isEditMode$1 ? "edit/" : ""}${appId}${targetPath}`;
997
+ editorBridge.navigateTo(parentUrl, true);
998
+ };
999
+ window.addEventListener("click", handleClick, true);
1000
+ return () => window.removeEventListener("click", handleClick, true);
1001
+ }
1002
+
877
1003
  //#endregion
878
1004
  //#region src/edit-mode/build-error-notification.tsx
879
1005
  const ModalOverlay = styled(Dialog.Overlay)`
@@ -2690,6 +2816,24 @@ const useObserverMemo = (fn, deps) => {
2690
2816
  return computed(fn);
2691
2817
  }, deps).get();
2692
2818
  };
2819
+ /**
2820
+ * Like useObserverMemo, but does not require the component to be wrapped in an observer.
2821
+ * It is recommended to use useObserverMemo instead.
2822
+ * @see useObserverMemo
2823
+ *
2824
+ * Note: This implementation uses MobX reactions to track both observable changes and
2825
+ * dependency changes.
2826
+ */
2827
+ const useStandaloneObserverMemo = (fn, deps) => {
2828
+ const fnRef = useRef(fn);
2829
+ fnRef.current = fn;
2830
+ const [result, setResult] = useState(fnRef.current);
2831
+ useEffect(() => reaction(() => fnRef.current(), setResult, {
2832
+ fireImmediately: true,
2833
+ name: "useStandaloneObserverMemo"
2834
+ }), deps);
2835
+ return result;
2836
+ };
2693
2837
 
2694
2838
  //#endregion
2695
2839
  //#region src/lib/user-facing/layers.ts
@@ -3157,6 +3301,42 @@ function EditorHotkeys({ children }) {
3157
3301
  ],
3158
3302
  enableOnContentEditable: true
3159
3303
  });
3304
+ useEditorHotkeys("command+1, command+2, command+3, command+4, command+5, command+6, command+7, command+8, command+9", (e) => {
3305
+ e.preventDefault();
3306
+ e.stopPropagation();
3307
+ editorBridge.forwardKeypress(`command+${e.key}`, {
3308
+ code: e.code,
3309
+ key: e.key,
3310
+ altKey: e.altKey,
3311
+ ctrlKey: e.ctrlKey,
3312
+ shiftKey: e.shiftKey
3313
+ });
3314
+ }, {
3315
+ enableOnTags: [
3316
+ "TEXTAREA",
3317
+ "INPUT",
3318
+ "SELECT"
3319
+ ],
3320
+ enableOnContentEditable: true
3321
+ });
3322
+ useEditorHotkeys("command+enter, ctrl+enter", (e) => {
3323
+ e.preventDefault();
3324
+ e.stopPropagation();
3325
+ editorBridge.forwardKeypress("command+enter", {
3326
+ code: e.code,
3327
+ key: e.key,
3328
+ altKey: e.altKey,
3329
+ ctrlKey: e.ctrlKey,
3330
+ shiftKey: e.shiftKey
3331
+ });
3332
+ }, {
3333
+ enableOnTags: [
3334
+ "TEXTAREA",
3335
+ "INPUT",
3336
+ "SELECT"
3337
+ ],
3338
+ enableOnContentEditable: true
3339
+ });
3160
3340
  return /* @__PURE__ */ jsx(Fragment, { children });
3161
3341
  }
3162
3342
 
@@ -3285,6 +3465,9 @@ const IframeConnected = observer(function IframeConnected$1(props) {
3285
3465
  console.debug("[internal] [iframe-wrappers] sending ready");
3286
3466
  editorBridge.sendReady();
3287
3467
  }, []);
3468
+ useEffect(() => {
3469
+ return linkModifierInterceptor({ isEditMode: true });
3470
+ }, []);
3288
3471
  useEffect(() => {
3289
3472
  const handleDragStart = () => {};
3290
3473
  iframeMessageHandler.addEventListener("dragstart", handleDragStart);
@@ -3598,28 +3781,7 @@ const EmbedWrapper = (props) => {
3598
3781
  } catch {}
3599
3782
  };
3600
3783
  }, []);
3601
- useEffect(() => {
3602
- const globalSyncListener = (event) => {
3603
- const { global } = event.data.payload;
3604
- superblocksContext.updateContext(global);
3605
- };
3606
- iframeMessageHandler.addEventListener("sb-global-sync", globalSyncListener);
3607
- const navigateToListener = async (event) => {
3608
- const { route, routeParams, queryParams } = event.data.payload;
3609
- const eventSearch = new URLSearchParams(queryParams);
3610
- const nextSearch = new URLSearchParams(window.location.search);
3611
- for (const [key, value] of eventSearch.entries()) nextSearch.set(key, value);
3612
- await navigate({
3613
- pathname: generatePath(route, routeParams),
3614
- search: nextSearch.toString()
3615
- });
3616
- };
3617
- iframeMessageHandler.addEventListener("route-change", navigateToListener);
3618
- return () => {
3619
- iframeMessageHandler.removeEventListener("sb-global-sync", globalSyncListener);
3620
- iframeMessageHandler.removeEventListener("route-change", navigateToListener);
3621
- };
3622
- }, [navigate, superblocksContext]);
3784
+ useEmbedMessageListeners(navigate, superblocksContext);
3623
3785
  useEffect(() => {
3624
3786
  const messageListener = (event) => {
3625
3787
  if (event.data?.type === "parent-action-batch" && event.data.payload) event.data.payload.forEach((action$1) => {
@@ -4228,28 +4390,11 @@ const EmbedWrapper$1 = (props) => {
4228
4390
  }
4229
4391
  };
4230
4392
  iframeMessageHandler.addEventListener("sb-bootstrap-response", bootstrapResponseListener);
4231
- const globalSyncListener = (event) => {
4232
- const { global } = event.data.payload;
4233
- superblocksContext.updateContext(global);
4234
- };
4235
- iframeMessageHandler.addEventListener("sb-global-sync", globalSyncListener);
4236
- const navigateToListener = async (event) => {
4237
- const { route, routeParams, queryParams } = event.data.payload;
4238
- const eventSearch = new URLSearchParams(queryParams);
4239
- const nextSearch = new URLSearchParams(window.location.search);
4240
- for (const [key, value] of eventSearch.entries()) nextSearch.set(key, value);
4241
- await navigate({
4242
- pathname: generatePath(route, routeParams),
4243
- search: nextSearch.toString()
4244
- });
4245
- };
4246
- iframeMessageHandler.addEventListener("route-change", navigateToListener);
4247
4393
  return () => {
4248
4394
  iframeMessageHandler.removeEventListener("sb-bootstrap-response", bootstrapResponseListener);
4249
- iframeMessageHandler.removeEventListener("sb-global-sync", globalSyncListener);
4250
- iframeMessageHandler.removeEventListener("route-change", navigateToListener);
4251
4395
  };
4252
- }, [navigate, superblocksContext]);
4396
+ }, []);
4397
+ useEmbedMessageListeners(navigate, superblocksContext);
4253
4398
  useEffect(() => {
4254
4399
  const messageListener = (event) => {
4255
4400
  if (event.data?.type === "parent-action-batch" && event.data.payload) event.data.payload.forEach((action$1) => {
@@ -4263,6 +4408,9 @@ const EmbedWrapper$1 = (props) => {
4263
4408
  window.addEventListener("message", messageListener);
4264
4409
  return () => window.removeEventListener("message", messageListener);
4265
4410
  }, []);
4411
+ useEffect(() => {
4412
+ return linkModifierInterceptor({ isEmbedMode: new URLSearchParams(window.location.search).get("embed_mode") === "true" });
4413
+ }, []);
4266
4414
  if (!isLoaded && error) return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: "There was an error logging in to Superblocks." }), /* @__PURE__ */ jsx("p", { children: error })] });
4267
4415
  if (!root_store_default.apis.isInitialized() && !isLoaded) {
4268
4416
  if (!isRetrievingToken.current && window.parent !== window.self) {
@@ -4355,36 +4503,65 @@ function useTrackRouteChange() {
4355
4503
 
4356
4504
  //#endregion
4357
4505
  //#region src/lib/user-facing/sb-provider-tracker.ts
4358
- let sbProviderRendered = false;
4506
+ const hasSbProviderRenderedEditMode = () => globalThis.__SB_PROVIDER_RENDERED_EDIT_MODE__ === true;
4359
4507
  const reportSbProviderRenderedEditMode = () => {
4360
- sbProviderRendered = true;
4508
+ globalThis.__SB_PROVIDER_RENDERED_EDIT_MODE__ = true;
4361
4509
  };
4362
4510
  const ERROR_ID = "base-app-not-rendered";
4363
- if (isEditMode()) setTimeout(() => {
4364
- if (!root_store_default.editStore) console.error("Edit store not initialized.");
4365
- if (sbProviderRendered) {
4366
- editorBridge.sendClearRuntimeError(ERROR_ID, true);
4367
- return;
4368
- }
4369
- const errorMessage = `AppProvider not rendered in time.
4511
+ if (isEditMode()) {
4512
+ const hasSbProviderRootInDom = () => typeof document !== "undefined" && !!document.getElementById("sb-provider-root");
4513
+ const hasRendered = () => hasSbProviderRenderedEditMode() || hasSbProviderRootInDom();
4514
+ const startTracking = () => {
4515
+ setTimeout(() => {
4516
+ if (!root_store_default.editStore) console.error("Edit store not initialized.");
4517
+ if (hasRendered()) {
4518
+ editorBridge.sendClearRuntimeError(ERROR_ID, true);
4519
+ return;
4520
+ }
4521
+ const errorMessage = `AppProvider not rendered in time.
4370
4522
  Please ensure that 'App' from @superblocksteam/library is always rendered.
4371
4523
  API executions and editor features will be unavailable.
4372
4524
  `;
4373
- console.error(errorMessage);
4374
- editorBridge.sendRuntimeError({
4375
- id: ERROR_ID,
4376
- error: errorMessage,
4377
- errorInfo: {}
4378
- }, true);
4379
- editorBridge.sendLoadError(errorMessage);
4380
- const intervalId = setInterval(() => {
4381
- if (sbProviderRendered) {
4382
- clearInterval(intervalId);
4383
- editorBridge.sendClearRuntimeError(ERROR_ID, true);
4384
- return;
4525
+ console.error(errorMessage);
4526
+ editorBridge.sendRuntimeError({
4527
+ id: ERROR_ID,
4528
+ error: errorMessage,
4529
+ errorInfo: {}
4530
+ }, true);
4531
+ editorBridge.sendLoadError(errorMessage);
4532
+ const intervalId = setInterval(() => {
4533
+ if (hasRendered()) {
4534
+ clearInterval(intervalId);
4535
+ editorBridge.sendClearRuntimeError(ERROR_ID, true);
4536
+ return;
4537
+ }
4538
+ }, 500);
4539
+ }, 2e4);
4540
+ };
4541
+ if (hasRendered()) editorBridge.sendClearRuntimeError(ERROR_ID, true);
4542
+ else {
4543
+ let started = false;
4544
+ let observer$1 = null;
4545
+ const startOnce = () => {
4546
+ if (started) return;
4547
+ started = true;
4548
+ observer$1?.disconnect();
4549
+ observer$1 = null;
4550
+ startTracking();
4551
+ };
4552
+ const rootEl = typeof document !== "undefined" ? document.getElementById("root") : null;
4553
+ if (rootEl) if (rootEl.childNodes.length > 0) startOnce();
4554
+ else {
4555
+ observer$1 = new MutationObserver(() => {
4556
+ if (hasRendered() || rootEl.childNodes.length > 0) startOnce();
4557
+ });
4558
+ observer$1.observe(rootEl, {
4559
+ childList: true,
4560
+ subtree: true
4561
+ });
4385
4562
  }
4386
- }, 1e3);
4387
- }, 1e4);
4563
+ }
4564
+ }
4388
4565
 
4389
4566
  //#endregion
4390
4567
  //#region src/lib/user-facing/styling/styles.ts
@@ -5521,11 +5698,171 @@ async function logoutIntegrations() {
5521
5698
  if (logoutResult?.errors && logoutResult.errors.length > 0) console.error("Logout returned with errors", logoutResult.errors);
5522
5699
  }
5523
5700
 
5701
+ //#endregion
5702
+ //#region src/lib/user-facing/embed.ts
5703
+ /**
5704
+ * Emit a custom event to the external embedder.
5705
+ * This is used when the library is embedded in an iframe
5706
+ * to communicate events back to the parent application.
5707
+ *
5708
+ * @param eventName - The name of the event to emit
5709
+ * @param payload - Optional payload data to send with the event
5710
+ *
5711
+ * @example
5712
+ * ```ts
5713
+ * import { Superblocks } from "@superblocksteam/library";
5714
+ *
5715
+ * // Emit a simple event
5716
+ * Superblocks.emitEvent("formSubmitted");
5717
+ *
5718
+ * // Emit an event with payload
5719
+ * Superblocks.emitEvent("userSelected", { userId: "123", name: "John" });
5720
+ * ```
5721
+ */
5722
+ function emitEvent(eventName, payload = {}) {
5723
+ embedStore.emitEvent(eventName, payload);
5724
+ }
5725
+ /**
5726
+ * Get the current embed properties passed from the external embedder.
5727
+ *
5728
+ * @returns The current embed properties object
5729
+ *
5730
+ * @example
5731
+ * ```ts
5732
+ * import { Superblocks } from "@superblocksteam/library";
5733
+ *
5734
+ * const props = Superblocks.getEmbedProperties();
5735
+ * console.log(props.userId);
5736
+ * ```
5737
+ */
5738
+ function getEmbedProperties() {
5739
+ return embedStore.properties;
5740
+ }
5741
+ /**
5742
+ * The Superblocks object provides utilities for interacting with
5743
+ * the embedding context when the library is embedded in an iframe.
5744
+ */
5745
+ const Superblocks = {
5746
+ emitEvent,
5747
+ getEmbedProperties
5748
+ };
5749
+
5750
+ //#endregion
5751
+ //#region src/lib/hooks/use-embed-properties.ts
5752
+ /**
5753
+ * React hook for accessing embed properties passed from the external embedder.
5754
+ * Automatically re-renders when properties change.
5755
+ *
5756
+ * @returns The current embed properties object (reactive)
5757
+ *
5758
+ * @example
5759
+ * ```tsx
5760
+ * import { useEmbedProperties } from "@superblocksteam/library";
5761
+ *
5762
+ * function MyComponent() {
5763
+ * const properties = useEmbedProperties();
5764
+ *
5765
+ * // Access properties passed from the embedder
5766
+ * const userId = properties.userId as string;
5767
+ * const theme = properties.theme as "light" | "dark";
5768
+ *
5769
+ * return <div>User: {userId}, Theme: {theme}</div>;
5770
+ * }
5771
+ * ```
5772
+ */
5773
+ function useEmbedProperties() {
5774
+ return useStandaloneObserverMemo(() => embedStore.properties, []);
5775
+ }
5776
+
5777
+ //#endregion
5778
+ //#region src/lib/hooks/use-embed-event.ts
5779
+ /**
5780
+ * React hook for listening to events triggered by the external embedder.
5781
+ * The handler will be called whenever the embedder triggers the specified event.
5782
+ *
5783
+ * @param eventName - The name of the event to listen for
5784
+ * @param handler - Callback function invoked when the event is triggered
5785
+ *
5786
+ * @example
5787
+ * ```tsx
5788
+ * import { useEmbedEvent } from "@superblocksteam/library";
5789
+ *
5790
+ * function MyComponent() {
5791
+ * useEmbedEvent("refreshData", (payload) => {
5792
+ * console.log("Embedder requested refresh:", payload);
5793
+ * // Refetch data, reset state, etc.
5794
+ * });
5795
+ *
5796
+ * useEmbedEvent("themeChange", (payload) => {
5797
+ * const { theme } = payload as { theme: "light" | "dark" };
5798
+ * setTheme(theme);
5799
+ * });
5800
+ *
5801
+ * return <div>Listening for events...</div>;
5802
+ * }
5803
+ * ```
5804
+ */
5805
+ function useEmbedEvent(eventName, handler) {
5806
+ const handlerRef = useRef(handler);
5807
+ handlerRef.current = handler;
5808
+ useEffect(() => {
5809
+ const listener = (event) => {
5810
+ const customEvent = event;
5811
+ handlerRef.current(customEvent.detail ?? {});
5812
+ };
5813
+ window.addEventListener(`superblocks:${eventName}`, listener);
5814
+ return () => {
5815
+ window.removeEventListener(`superblocks:${eventName}`, listener);
5816
+ };
5817
+ }, [eventName]);
5818
+ }
5819
+
5820
+ //#endregion
5821
+ //#region src/lib/hooks/use-emit-embed-event.ts
5822
+ /**
5823
+ * React hook that returns a function to emit events to the external embedder.
5824
+ * Use this to communicate actions or state changes back to the parent application.
5825
+ *
5826
+ * @returns A function to emit events to the embedder
5827
+ *
5828
+ * @example
5829
+ * ```tsx
5830
+ * import { useEmitEmbedEvent } from "@superblocksteam/library";
5831
+ *
5832
+ * function MyComponent() {
5833
+ * const emitEvent = useEmitEmbedEvent();
5834
+ *
5835
+ * const handleFormSubmit = (data: FormData) => {
5836
+ * emitEvent("formSubmitted", {
5837
+ * formId: "contact-form",
5838
+ * timestamp: Date.now(),
5839
+ * data,
5840
+ * });
5841
+ * };
5842
+ *
5843
+ * const handleRowClick = (row: { id: string; name: string }) => {
5844
+ * emitEvent("rowSelected", { rowId: row.id, rowName: row.name });
5845
+ * };
5846
+ *
5847
+ * return (
5848
+ * <button onClick={() => emitEvent("buttonClicked", { action: "save" })}>
5849
+ * Save
5850
+ * </button>
5851
+ * );
5852
+ * }
5853
+ * ```
5854
+ */
5855
+ function useEmitEmbedEvent() {
5856
+ return useCallback((eventName, payload = {}) => {
5857
+ embedStore.emitEvent(eventName, payload);
5858
+ }, []);
5859
+ }
5860
+
5524
5861
  //#endregion
5525
5862
  //#region src/lib/index.ts
5526
5863
  early_console_buffer_default.getInstance().patchEarly();
5527
5864
  registerHtmlElements();
5528
5865
 
5529
5866
  //#endregion
5530
- export { App, PageNotFound, Prop, Property, PropsCategory, RouteLoadError, Section, sb_provider_default as SuperblocksProvider, getAppMode, logoutIntegrations, registerComponent, tailwindStylesCategory, useApiStateful as useApi, useSuperblocksGroups, useSuperblocksProfiles, useSuperblocksUser };
5867
+ export { App, PageNotFound, Prop, Property, PropsCategory, RouteLoadError, Section, Superblocks, sb_provider_default as SuperblocksProvider, embedStore, getAppMode, logoutIntegrations, registerComponent, tailwindStylesCategory, useApiStateful as useApi, useEmbedEvent, useEmbedProperties, useEmitEmbedEvent, useSuperblocksGroups, useSuperblocksProfiles, useSuperblocksUser };
5531
5868
  //# sourceMappingURL=index.js.map