@ethisyscore/plugin-ui 1.94.1 → 1.95.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.
@@ -298,6 +298,33 @@ declare const ORGANISATION_SETTINGS_URI = "ethisys:organisation-settings";
298
298
  */
299
299
  declare function useOrgFormatSync(): void;
300
300
 
301
+ /**
302
+ * Reads the caller organisation's reporting currency from the host
303
+ * {@link REPORTING_CURRENCY_TOOL} and stamps it into the core-utils reporting-currency
304
+ * ref (`@ethisyscore/core-utils/money`), so THIS plugin bundle's pure
305
+ * `formatMoney(amount)` renders reporting-currency amounts in the org's currency
306
+ * without threading a code.
307
+ *
308
+ * The org-currency sibling of {@link useOrgFormatSync}. Each plugin bundle owns its
309
+ * own copy of the module ref, so this must run per bundle —
310
+ * `definePlatformReactPluginPage` and `definePlatformReactPluginOverlay` auto-call
311
+ * it once per surface mount, so plugins wire nothing.
312
+ *
313
+ * Reactive: the currency arrives asynchronously, after the surface has already
314
+ * rendered on the GBP fallback. The module ref is non-React, so a `useState` bump
315
+ * re-renders the surface once the currency resolves. Keyed on the active
316
+ * organisation id so switching organisation without a remount refetches.
317
+ *
318
+ * Fails open in both directions, mirroring {@link useOrgFormatSync}:
319
+ * - No TRANSPORT (standalone/mock run, unit test) — resolved via the OPTIONAL
320
+ * accessor, degrades to a no-op and `formatMoney` uses the GBP fallback.
321
+ * - No ACCESSOR (host realm older than SDK 1.88.0) — see the module-scope
322
+ * resolution above.
323
+ * On a rejected/failed fetch the ref is reset to the GBP fallback rather than left
324
+ * holding a previous organisation's currency.
325
+ */
326
+ declare function useReportingCurrencySync(): void;
327
+
301
328
  /** Host tool that resolves the caller org's reporting currency (default, else GBP). */
302
329
  declare const REPORTING_CURRENCY_TOOL = "settings:get-organisation-reporting-currency";
303
330
  /** Host tool that lists the currency catalogue. */
@@ -1359,4 +1386,4 @@ interface MenuConfigHostSidebarOptions {
1359
1386
  */
1360
1387
  declare function menuConfigToHostSidebarInput(config: HeaderMenuItem[], opts: MenuConfigHostSidebarOptions): HostSidebarHookInput;
1361
1388
 
1362
- export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useSurfaceUrl, useTypedToolInvokerMap, useView };
1389
+ export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceUrl, useTypedToolInvokerMap, useView };
@@ -298,6 +298,33 @@ declare const ORGANISATION_SETTINGS_URI = "ethisys:organisation-settings";
298
298
  */
299
299
  declare function useOrgFormatSync(): void;
300
300
 
301
+ /**
302
+ * Reads the caller organisation's reporting currency from the host
303
+ * {@link REPORTING_CURRENCY_TOOL} and stamps it into the core-utils reporting-currency
304
+ * ref (`@ethisyscore/core-utils/money`), so THIS plugin bundle's pure
305
+ * `formatMoney(amount)` renders reporting-currency amounts in the org's currency
306
+ * without threading a code.
307
+ *
308
+ * The org-currency sibling of {@link useOrgFormatSync}. Each plugin bundle owns its
309
+ * own copy of the module ref, so this must run per bundle —
310
+ * `definePlatformReactPluginPage` and `definePlatformReactPluginOverlay` auto-call
311
+ * it once per surface mount, so plugins wire nothing.
312
+ *
313
+ * Reactive: the currency arrives asynchronously, after the surface has already
314
+ * rendered on the GBP fallback. The module ref is non-React, so a `useState` bump
315
+ * re-renders the surface once the currency resolves. Keyed on the active
316
+ * organisation id so switching organisation without a remount refetches.
317
+ *
318
+ * Fails open in both directions, mirroring {@link useOrgFormatSync}:
319
+ * - No TRANSPORT (standalone/mock run, unit test) — resolved via the OPTIONAL
320
+ * accessor, degrades to a no-op and `formatMoney` uses the GBP fallback.
321
+ * - No ACCESSOR (host realm older than SDK 1.88.0) — see the module-scope
322
+ * resolution above.
323
+ * On a rejected/failed fetch the ref is reset to the GBP fallback rather than left
324
+ * holding a previous organisation's currency.
325
+ */
326
+ declare function useReportingCurrencySync(): void;
327
+
301
328
  /** Host tool that resolves the caller org's reporting currency (default, else GBP). */
