@fluid-app/portal-sdk 0.1.375 → 0.1.376

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.
Files changed (29) hide show
  1. package/dist/{authoring-Di7OJapg.d.cts → authoring-DDJSpQcy.d.cts} +2 -2
  2. package/dist/{authoring-D0yimRFr.d.mts.map → authoring-DDJSpQcy.d.cts.map} +1 -1
  3. package/dist/{authoring-D0yimRFr.d.mts → authoring-DUQfz-af.d.mts} +2 -2
  4. package/dist/{authoring-Di7OJapg.d.cts.map → authoring-DUQfz-af.d.mts.map} +1 -1
  5. package/dist/index.cjs +119 -18
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +4 -3
  8. package/dist/index.d.cts.map +1 -1
  9. package/dist/index.d.mts +4 -3
  10. package/dist/index.d.mts.map +1 -1
  11. package/dist/index.mjs +119 -18
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/preview/preview-entry.cjs +1 -1
  14. package/dist/preview/preview-entry.d.cts +1 -1
  15. package/dist/preview/preview-entry.d.mts +1 -1
  16. package/dist/preview/preview-entry.mjs +1 -1
  17. package/dist/{widget-package-descriptor-Chc8Gb6V.d.cts → widget-package-descriptor-BFknJmTb.d.cts} +11 -1
  18. package/dist/{widget-package-descriptor-Chc8Gb6V.d.cts.map → widget-package-descriptor-BFknJmTb.d.cts.map} +1 -1
  19. package/dist/{widget-package-descriptor-fjHqObKE.d.mts → widget-package-descriptor-BTnvi-td.d.mts} +11 -1
  20. package/dist/{widget-package-descriptor-fjHqObKE.d.mts.map → widget-package-descriptor-BTnvi-td.d.mts.map} +1 -1
  21. package/dist/{widget-package-utils-pdLitM72.cjs → widget-package-utils-CJp6o3RD.cjs} +94 -40
  22. package/dist/widget-package-utils-CJp6o3RD.cjs.map +1 -0
  23. package/dist/{widget-package-utils-DG2ibxqS.mjs → widget-package-utils-DnNxWKOo.mjs} +94 -40
  24. package/dist/widget-package-utils-DnNxWKOo.mjs.map +1 -0
  25. package/dist/widgets/authoring.d.cts +1 -1
  26. package/dist/widgets/authoring.d.mts +1 -1
  27. package/package.json +10 -10
  28. package/dist/widget-package-utils-DG2ibxqS.mjs.map +0 -1
  29. package/dist/widget-package-utils-pdLitM72.cjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -60,7 +60,7 @@ import { i as useScreenHeaderSlotRefs, r as ScreenHeaderProvider } from "./Scree
60
60
  import { t as useStore } from "./use-store-DB3FAMT2.mjs";
61
61
  import { a as FallbackCard, i as CoreScreenPlaceholder, r as customersScreenPropertySchema, t as CustomersScreen } from "./CustomersScreen-DVHcFV8G.mjs";
62
62
  import { n as useAppNavigation, t as AppNavigationProvider } from "./AppNavigationContext-DgelzxV9.mjs";
63
- import { a as loadWidgetPackages, c as getDefaultWidgetPackageManifestUrl, d as createDefaultFluidConfig, i as installAndReadFluidWidgetsRegistry, l as buildWidgetRegistry, n as resolveHostedWidgetPackageManifestUrl, o as subscribeToFluidWidgetsRegistry, r as fetchWidgetPackageDescriptors, t as dedupeWidgetPackagesByPackageIdAndVersion, u as mergeRegisteredWidgetsIntoRegistry } from "./widget-package-utils-DG2ibxqS.mjs";
63
+ import { a as loadWidgetPackages, c as getDefaultWidgetPackageManifestUrl, d as createDefaultFluidConfig, i as installAndReadFluidWidgetsRegistry, l as buildWidgetRegistry, n as resolveHostedWidgetPackageManifestUrl, o as subscribeToFluidWidgetsRegistry, r as fetchWidgetPackageDescriptors, t as dedupeWidgetPackagesByPackageIdAndVersion, u as mergeRegisteredWidgetsIntoRegistry } from "./widget-package-utils-DnNxWKOo.mjs";
64
64
  import { c as sourceWidgetPackagesToManifests, i as isSourceWidgetPackage, n as defineWidgetPackage, t as defineWidget } from "./authoring-CLuHp6qI.mjs";
