@oatfi/ui 0.6.0 → 0.7.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/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Theme as Theme$1 } from '@mui/material/styles';
2
2
  import * as react from 'react';
3
- import react__default from 'react';
3
+ import react__default, { FC } from 'react';
4
4
  import * as styled_components_dist_types from 'styled-components/dist/types';
5
5
  import * as styled_components from 'styled-components';
6
6
 
@@ -811,6 +811,28 @@ interface AchVerificationConsentProps {
811
811
  */
812
812
  declare function AchVerificationConsent({ consentGiven, onChange, disabled, actionLabel, testId, }: AchVerificationConsentProps): react__default.JSX.Element;
813
813
 
814
+ interface EnvironmentTagProps {
815
+ /** The Vercel project the bundle was built for (`OATFI_ENV`), `local` under a dev server. */
816
+ bundleEnv?: string;
817
+ /** The host's `environment` attribute. */
818
+ apiEnv?: string;
819
+ /** Git ref the bundle was built from, for the tooltip. */
820
+ buildRef?: string;
821
+ /** Short commit SHA, for the tooltip. */
822
+ buildSha?: string;
823
+ size?: 'small' | 'medium';
824
+ /** `data-testid` on the chip. Override when several embeds share a page. */
825
+ testId?: string;
826
+ }
827
+ /**
828
+ * The environment chip for embedded components. Shows which API the component
829
+ * calls and, when it differs, which Vercel project the bundle came from:
830
+ * `DEV` on a match, `LOCAL | API DEV` for a local dev server, `BUNDLE DEV | API STG`
831
+ * (red-bordered) on a mismatch, a red `API ?` for an unrecognised API env, and
832
+ * nothing in production/production. See `resolveComponentEnvTag` for the rules.
833
+ */
834
+ declare const EnvironmentTag: FC<EnvironmentTagProps>;
835
+
814
836
  interface PreviewProps {
815
837
  /** Partner branding to render the sample with. Omit for the default theme. */
816
838
  branding?: Branding;
@@ -824,5 +846,78 @@ interface PreviewProps {
824
846
  */
825
847
  declare function Preview({ branding, className }: PreviewProps): react__default.JSX.Element;
826
848
 
827
- export { AchVerificationConsent, AsteriskMark, AsteriskNote, AutocompleteInput, Badge, Banner, BaseInput, Body100, Body200, Body400, Button, ButtonContainer, CheckboxInput, CollapsibleSource, Container, Content, CurrencyInput, DateInput, DetailElement, DetailRow, DetailsContainer, DotsMenu, DropDown, DropdownContainer, DropdownItem, DropdownList, EmailInput, FieldsGrid, FileInput, FlexColumnWrapper, FlexRowWrapper, FooterActions, FooterRight, Footnote, Form, FormActions, FormCheckboxLabel, FormColumn, FormRow, FormSubtitle, FormTitle, H1, H2, H3, HelperText, InputError, InputLabel, InputWrapper, Loader, ManualMethodCard, MethodBody, MethodCard, MethodHeader, MethodTitle, NoResults, PhoneInput, PlaidMethodCard, PlaidTile, Preview, RadioInput, SSNInput, SearchDropdown, SelectInput, StatusTag, Stepper, Tabs, TaxIdInput, TermsDocument, TermsList, TextInput, ThemeProvider, UnderwritingStatus, UploadZone, buildMuiTheme, defaultTheme, mergeBranding, useTheme };
828
- export type { AchVerificationConsentProps, BadgeVariant, Branding, CollapsibleSourceProps, CurrencyInputProps, DateInputProps, DotsMenuOption, DotsMenuProps, DropDownProps, EmailInputProps, FileInputProps, FootnoteLink, FootnoteProps, LoaderProps, ManualMethodCardProps, ManualMethodStatus, ManualMethodValue, Option, PhoneInputProps, PlaidConnection, PlaidMethodCardProps, PlaidTileProps, PreviewProps, SSNInputProps, SearchDropdownProps, StepperProps, StepperStep, Tab, TabsProps, TaxIdInputProps, TermsDocumentProps, TextInputProps, Theme, ThemeBorder, ThemeColors, ThemeProviderProps, ThemeTypography, UnderwritingDecision, UnderwritingStatusProps, UploadZoneProps, UploadedFile };
849
+ /**
850
+ * Environment chip logic for embedded components. Framework-free so the
851
+ * React-18 bundle (`mf-remote-react`), which can't take this package, can copy
852
+ * it verbatim.
853
+ *
854
+ * Ported from `oatfi-app-shell/src/lib/environment.ts`. The difference: a
855
+ * dashboard has one environment, a component has two — the Vercel project the
856
+ * bundle was built for (`bundleEnv`) and the API the host points it at
857
+ * (`apiEnv`, the `environment` attribute). They render as one chip that splits
858
+ * when they disagree.
859
+ */
860
+ type EnvironmentName = 'production' | 'staging' | 'qa' | 'development' | 'local';
861
+ interface EnvironmentTagInfo {
862
+ /** Short chip text, e.g. "STG". */
863
+ readonly label: string;
864
+ /** Full name, for the tooltip. */
865
+ readonly name: string;
866
+ /** Chip fill. */
867
+ readonly fill: string;
868
+ /** Text color on the fill. */
869
+ readonly ink: string;
870
+ }
871
+ type ComponentEnvTag =
872
+ /** Bundle and API agree (or the bundle env is unset). */
873
+ {
874
+ kind: 'single';
875
+ tag: EnvironmentTagInfo;
876
+ }
877
+ /** A local dev-server bundle on a non-prod API: informational, not a warning. */
878
+ | {
879
+ kind: 'local';
880
+ api: EnvironmentTagInfo;
881
+ }
882
+ /** Bundle and API disagree, or the bundle env is unrecognised (`bundleEnv: null`): a warning. */
883
+ | {
884
+ kind: 'split';
885
+ bundleEnv: EnvironmentName | null;
886
+ bundle: EnvironmentTagInfo;
887
+ api: EnvironmentTagInfo;
888
+ }
889
+ /** The API env is set but unrecognised, so the component calls the wrong API (or none). */
890
+ | {
891
+ kind: 'invalid-api';
892
+ apiEnv: string;
893
+ };
894
+ interface ComponentEnv {
895
+ /** The Vercel project the bundle was built for (`OATFI_ENV`), `local` under a dev server. */
896
+ bundleEnv?: string | null;
897
+ /** The host's `environment` attribute — which API the component calls. */
898
+ apiEnv?: string | null;
899
+ }
900
+ /**
901
+ * What the chip shows. Unset envs stay quiet; set-but-unrecognised ones are flagged:
902
+ * - API env unset → nothing (it means production)
903
+ * - API env unrecognised → `invalid-api`, an error (the host is calling the wrong API)
904
+ * - bundle env unset → treated as a match on the API env
905
+ * - bundle env unrecognised → a warning split against the API env
906
+ * - local bundle → informational `LOCAL | API X` on a non-prod API, a single `LOCAL` on
907
+ * the local API, and a warning against prod
908
+ * - prod/prod → nothing
909
+ */
910
+ declare const resolveComponentEnvTag: ({ bundleEnv, apiEnv, }: ComponentEnv) => ComponentEnvTag | null;
911
+ interface ComponentBuildInfo extends ComponentEnv {
912
+ /** Git ref the bundle was built from, e.g. `dev12` or `v1.4.0`. */
913
+ ref?: string | null;
914
+ /** Short commit SHA. */
915
+ sha?: string | null;
916
+ }
917
+ /** One-line debug string for the console: `bundle=development api=staging ref=dev12 sha=abc1234`. */
918
+ declare const describeComponentEnv: ({ bundleEnv, apiEnv, ref, sha }: ComponentBuildInfo) => string;
919
+ /** Tooltip text: `Bundle: Development (dev12, abc1234) · API: Staging`. */
920
+ declare const describeComponentEnvTitle: ({ bundleEnv, apiEnv, ref, sha, }: ComponentBuildInfo) => string;
921
+
922
+ export { AchVerificationConsent, AsteriskMark, AsteriskNote, AutocompleteInput, Badge, Banner, BaseInput, Body100, Body200, Body400, Button, ButtonContainer, CheckboxInput, CollapsibleSource, Container, Content, CurrencyInput, DateInput, DetailElement, DetailRow, DetailsContainer, DotsMenu, DropDown, DropdownContainer, DropdownItem, DropdownList, EmailInput, EnvironmentTag, FieldsGrid, FileInput, FlexColumnWrapper, FlexRowWrapper, FooterActions, FooterRight, Footnote, Form, FormActions, FormCheckboxLabel, FormColumn, FormRow, FormSubtitle, FormTitle, H1, H2, H3, HelperText, InputError, InputLabel, InputWrapper, Loader, ManualMethodCard, MethodBody, MethodCard, MethodHeader, MethodTitle, NoResults, PhoneInput, PlaidMethodCard, PlaidTile, Preview, RadioInput, SSNInput, SearchDropdown, SelectInput, StatusTag, Stepper, Tabs, TaxIdInput, TermsDocument, TermsList, TextInput, ThemeProvider, UnderwritingStatus, UploadZone, buildMuiTheme, defaultTheme, describeComponentEnv, describeComponentEnvTitle, mergeBranding, resolveComponentEnvTag, useTheme };
923
+ export type { AchVerificationConsentProps, BadgeVariant, Branding, CollapsibleSourceProps, ComponentBuildInfo, ComponentEnv, ComponentEnvTag, CurrencyInputProps, DateInputProps, DotsMenuOption, DotsMenuProps, DropDownProps, EmailInputProps, EnvironmentName, EnvironmentTagInfo, EnvironmentTagProps, FileInputProps, FootnoteLink, FootnoteProps, LoaderProps, ManualMethodCardProps, ManualMethodStatus, ManualMethodValue, Option, PhoneInputProps, PlaidConnection, PlaidMethodCardProps, PlaidTileProps, PreviewProps, SSNInputProps, SearchDropdownProps, StepperProps, StepperStep, Tab, TabsProps, TaxIdInputProps, TermsDocumentProps, TextInputProps, Theme, ThemeBorder, ThemeColors, ThemeProviderProps, ThemeTypography, UnderwritingDecision, UnderwritingStatusProps, UploadZoneProps, UploadedFile };
package/dist/index.esm.js CHANGED
@@ -2365,6 +2365,167 @@ function AchVerificationConsent({
2365
2365
  ] });
2366
2366
  }
2367
2367
 
2368
+ const AMBER = "#F59E0B";
2369
+ const CYAN = "#22D3EE";
2370
+ const GREY = "#9CA3AF";
2371
+ const GREEN = "#22C55E";
2372
+ const WHITE = "#FFFFFF";
2373
+ const INK = "#141312";
2374
+ const RED = "#DC2626";
2375
+ const ENVIRONMENT_MISMATCH_BORDER = RED;
2376
+ const ENVIRONMENT_TAGS = Object.freeze({
2377
+ production: Object.freeze({ label: "PROD", name: "Production", fill: WHITE, ink: INK }),
2378
+ staging: Object.freeze({ label: "STG", name: "Staging", fill: AMBER, ink: INK }),
2379
+ qa: Object.freeze({ label: "QA", name: "QA", fill: CYAN, ink: INK }),
2380
+ development: Object.freeze({ label: "DEV", name: "Development", fill: GREY, ink: INK }),
2381
+ local: Object.freeze({ label: "LOCAL", name: "Local", fill: GREEN, ink: INK })
2382
+ });
2383
+ const UNKNOWN_ENVIRONMENT_TAG = Object.freeze({
2384
+ label: "?",
2385
+ name: "Unknown",
2386
+ fill: WHITE,
2387
+ ink: INK
2388
+ });
2389
+ const INVALID_API_TAG = Object.freeze({
2390
+ label: "?",
2391
+ name: "Unknown",
2392
+ fill: RED,
2393
+ ink: WHITE
2394
+ });
2395
+ const ALIASES = /* @__PURE__ */ new Map([
2396
+ ["production", "production"],
2397
+ ["prod", "production"],
2398
+ ["staging", "staging"],
2399
+ ["stg", "staging"],
2400
+ ["qa", "qa"],
2401
+ ["development", "development"],
2402
+ ["dev", "development"],
2403
+ ["local", "local"]
2404
+ ]);
2405
+ const normalizeEnvironment = (value) => {
2406
+ const key = value?.trim().toLowerCase();
2407
+ return key && ALIASES.get(key) || null;
2408
+ };
2409
+ const resolveComponentEnvTag = ({
2410
+ bundleEnv,
2411
+ apiEnv
2412
+ }) => {
2413
+ const apiValue = apiEnv?.trim();
2414
+ if (!apiValue) return null;
2415
+ const api = normalizeEnvironment(apiValue);
2416
+ if (!api) return { kind: "invalid-api", apiEnv: apiValue };
2417
+ const bundleValue = bundleEnv?.trim();
2418
+ const bundle = normalizeEnvironment(bundleValue);
2419
+ const apiTag = ENVIRONMENT_TAGS[api];
2420
+ if (bundleValue && !bundle) {
2421
+ return { kind: "split", bundleEnv: null, bundle: UNKNOWN_ENVIRONMENT_TAG, api: apiTag };
2422
+ }
2423
+ if (bundle === "local" && api !== "local" && api !== "production") {
2424
+ return { kind: "local", api: apiTag };
2425
+ }
2426
+ if (bundle && bundle !== api) {
2427
+ return { kind: "split", bundleEnv: bundle, bundle: ENVIRONMENT_TAGS[bundle], api: apiTag };
2428
+ }
2429
+ if (api === "production") return null;
2430
+ return { kind: "single", tag: apiTag };
2431
+ };
2432
+ const environmentDebug = (value) => {
2433
+ const env = normalizeEnvironment(value);
2434
+ if (env) return env;
2435
+ const raw = value?.trim();
2436
+ return raw ? `unrecognised:${raw}` : "unknown";
2437
+ };
2438
+ const describeComponentEnv = ({ bundleEnv, apiEnv, ref, sha }) => [
2439
+ `bundle=${environmentDebug(bundleEnv)}`,
2440
+ `api=${environmentDebug(apiEnv)}`,
2441
+ `ref=${ref || "unknown"}`,
2442
+ `sha=${sha || "unknown"}`
2443
+ ].join(" ");
2444
+ const environmentTitle = (value) => {
2445
+ const env = normalizeEnvironment(value);
2446
+ if (env) return ENVIRONMENT_TAGS[env].name;
2447
+ const raw = value?.trim();
2448
+ return raw ? `Unrecognised "${raw}"` : "Unknown";
2449
+ };
2450
+ const describeComponentEnvTitle = ({
2451
+ bundleEnv,
2452
+ apiEnv,
2453
+ ref,
2454
+ sha
2455
+ }) => {
2456
+ const build = [ref, sha].filter(Boolean).join(", ");
2457
+ return `Bundle: ${environmentTitle(bundleEnv)}${build ? ` (${build})` : ""} \xB7 API: ${environmentTitle(apiEnv)}`;
2458
+ };
2459
+
2460
+ const FONT_SIZE = { small: 9, medium: 11 };
2461
+ const PADDING_X = { small: 6, medium: 8 };
2462
+ const FONT_FAMILY = 'Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
2463
+ const BORDER_WIDTH = 1.5;
2464
+ const base = (size) => ({
2465
+ display: "inline-flex",
2466
+ alignItems: "stretch",
2467
+ boxSizing: "border-box",
2468
+ fontFamily: FONT_FAMILY,
2469
+ fontSize: FONT_SIZE[size],
2470
+ fontWeight: 800,
2471
+ letterSpacing: "0.1em",
2472
+ lineHeight: 1.4,
2473
+ whiteSpace: "nowrap",
2474
+ borderRadius: 0
2475
+ });
2476
+ const half = (tag, label, size) => /* @__PURE__ */ jsx("span", { style: { padding: `2px ${PADDING_X[size]}px`, background: tag.fill, color: tag.ink }, children: label });
2477
+ const EnvironmentTag = ({
2478
+ bundleEnv,
2479
+ apiEnv,
2480
+ buildRef,
2481
+ buildSha,
2482
+ size = "small",
2483
+ testId = "oatfi-env-tag"
2484
+ }) => {
2485
+ const result = resolveComponentEnvTag({ bundleEnv, apiEnv });
2486
+ if (!result) return null;
2487
+ const title = describeComponentEnvTitle({ bundleEnv, apiEnv, ref: buildRef, sha: buildSha });
2488
+ const chip = (border, children) => /* @__PURE__ */ jsx(
2489
+ "span",
2490
+ {
2491
+ role: "note",
2492
+ "aria-label": `Environment: ${title}`,
2493
+ "data-testid": testId,
2494
+ "data-env-kind": result.kind,
2495
+ title,
2496
+ style: { ...base(size), border: `${BORDER_WIDTH}px solid ${border}` },
2497
+ children
2498
+ }
2499
+ );
2500
+ switch (result.kind) {
2501
+ case "single":
2502
+ return chip(result.tag.fill, half(result.tag, result.tag.label, size));
2503
+ case "local":
2504
+ return chip(
2505
+ ENVIRONMENT_TAGS.local.fill,
2506
+ /* @__PURE__ */ jsxs(Fragment, { children: [
2507
+ half(ENVIRONMENT_TAGS.local, ENVIRONMENT_TAGS.local.label, size),
2508
+ half(result.api, `API ${result.api.label}`, size)
2509
+ ] })
2510
+ );
2511
+ case "invalid-api":
2512
+ return chip(
2513
+ INVALID_API_TAG.fill,
2514
+ half(INVALID_API_TAG, `API ${INVALID_API_TAG.label}`, size)
2515
+ );
2516
+ case "split": {
2517
+ const bundleLabel = result.bundleEnv === "local" ? "LOCAL" : `BUNDLE ${result.bundle.label}`;
2518
+ return chip(
2519
+ ENVIRONMENT_MISMATCH_BORDER,
2520
+ /* @__PURE__ */ jsxs(Fragment, { children: [
2521
+ half(result.bundle, bundleLabel, size),
2522
+ half(result.api, `API ${result.api.label}`, size)
2523
+ ] })
2524
+ );
2525
+ }
2526
+ }
2527
+ };
2528
+
2368
2529
  const PreviewCard = styled.div`
2369
2530
  display: flex;
2370
2531
  gap: 2rem;
@@ -2436,5 +2597,5 @@ function Preview({ branding, className }) {
2436
2597
  return /* @__PURE__ */ jsx(ThemeProvider, { branding, children: /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(PreviewContent, {}) }) });
2437
2598
  }
2438
2599
 
2439
- export { AchVerificationConsent, AsteriskMark, AsteriskNote, AutocompleteInput, Badge, Banner, BaseInput, Body100, Body200, Body400, Button, ButtonContainer, CheckboxInput, CollapsibleSource, Container, Content$1 as Content, CurrencyInput, DateInput, DetailElement, DetailRow, DetailsContainer, DotsMenu, DropDown, DropdownContainer, DropdownItem, DropdownList, EmailInput, FieldsGrid, FileInput, FlexColumnWrapper, FlexRowWrapper, FooterActions, FooterRight, Footnote, Form, FormActions, FormCheckboxLabel, FormColumn, FormRow, FormSubtitle, FormTitle, H1, H2, H3, HelperText, InputError, InputLabel, InputWrapper, Loader, ManualMethodCard, MethodBody, MethodCard, MethodHeader, MethodTitle, NoResults, PhoneInput, PlaidMethodCard, PlaidTile, Preview, RadioInput, SSNInput, SearchDropdown, SelectInput, StatusTag, Stepper, Tabs, TaxIdInput, TermsDocument, TermsList, TextInput, ThemeProvider, UnderwritingStatus, UploadZone, buildMuiTheme, defaultTheme, mergeBranding, useTheme };
2600
+ export { AchVerificationConsent, AsteriskMark, AsteriskNote, AutocompleteInput, Badge, Banner, BaseInput, Body100, Body200, Body400, Button, ButtonContainer, CheckboxInput, CollapsibleSource, Container, Content$1 as Content, CurrencyInput, DateInput, DetailElement, DetailRow, DetailsContainer, DotsMenu, DropDown, DropdownContainer, DropdownItem, DropdownList, EmailInput, EnvironmentTag, FieldsGrid, FileInput, FlexColumnWrapper, FlexRowWrapper, FooterActions, FooterRight, Footnote, Form, FormActions, FormCheckboxLabel, FormColumn, FormRow, FormSubtitle, FormTitle, H1, H2, H3, HelperText, InputError, InputLabel, InputWrapper, Loader, ManualMethodCard, MethodBody, MethodCard, MethodHeader, MethodTitle, NoResults, PhoneInput, PlaidMethodCard, PlaidTile, Preview, RadioInput, SSNInput, SearchDropdown, SelectInput, StatusTag, Stepper, Tabs, TaxIdInput, TermsDocument, TermsList, TextInput, ThemeProvider, UnderwritingStatus, UploadZone, buildMuiTheme, defaultTheme, describeComponentEnv, describeComponentEnvTitle, mergeBranding, resolveComponentEnvTag, useTheme };
2440
2601
  //# sourceMappingURL=index.esm.js.map