302
329
  declare const REPORTING_CURRENCY_TOOL = "settings:get-organisation-reporting-currency";
303
330
  /** Host tool that lists the currency catalogue. */
@@ -1359,4 +1386,4 @@ interface MenuConfigHostSidebarOptions {
1359
1386
  */
1360
1387
  declare function menuConfigToHostSidebarInput(config: HeaderMenuItem[], opts: MenuConfigHostSidebarOptions): HostSidebarHookInput;
1361
1388
 
1362
- export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useSurfaceUrl, useTypedToolInvokerMap, useView };
1389
+ export { type AuthenticatedQueryResult, type CurrencyInfo, type CurrencySelector, DEFAULT_MAX_UPLOAD_BYTES, type DefinePlatformReactPluginOverlayOptions, type DefinePlatformReactPluginPageOptions, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HostSidebarHookInput, HostSidebarInput, type InsetLease, LIST_CURRENCIES_TOOL, type ManagedLifecycle, type McpToolArgs, type McpToolContract, type McpToolContracts, type McpToolResult, type MenuConfigHostSidebarOptions, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, type OverlayHostApi, type OverlayHostCapabilities, OverlayHostContext, type PlatformReactOverlayProps, type PluginOverlayDefinerConfig, type PluginPageDefinerConfig, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL, type ReactRouterShimOptions, SurfaceBaseContext, type SurfaceBaseValue, TemplateContext, type TemplateManifest, type ToHostSidebarInputOptions, ToolInvoker, TypedMcpService, type UseCurrencyResult, type UseMcpUploadOptions, type UseMcpUploadResult, type UseMcpUploadTarget, type ViewComponent, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, resolveSurfaceBase, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceUrl, useTypedToolInvokerMap, useView };
@@ -1,4 +1,4 @@
1
- import { createContext, useEffect, useContext, useState, useMemo, createElement, useCallback, useRef, useSyncExternalStore } from 'react';
1
+ import { createContext, useEffect, useContext, useState, useMemo, useRef, createElement, useCallback, useSyncExternalStore } from 'react';
2
2
  import { QueryClient, useQuery, useQueries, QueryClientProvider } from '@tanstack/react-query';
3
3
  import { definePlatformReactPage, emitNavigation } from '@ethisyscore/components-react';
4
4
  import * as extensionRuntime from '@ethisyscore/extension-runtime/plugin';
@@ -6,7 +6,7 @@ import { useHostIdentity, useMcpTool, useOptionalExtensionRuntimeTransport, useP
6
6
  import { useTheme, ThemeProvider } from '@mui/material';
7
7
  import { jsxs, jsx } from 'react/jsx-runtime';
8
8
  import { setOrgFormats } from '@ethisyscore/core-utils/date/org-format';
9
- import { MONEY_FALLBACK_LOCALE, formatMoney } from '@ethisyscore/core-utils/money';
9
+ import { setOrgReportingCurrency, MONEY_FALLBACK_LOCALE, formatMoney } from '@ethisyscore/core-utils/money';
10
10
 
11
11
  // src/platform-react/definePlatformReactPluginPage.tsx
12
12
  var TemplateContext = createContext(null);
@@ -182,6 +182,50 @@ function useOrgFormatSync() {
182
182
  return () => controller.abort();
183
183
  }, [transport, organisationId]);