65
65
  import "./use-portal-card-add-3ds-flow-BLjXfmje.mjs";
66
66
  import "./display-B3BfkaBm.mjs";
@@ -2652,6 +2652,12 @@ function AppShell({ appData: appDataProp, navigation: navigationProp, customPage
2652
2652
  }
2653
2653
  //#endregion
2654
2654
  //#region src/entry/create-portal.tsx
2655
+ const warnedPortalRuntimeMergeWarningMessages = /* @__PURE__ */ new Set();
2656
+ const warnPortalRuntimeMergeWarningOnce = (message) => {
2657
+ if (warnedPortalRuntimeMergeWarningMessages.has(message)) return;
2658
+ warnedPortalRuntimeMergeWarningMessages.add(message);
2659
+ console.warn(message);
2660
+ };
2655
2661
  /**
2656
2662
  * Last-resort error boundary for crashes above the AppShell (provider
2657
2663
  * setup, theme/auth bootstrap). Renders above FluidThemeProvider, so the
@@ -2732,37 +2738,67 @@ var RootBoundary = class extends Component {
2732
2738
  });
2733
2739
  }
2734
2740
  };
2735
- function RuntimeWidgetBootstrap({ children, fluidConfig, initialWidgetRegistry, ingestFluidWidgetsRegistry, widgetPackageLoadPromise }) {
2736
- const [widgetRegistry, setWidgetRegistry] = useState(initialWidgetRegistry);
2741
+ function RuntimeWidgetBootstrap({ children, fluidConfig, baseWidgetRegistry, initialGlobalRegisteredWidgets, shouldSubscribeToGlobalWidgetRegistry, widgetPackageLoadPromise }) {
2742
+ const [globalRegisteredWidgets, setGlobalRegisteredWidgets] = useState(initialGlobalRegisteredWidgets);
2743
+ const [loadedRegisteredWidgets, setLoadedRegisteredWidgets] = useState([]);
2737
2744
  const [isLoading, setIsLoading] = useState(() => Boolean(widgetPackageLoadPromise));
2738
2745
  const [loadFailed, setLoadFailed] = useState(false);
2739
2746
  useEffect(() => {
2740
- setWidgetRegistry(initialWidgetRegistry);
2741
- if (!ingestFluidWidgetsRegistry) return;
2742
- return subscribeToFluidWidgetsRegistry((registeredWidgets) => {
2743
- setWidgetRegistry((currentRegistry) => mergeRegisteredWidgetsIntoRegistry(currentRegistry, registeredWidgets));
2747
+ setGlobalRegisteredWidgets(initialGlobalRegisteredWidgets);
2748
+ }, [initialGlobalRegisteredWidgets]);
2749
+ useEffect(() => {
2750
+ if (!shouldSubscribeToGlobalWidgetRegistry) return;
2751
+ const subscription = subscribeToFluidWidgetsRegistry((registeredWidgets) => {
2752
+ setGlobalRegisteredWidgets(registeredWidgets);
2744
2753
  });
2745
- }, [initialWidgetRegistry, ingestFluidWidgetsRegistry]);
2754
+ setGlobalRegisteredWidgets(subscription.registeredWidgets);
2755
+ return subscription.unsubscribe;
2756
+ }, [shouldSubscribeToGlobalWidgetRegistry]);
2746
2757
  useEffect(() => {
2758
+ setLoadedRegisteredWidgets([]);
2747
2759
  setIsLoading(Boolean(widgetPackageLoadPromise));
2748
2760
  setLoadFailed(false);
2749
2761
  if (!widgetPackageLoadPromise) return;
2750
2762
  let cancelled = false;
2751
2763
  widgetPackageLoadPromise.then((summary) => {
2752
2764
  if (cancelled) return;
2753
- setWidgetRegistry((currentRegistry) => mergeRegisteredWidgetsIntoRegistry(currentRegistry, summary.registeredWidgets));
2765
+ setLoadedRegisteredWidgets(summary.registeredWidgets);
2766
+ if (shouldSubscribeToGlobalWidgetRegistry) setGlobalRegisteredWidgets(installAndReadFluidWidgetsRegistry());
2754
2767
  setIsLoading(false);
2755
2768
  setLoadFailed(summary.hasFailures);
2756
2769
  }).catch((error) => {
2757
2770
  if (cancelled) return;
2758
2771
  console.error("[portal] Failed to load widget packages:", error);
2772
+ if (shouldSubscribeToGlobalWidgetRegistry) setGlobalRegisteredWidgets(installAndReadFluidWidgetsRegistry());
2759
2773
  setIsLoading(false);
2760
2774
  setLoadFailed(true);
2761
2775
  });
2762
2776
  return () => {
2763
2777
  cancelled = true;
2764
2778
  };
2765
- }, [widgetPackageLoadPromise]);
2779
+ }, [shouldSubscribeToGlobalWidgetRegistry, widgetPackageLoadPromise]);
2780
+ const warnedDuplicateGlobalWidgetTypesRef = useRef(/* @__PURE__ */ new Set());
2781
+ const { duplicateGlobalWidgetTypes, widgetRegistry } = useMemo(() => {
2782
+ const activeLoadedRegisteredWidgets = shouldSubscribeToGlobalWidgetRegistry ? syncLoadedWidgetsWithGlobalRegistry(loadedRegisteredWidgets, globalRegisteredWidgets) : loadedRegisteredWidgets;
2783
+ const dedupedGlobalWidgets = dedupeGlobalRegisteredWidgetsByType(shouldSubscribeToGlobalWidgetRegistry ? filterGlobalWidgetsAlreadyRepresentedByLoadedWidgets(globalRegisteredWidgets, activeLoadedRegisteredWidgets) : globalRegisteredWidgets);
2784
+ const globalWidgetRegistry = mergeRegisteredWidgetsIntoRegistry(baseWidgetRegistry, dedupedGlobalWidgets.widgets, warnPortalRuntimeMergeWarningOnce);
2785
+ return {
2786
+ duplicateGlobalWidgetTypes: dedupedGlobalWidgets.duplicateTypes,
2787
+ widgetRegistry: mergeRegisteredWidgetsIntoRegistry(globalWidgetRegistry, activeLoadedRegisteredWidgets, warnPortalRuntimeMergeWarningOnce)
2788
+ };
2789
+ }, [
2790
+ baseWidgetRegistry,
2791
+ globalRegisteredWidgets,
2792
+ loadedRegisteredWidgets,
2793
+ shouldSubscribeToGlobalWidgetRegistry
2794
+ ]);
2795
+ useEffect(() => {
2796
+ for (const widgetType of duplicateGlobalWidgetTypes) {
2797
+ if (warnedDuplicateGlobalWidgetTypesRef.current.has(widgetType)) continue;
2798
+ warnedDuplicateGlobalWidgetTypesRef.current.add(widgetType);
2799
+ warnDuplicateGlobalRuntimeWidgetType(widgetType);
2800
+ }
2801
+ }, [duplicateGlobalWidgetTypes]);
2766
2802
  const statusMessage = loadFailed ? "Some widgets failed to load. The portal will continue with available widgets." : isLoading ? "Loading widget packages…" : null;
2767
2803
  return /* @__PURE__ */ jsxs(FluidProvider, {
2768
2804
  config: fluidConfig,
@@ -2788,6 +2824,68 @@ function RuntimeWidgetBootstrap({ children, fluidConfig, initialWidgetRegistry,
2788
2824
  }) : null, children]
2789
2825
  });
2790
2826
  }
2827
+ function dedupeGlobalRegisteredWidgetsByType(globalWidgets) {
2828
+ if (globalWidgets.length < 2) return {
2829
+ duplicateTypes: [],
2830
+ widgets: globalWidgets
2831
+ };
2832
+ const duplicateTypes = /* @__PURE__ */ new Set();
2833
+ const widgetsByType = /* @__PURE__ */ new Map();
2834
+ for (const widget of globalWidgets) {
2835
+ if (widgetsByType.has(widget.type)) {
2836
+ duplicateTypes.add(widget.type);
2837
+ continue;
2838
+ }
2839
+ widgetsByType.set(widget.type, widget);
2840
+ }
2841
+ return duplicateTypes.size > 0 ? {
2842
+ duplicateTypes: Array.from(duplicateTypes),
2843
+ widgets: Array.from(widgetsByType.values())
2844
+ } : {
2845
+ duplicateTypes: [],
2846
+ widgets: globalWidgets
2847
+ };
2848
+ }
2849
+ function warnDuplicateGlobalRuntimeWidgetType(widgetType) {
2850
+ console.warn(`[portal-sdk] Ignoring duplicate global runtime widget type "${widgetType}" because an earlier global registration already provides that SDK-facing type.`);
2851
+ }
2852
+ function syncLoadedWidgetsWithGlobalRegistry(loadedWidgets, globalWidgets) {
2853
+ if (loadedWidgets.length === 0) return [];
2854
+ if (globalWidgets.length === 0) return loadedWidgets;
2855
+ const globalWidgetsByKey = new Map(globalWidgets.map((widget) => [createRuntimeRegisteredWidgetKey(widget.packageId, widget.version, widget.type), widget]));
2856
+ return loadedWidgets.flatMap((loadedWidget) => {
2857
+ const globalWidget = globalWidgetsByKey.get(createRuntimeRegisteredWidgetKey(loadedWidget.packageId, loadedWidget.version, loadedWidget.type));
2858
+ if (!globalWidget) return [];
2859
+ return [mergeLoadedWidgetWithGlobalWidget(loadedWidget, globalWidget)];
2860
+ });
2861
+ }
2862
+ function mergeLoadedWidgetWithGlobalWidget(loadedWidget, globalWidget) {
2863
+ return {
2864
+ ...loadedWidget,
2865
+ ...globalWidget,
2866
+ name: globalWidget.name ?? loadedWidget.name,
2867
+ displayName: globalWidget.displayName ?? loadedWidget.displayName,
2868
+ description: globalWidget.description ?? loadedWidget.description,
2869
+ icon: globalWidget.icon ?? loadedWidget.icon,
2870
+ category: globalWidget.category ?? loadedWidget.category,
2871
+ container: globalWidget.container ?? loadedWidget.container,
2872
+ minSdkVersion: globalWidget.minSdkVersion ?? loadedWidget.minSdkVersion,
2873
+ resizable: globalWidget.resizable ?? loadedWidget.resizable,
2874
+ packageType: loadedWidget.packageType
2875
+ };
2876
+ }
2877
+ function filterGlobalWidgetsAlreadyRepresentedByLoadedWidgets(globalWidgets, loadedWidgets) {
2878
+ if (globalWidgets.length === 0 || loadedWidgets.length === 0) return globalWidgets;
2879
+ const loadedWidgetKeys = new Set(loadedWidgets.map((widget) => createRuntimeRegisteredWidgetKey(widget.packageId, widget.version, widget.type)));
2880
+ return globalWidgets.filter((widget) => !loadedWidgetKeys.has(createRuntimeRegisteredWidgetKey(widget.packageId, widget.version, widget.type)));
2881
+ }
2882
+ function createRuntimeRegisteredWidgetKey(packageId, version, type) {
2883
+ return JSON.stringify([
2884
+ packageId,
2885
+ version,
2886
+ type
2887
+ ]);
2888
+ }
2791
2889
  /**
2792
2890
  * Bootstrap a Fluid portal with a single function call.
2793
2891
  *
@@ -2822,8 +2920,9 @@ function createPortal(config = {}) {
2822
2920
  const rootElement = document.getElementById(config.rootId ?? "root");
2823
2921
  if (!rootElement) throw new Error(`Portal root element "#${config.rootId ?? "root"}" not found`);
2824
2922
  const fluidConfig = createDefaultFluidConfig(config.fluid);
2825
- const preRegisteredWidgets = config.ingestPreRegisteredWidgets === false ? [] : installAndReadFluidWidgetsRegistry();
2826
- const initialWidgetRegistry = mergeRegisteredWidgetsIntoRegistry(buildWidgetRegistry(config.customWidgets ?? []), preRegisteredWidgets);
2923
+ const shouldSubscribeToGlobalWidgetRegistry = config.ingestPreRegisteredWidgets !== false;
2924
+ const initialGlobalRegisteredWidgets = shouldSubscribeToGlobalWidgetRegistry ? installAndReadFluidWidgetsRegistry() : [];
2925
+ const baseWidgetRegistry = buildWidgetRegistry(config.customWidgets ?? []);
2827
2926
  const widgetPackageLoadPromise = createWidgetPackageLoadPromise(config, fluidConfig);
2828
2927
  let app = /* @__PURE__ */ jsx(AppShell, {
2829
2928
  customPages: config.customPages,
@@ -2838,8 +2937,9 @@ function createPortal(config = {}) {
2838
2937
  errorReporter: config.errorReporter,
2839
2938
  children: /* @__PURE__ */ jsx(RuntimeWidgetBootstrap, {
2840
2939
  fluidConfig,
2841
- initialWidgetRegistry,
2842
- ingestFluidWidgetsRegistry: config.ingestPreRegisteredWidgets !== false,
2940
+ baseWidgetRegistry,
2941
+ initialGlobalRegisteredWidgets,
2942
+ shouldSubscribeToGlobalWidgetRegistry,
2843
2943
  widgetPackageLoadPromise,
2844
2944
  children: app
2845
2945
  })
@@ -2850,11 +2950,12 @@ function createWidgetPackageLoadPromise(config, fluidConfig) {
2850
2950
  const explicitWidgetPackages = dedupeWidgetPackagesByPackageIdAndVersion(config.widgetPackages ?? []);
2851
2951
  const hasExplicitDescriptorEndpoint = config.widgetPackageManifestUrl !== void 0;
2852
2952
  const descriptorEndpointUrl = hasExplicitDescriptorEndpoint ? config.widgetPackageManifestUrl ?? false : getDefaultWidgetPackageManifestUrl();
2853
- if (descriptorEndpointUrl === false) return explicitWidgetPackages.length ? loadWidgetPackages(explicitWidgetPackages) : void 0;
2953
+ const loadOptions = { ignoreExistingGlobalRegistrations: config.ingestPreRegisteredWidgets === false };
2954
+ if (descriptorEndpointUrl === false) return explicitWidgetPackages.length ? loadWidgetPackages(explicitWidgetPackages, loadOptions) : void 0;
2854
2955
  const isOmittedHostedCatalog = !hasExplicitDescriptorEndpoint && descriptorEndpointUrl === "/api/app/widget-packages";
2855
- return loadFetchedAndExplicitWidgetPackages(explicitWidgetPackages, isOmittedHostedCatalog ? resolveHostedWidgetPackageManifestUrl(descriptorEndpointUrl, fluidConfig.baseUrl) : descriptorEndpointUrl, config.widgetPackageAllowedOrigins, isOmittedHostedCatalog, isOmittedHostedCatalog ? "include" : void 0);
2956
+ return loadFetchedAndExplicitWidgetPackages(explicitWidgetPackages, isOmittedHostedCatalog ? resolveHostedWidgetPackageManifestUrl(descriptorEndpointUrl, fluidConfig.baseUrl) : descriptorEndpointUrl, config.widgetPackageAllowedOrigins, isOmittedHostedCatalog, isOmittedHostedCatalog ? "include" : void 0, loadOptions);
2856
2957
  }
2857
- async function loadFetchedAndExplicitWidgetPackages(explicitWidgetPackages, descriptorEndpointUrl, widgetPackageAllowedOrigins, trustCatalogAssetOrigins, credentials) {
2958
+ async function loadFetchedAndExplicitWidgetPackages(explicitWidgetPackages, descriptorEndpointUrl, widgetPackageAllowedOrigins, trustCatalogAssetOrigins, credentials, loadOptions) {
2858
2959
  let fetchedWidgetPackages = [];
2859
2960
  try {
2860
2961
  fetchedWidgetPackages = await fetchWidgetPackageDescriptors(descriptorEndpointUrl, {
@@ -2865,7 +2966,7 @@ async function loadFetchedAndExplicitWidgetPackages(explicitWidgetPackages, desc
2865
2966
  } catch (error) {
2866
2967
  console.warn("[portal] Failed to fetch widget package descriptors; continuing with explicit packages only:", error);
2867
2968
  }
2868
- return loadWidgetPackages(dedupeWidgetPackagesByPackageIdAndVersion([...explicitWidgetPackages, ...fetchedWidgetPackages]));
2969
+ return loadWidgetPackages(dedupeWidgetPackagesByPackageIdAndVersion([...explicitWidgetPackages, ...fetchedWidgetPackages]), loadOptions);
2869
2970
  }
2870
2971
  //#endregion
2871
2972
  //#region src/hooks/use-fluid-profile.ts