184
184
  }
185
+ var warnedAboutMissingAccessor2 = false;
186
+ var useOptionalExtensionRuntimeTransport4 = typeof extensionRuntime.useOptionalExtensionRuntimeTransport === "function" ? extensionRuntime.useOptionalExtensionRuntimeTransport : () => {
187
+ if (!warnedAboutMissingAccessor2) {
188
+ warnedAboutMissingAccessor2 = true;
189
+ console.warn(
190
+ "[plugin-ui] The host realm does not expose useOptionalExtensionRuntimeTransport (host SDK predates 1.88.0). The organisation reporting currency falls back to GBP for this bundle. Bump the host's @ethisyscore/extension-runtime pin to restore it."
191
+ );
192
+ }
193
+ return null;
194
+ };
195
+ var REPORTING_CURRENCY_TOOL = "settings:get-organisation-reporting-currency";
196
+ function useReportingCurrencySync() {
197
+ const transport = useOptionalExtensionRuntimeTransport4();
198
+ const organisationId = extensionRuntime.useHostIdentity()?.organisationId ?? null;
199
+ const [, bumpVersion] = useState(0);
200
+ const previousOrganisationId = useRef(void 0);
201
+ if (previousOrganisationId.current !== organisationId) {
202
+ previousOrganisationId.current = organisationId;
203
+ setOrgReportingCurrency(null);
204
+ }
205
+ useEffect(() => {
206
+ setOrgReportingCurrency(null);
207
+ bumpVersion((v) => v + 1);
208
+ if (!transport) return;
209
+ const controller = new AbortController();
210
+ transport.invokeTool(
211
+ REPORTING_CURRENCY_TOOL,
212
+ {},
213
+ controller.signal
214
+ ).then((result) => {
215
+ if (controller.signal.aborted) return;
216
+ const currency = result?.currency ?? null;
217
+ setOrgReportingCurrency(
218
+ currency ? { code: currency.code, decimalPlaces: currency.decimalPlaces } : null
219
+ );
220
+ bumpVersion((v) => v + 1);
221
+ }).catch(() => {
222
+ if (controller.signal.aborted) return;
223
+ setOrgReportingCurrency(null);
224
+ bumpVersion((v) => v + 1);
225
+ });
226
+ return () => controller.abort();
227
+ }, [transport, organisationId]);
228
+ }
185
229
 
186
230
  // src/platform-react/definePlatformReactPluginPage.tsx
187
231
  function makeDefaultQueryClient() {
@@ -208,6 +252,7 @@ function definePlatformReactPluginPage(Page, options) {
208
252
  } = options;
209
253
  function PluginPage(props) {
210
254
  useOrgFormatSync();
255
+ useReportingCurrencySync();
211
256
  const page = createElement(Page, props);
212
257
  const body = wrapPage ? wrapPage(page) : page;
213
258
  const surfaceTree = createElement(
@@ -369,7 +414,7 @@ function useAuthenticatedQuery(options) {
369
414
  function useAuthenticatedQueries(queries) {
370
415
  return useQueries({ queries });
371
416
  }
372
- var REPORTING_CURRENCY_TOOL = "settings:get-organisation-reporting-currency";
417
+ var REPORTING_CURRENCY_TOOL2 = "settings:get-organisation-reporting-currency";
373
418
  var LIST_CURRENCIES_TOOL = "settings:list-currencies";
374
419
  var emptyCatalogue = () => /* @__PURE__ */ new Map();
375
420
  var SETTLED_FULFILLED = "fulfilled";
@@ -390,7 +435,7 @@ function useCurrency() {
390
435
  const controller = new AbortController();
391
436
  Promise.allSettled([
392
437
  transport.invokeTool(
393
- REPORTING_CURRENCY_TOOL,
438
+ REPORTING_CURRENCY_TOOL2,
394
439
  {},
395
440
  controller.signal
396
441
  ),
@@ -402,7 +447,8 @@ function useCurrency() {
402
447
  ]).then(([reporting, list]) => {
403
448
  if (controller.signal.aborted) return;
404
449
  if (reporting.status === SETTLED_FULFILLED) {
405
- setReportingCurrency(reporting.value?.currency ?? null);
450
+ const resolved = reporting.value?.currency ?? null;
451
+ setReportingCurrency(resolved);
406
452
  }
407
453
  if (list.status === SETTLED_FULFILLED && Array.isArray(list.value)) {
408
454
  setCurrencies(new Map(list.value.map((currency) => [currency.id, currency])));
@@ -700,6 +746,7 @@ function definePlatformReactPluginOverlay(Overlay, options) {
700
746
  const { rootClassName, styleId, css, manifest = {}, queryClient = defaultQueryClient2, wrapOverlay } = options;
701
747
  return function MountedOverlay(props) {
702
748
  useOrgFormatSync();
749
+ useReportingCurrencySync();
703
750
  const tree = createElement(
704
751
  OverlayHostContext.Provider,
705
752
  { value: props.overlayHost },
@@ -1022,6 +1069,6 @@ function menuConfigToHostSidebarInput(config, opts) {
1022
1069
  return { mode: "actions", actions };
1023
1070
  }
1024
1071
 
1025
- export { BaseMcpService, DEFAULT_MAX_UPLOAD_BYTES, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HOST_CHROME_CONTRACT_VERSION, HostSidebarActionsContext, LIST_CURRENCIES_TOOL, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, OverlayHostContext, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL, SIDEBAR_MODE, SurfaceBaseContext, TemplateContext, TypedMcpService, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, isHostChromeCompatible, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, notViaMcp, reportHostChromeDiagnostic, resolveSurfaceBase, setHostChromeDiagnosticSink, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useHostSidebarActions, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useSurfaceUrl, useToolInvoker, useToolInvokerMap, useTypedToolInvokerMap, useView };
1072
+ export { BaseMcpService, DEFAULT_MAX_UPLOAD_BYTES, EHX_PLUGIN_PORTAL_ATTR, EHX_PLUGIN_PORTAL_CLASS, EHX_PLUGIN_ROOT_CLASS, HOST_CHROME_CONTRACT_VERSION, HostSidebarActionsContext, LIST_CURRENCIES_TOOL, MissingViewFallback, ORGANISATION_SETTINGS_URI, OVERLAY_HOST_CONTRACT_VERSION, OverlayHostContext, PluginPortalScope, PluginStyleScope, REPORTING_CURRENCY_TOOL2 as REPORTING_CURRENCY_TOOL, SIDEBAR_MODE, SurfaceBaseContext, TemplateContext, TypedMcpService, buildSurfaceUrl, createPluginOverlayDefiner, createPluginPageDefiner, createReactRouterShim, createUseView, definePlatformReactPluginOverlay, definePlatformReactPluginPage, deriveHostEntityToken, injectPluginStyles, isComponent, isHostChromeCompatible, mcpTool, menuConfigToHostSidebarInput, normaliseSlug, notViaMcp, reportHostChromeDiagnostic, resolveSurfaceBase, setHostChromeDiagnosticSink, surfacePathFor, toHostSidebarInput, useAuthenticatedQueries, useAuthenticatedQuery, useCurrency, useHostSidebarActions, useManagedLifecycle, useMcpUpload, useOrgFormatSync, useOverlayHost, usePluginRealtime, useReportingCurrencySync, useSurfaceUrl, useToolInvoker, useToolInvokerMap, useTypedToolInvokerMap, useView };
1026
1073
  //# sourceMappingURL=index.js.map
1027
1074
  //# sourceMappingURL=index.js.map