{"version":3,"file":"styleToTheme.mjs","sources":["../../../../../../../../web/src/ui/compat/styleToTheme.ts"],"sourcesContent":["import { logger, RUN_IN_DEV } from '@stytch/core';\nimport type { StyleConfig } from '@stytch/core/public';\n\nimport type { PresentationOptions } from '../components/PresentationConfig';\nimport type { Theme } from '../components/themes/ThemeConfig';\n\n/* eslint-disable lingui/no-unlocalized-strings */\n\n/**\n * Maps a legacy StyleConfig to the new Theme format.\n *\n * This is a best-effort mapping - some StyleConfig properties don't have\n * direct equivalents in Theme, and some Theme properties don't have\n * StyleConfig equivalents.\n *\n * StyleConfig properties that don't have good mappings to Theme:\n *  - inputs.placeholderColor - No equivalent (could potentially map to muted-foreground)\n *  - inputs.textColor - Mapped to foreground as approximation, but is input-specific\n *  - buttons.primary.borderColor - No specific mapping (could use border but loses specificity)\n *  - buttons.primary.borderRadius - Mapped to button-radius but loses primary-specific control\n *  - buttons.secondary.borderColor - No specific mapping (could use border but loses specificity)\n *  - buttons.secondary.borderRadius - Mapped to button-radius but loses secondary-specific control\n *  - buttons.disabled.* - No equivalents (disabled state styling not in Theme)\n *\n * Theme properties that don't have StyleConfig equivalents:\n *  - 'transition-duration' - defaulted to 0 instead of 0.15s in our new default theme\n *  - 'font-family-mono' - defaults to theme default which is system UI monospace\n *  - 'text-base' - defaults to 1rem which is close to the old font sizes\n *  - spacing - defaults to new theme default which is close but not equivalent to old spacing\n *  - shadow, 'shadow-button', 'shadow-input' - no default in new theme\n *  - foreground - Approximated from inputs.textColor but not exact\n *  - muted, 'muted-foreground'\n *  - 'accent-foreground'\n *  - ring - previously defaults to OS default focus outline color\n */\nexport function styleToTheme(\n  styleConfig: StyleConfig,\n  { silent }: { silent?: boolean } = {},\n): {\n  theme: Partial<Theme>;\n  options: Partial<PresentationOptions>;\n} {\n  const warn = silent\n    ? () => {\n        // noop\n      }\n    : logger.warn;\n  const error = silent\n    ? () => {\n        // noop\n      }\n    : logger.error;\n\n  const theme: Partial<Theme> = {};\n  const options: Partial<PresentationOptions> = {};\n\n  const { colors, container, inputs, hideHeaderText, buttons, logo, fontFamily, ...outerEmpty } = styleConfig;\n\n  // presentation.theme mapping\n  // ------------------------------------------------\n  RUN_IN_DEV(() => {\n    warn(\n      \"styleToTheme: We recommend setting theme['color-scheme'] to either 'light' or 'dark' explicitly \" +\n        'depending on whether this is a light or dark theme. This enables icons to automatically automatically ' +\n        'apply contrasting colors.',\n    );\n\n    if (Object.keys(outerEmpty).length > 0) warn('styleToTheme: Unrecognized style properties', outerEmpty);\n  });\n\n  theme['font-family'] = fontFamily;\n\n  if (colors) {\n    const { primary, secondary, success, warning, accent, error, ...expectEmpty } = colors;\n    RUN_IN_DEV(() => {\n      if (Object.keys(expectEmpty).length > 0) warn('styleToTheme: Unrecognized style.colors properties', expectEmpty);\n    });\n\n    Object.assign(theme, {\n      primary,\n      secondary,\n      success,\n      warning,\n      accent,\n      destructive: error,\n    } satisfies Partial<Theme>);\n  }\n\n  if (container) {\n    const { backgroundColor, borderColor, width, borderRadius, ...expectEmpty } = container;\n\n    RUN_IN_DEV(() => {\n      if (Object.keys(expectEmpty).length > 0)\n        warn('styleToTheme: Unrecognized style.container properties', expectEmpty);\n    });\n\n    Object.assign(theme, {\n      background: backgroundColor,\n      border: borderColor,\n      'container-width': width,\n      // 1/4 because the new base is quite small and most components use a 2x or 4x multiplier\n      'rounded-base': updateLength(borderRadius, 0.25),\n    } satisfies Partial<Theme>);\n  }\n\n  if (buttons) {\n    const { primary, secondary, disabled, ...expectEmpty } = buttons;\n\n    RUN_IN_DEV(() => {\n      if (Object.keys(expectEmpty).length > 0) warn('styleToTheme: Unrecognized style.buttons properties', expectEmpty);\n\n      if (disabled && Object.keys(disabled).length > 0)\n        warn('styleToTheme: buttons.disabled is no longer supported', { disabled });\n\n      if (primary?.borderColor && primary?.backgroundColor && primary.borderColor !== primary.backgroundColor)\n        error(\n          \"styleToTheme: primary button's border color is now always equal to background color; \" +\n            'having distinct colors is no longer supported',\n          {\n            borderColor: primary.borderColor,\n            backgroundColor: primary.backgroundColor,\n          },\n        );\n\n      if (secondary?.borderColor && secondary.textColor && secondary.borderColor !== secondary.textColor)\n        error(\"styleToTheme: secondary button's border color is now always equal to text color\", {\n          borderColor: secondary.borderColor,\n          textColor: secondary.textColor,\n        });\n\n      if (primary?.borderRadius !== secondary?.borderRadius)\n        error('styleToTheme: All buttons must use the same border-radius', {\n          primaryRadius: primary?.borderRadius,\n          secondaryRadius: secondary?.borderRadius,\n        });\n    });\n\n    // Set background and text colors\n    Object.assign(theme, {\n      primary: primary?.backgroundColor,\n      'primary-foreground': primary?.textColor,\n\n      secondary: secondary?.backgroundColor,\n      'secondary-foreground': secondary?.textColor,\n    } satisfies Partial<Theme>);\n\n    // Set border radius\n    if (primary?.borderRadius || secondary?.borderRadius) {\n      // Conflicts between primary and secondary border radius is handled above\n      const baseRadius = updateLength(primary?.borderRadius, 0.5) ?? updateLength(secondary?.borderRadius, 0.5);\n\n      if (theme['rounded-base']) {\n        if (theme['rounded-base'] !== baseRadius) {\n          theme['button-radius'] = primary?.borderRadius;\n        }\n      } else {\n        theme['rounded-base'] = baseRadius;\n      }\n    }\n  }\n\n  if (inputs) {\n    const { backgroundColor, textColor, placeholderColor, borderColor, borderRadius, ...expectEmpty } = inputs;\n    RUN_IN_DEV(() => {\n      if (Object.keys(expectEmpty).length > 0) warn('styleToTheme: Unrecognized style.buttons properties', expectEmpty);\n\n      if (backgroundColor && theme.background && theme.background !== backgroundColor)\n        error('styleToTheme: Input now always use the container background', {\n          inputBackground: backgroundColor,\n          containerBackground: theme.background,\n        });\n    });\n\n    Object.assign(theme, {\n      foreground: textColor,\n      input: borderColor,\n      'muted-foreground': placeholderColor,\n    } satisfies Partial<Theme>);\n\n    // Set border radius\n    if (theme['rounded-base']) {\n      if (theme['rounded-base'] !== borderRadius) {\n        theme['input-radius'] = borderRadius;\n      }\n    } else {\n      theme['rounded-base'] = borderRadius;\n    }\n  }\n\n  // presentation.options mapping\n  // ------------------------------------------------\n\n  options.hideHeaderText = hideHeaderText;\n  if (logo?.logoImageUrl) {\n    options.logo = {\n      url: logo.logoImageUrl,\n      alt: '',\n    };\n\n    RUN_IN_DEV(() => {\n      logger.warn('styleToTheme: Please set options.logo.alt for the logo alt text for accessibility');\n    });\n  }\n\n  return { theme: removeEmptyValues(theme), options: removeEmptyValues(options) };\n}\n\nfunction removeEmptyValues<T extends Record<string, unknown>>(obj: T): T {\n  return Object.fromEntries(Object.entries(obj).filter(([, value]) => value != null && value !== '')) as T;\n}\n\nfunction updateLength(length: string | undefined, factor: number): string | undefined {\n  if (!length) return length;\n\n  // Loose check that this is a numeric and not keyword value\n  const value = parseFloat(length);\n  if (Number.isNaN(value)) return length;\n\n  return `calc(${length} * ${factor})`;\n}\n"],"names":["styleToTheme","styleConfig","silent","warn","logger","error","theme","options","colors","container","inputs","hideHeaderText","buttons","logo","fontFamily","outerEmpty","RUN_IN_DEV","Object","keys","length","primary","secondary","success","warning","accent","expectEmpty","assign","destructive","backgroundColor","borderColor","width","borderRadius","background","border","updateLength","disabled","textColor","primaryRadius","secondaryRadius","baseRadius","placeholderColor","inputBackground","containerBackground","foreground","input","logoImageUrl","url","alt","removeEmptyValues","obj","fromEntries","entries","filter","value","factor","parseFloat","Number","isNaN"],"mappings":";;;AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;IA6BO,SAASA,YAAAA,CACdC,WAAwB,EACxB,EAAEC,MAAM,EAAwB,GAAG,EAAE,EAAA;AAKrC,IAAA,MAAMC,OAAOD,MAAAA,GACT,IAAA;;AAEA,IAAA,CAAA,GACAE,OAAOD,IAAI;AACf,IAAA,MAAME,QAAQH,MAAAA,GACV,IAAA;;AAEA,IAAA,CAAA,GACAE,OAAOC,KAAK;AAEhB,IAAA,MAAMC,QAAwB,EAAC;AAC/B,IAAA,MAAMC,UAAwC,EAAC;AAE/C,IAAA,MAAM,EAAEC,MAAM,EAAEC,SAAS,EAAEC,MAAM,EAAEC,cAAc,EAAEC,OAAO,EAAEC,IAAI,EAAEC,UAAU,EAAE,GAAGC,YAAY,GAAGd,WAAAA;;;IAIhGe,UAAAA,CAAW,IAAA;AACTb,QAAAA,IAAAA,CACE,qGACE,wGAAA,GACA,2BAAA,CAAA;QAGJ,IAAIc,MAAAA,CAAOC,IAAI,CAACH,UAAAA,CAAAA,CAAYI,MAAM,GAAG,CAAA,EAAGhB,KAAK,6CAAA,EAA+CY,UAAAA,CAAAA;AAC9F,IAAA,CAAA,CAAA;IAEAT,KAAK,CAAC,cAAc,GAAGQ,UAAAA;AAEvB,IAAA,IAAIN,MAAAA,EAAQ;AACV,QAAA,MAAM,EAAEY,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAEC,OAAO,EAAEC,MAAM,EAAEnB,KAAK,EAAE,GAAGoB,aAAa,GAAGjB,MAAAA;QAChFQ,UAAAA,CAAW,IAAA;YACT,IAAIC,MAAAA,CAAOC,IAAI,CAACO,WAAAA,CAAAA,CAAaN,MAAM,GAAG,CAAA,EAAGhB,KAAK,oDAAA,EAAsDsB,WAAAA,CAAAA;AACtG,QAAA,CAAA,CAAA;QAEAR,MAAAA,CAAOS,MAAM,CAACpB,KAAAA,EAAO;AACnBc,YAAAA,OAAAA;AACAC,YAAAA,SAAAA;AACAC,YAAAA,OAAAA;AACAC,YAAAA,OAAAA;AACAC,YAAAA,MAAAA;YACAG,WAAAA,EAAatB;AACf,SAAA,CAAA;AACF,IAAA;AAEA,IAAA,IAAII,SAAAA,EAAW;QACb,MAAM,EAAEmB,eAAe,EAAEC,WAAW,EAAEC,KAAK,EAAEC,YAAY,EAAE,GAAGN,WAAAA,EAAa,GAAGhB,SAAAA;QAE9EO,UAAAA,CAAW,IAAA;YACT,IAAIC,MAAAA,CAAOC,IAAI,CAACO,WAAAA,CAAAA,CAAaN,MAAM,GAAG,CAAA,EACpChB,KAAK,uDAAA,EAAyDsB,WAAAA,CAAAA;AAClE,QAAA,CAAA,CAAA;QAEAR,MAAAA,CAAOS,MAAM,CAACpB,KAAAA,EAAO;YACnB0B,UAAAA,EAAYJ,eAAAA;YACZK,MAAAA,EAAQJ,WAAAA;YACR,iBAAA,EAAmBC,KAAAA;;AAEnB,YAAA,cAAA,EAAgBI,aAAaH,YAAAA,EAAc,IAAA;AAC7C,SAAA,CAAA;AACF,IAAA;AAEA,IAAA,IAAInB,OAAAA,EAAS;QACX,MAAM,EAAEQ,OAAO,EAAEC,SAAS,EAAEc,QAAQ,EAAE,GAAGV,WAAAA,EAAa,GAAGb,OAAAA;QAEzDI,UAAAA,CAAW,IAAA;YACT,IAAIC,MAAAA,CAAOC,IAAI,CAACO,WAAAA,CAAAA,CAAaN,MAAM,GAAG,CAAA,EAAGhB,KAAK,qDAAA,EAAuDsB,WAAAA,CAAAA;YAErG,IAAIU,QAAAA,IAAYlB,OAAOC,IAAI,CAACiB,UAAUhB,MAAM,GAAG,CAAA,EAC7ChB,IAAAA,CAAK,uDAAA,EAAyD;AAAEgC,gBAAAA;AAAS,aAAA,CAAA;AAE3E,YAAA,IAAIf,OAAAA,EAASS,WAAAA,IAAeT,OAAAA,EAASQ,eAAAA,IAAmBR,OAAAA,CAAQS,WAAW,KAAKT,OAAAA,CAAQQ,eAAe,EACrGvB,KAAAA,CACE,uFAAA,GACE,+CAAA,EACF;AACEwB,gBAAAA,WAAAA,EAAaT,QAAQS,WAAW;AAChCD,gBAAAA,eAAAA,EAAiBR,QAAQQ;AAC3B,aAAA,CAAA;AAGJ,YAAA,IAAIP,SAAAA,EAAWQ,WAAAA,IAAeR,SAAAA,CAAUe,SAAS,IAAIf,SAAAA,CAAUQ,WAAW,KAAKR,SAAAA,CAAUe,SAAS,EAChG/B,KAAAA,CAAM,iFAAA,EAAmF;AACvFwB,gBAAAA,WAAAA,EAAaR,UAAUQ,WAAW;AAClCO,gBAAAA,SAAAA,EAAWf,UAAUe;AACvB,aAAA,CAAA;AAEF,YAAA,IAAIhB,OAAAA,EAASW,YAAAA,KAAiBV,SAAAA,EAAWU,YAAAA,EACvC1B,MAAM,2DAAA,EAA6D;AACjEgC,gBAAAA,aAAAA,EAAejB,OAAAA,EAASW,YAAAA;AACxBO,gBAAAA,eAAAA,EAAiBjB,SAAAA,EAAWU;AAC9B,aAAA,CAAA;AACJ,QAAA,CAAA,CAAA;;QAGAd,MAAAA,CAAOS,MAAM,CAACpB,KAAAA,EAAO;AACnBc,YAAAA,OAAAA,EAASA,OAAAA,EAASQ,eAAAA;AAClB,YAAA,oBAAA,EAAsBR,OAAAA,EAASgB,SAAAA;AAE/Bf,YAAAA,SAAAA,EAAWA,SAAAA,EAAWO,eAAAA;AACtB,YAAA,sBAAA,EAAwBP,SAAAA,EAAWe;AACrC,SAAA,CAAA;;QAGA,IAAIhB,OAAAA,EAASW,YAAAA,IAAgBV,SAAAA,EAAWU,YAAAA,EAAc;;AAEpD,YAAA,MAAMQ,aAAaL,YAAAA,CAAad,OAAAA,EAASW,cAAc,GAAA,CAAA,IAAQG,YAAAA,CAAab,WAAWU,YAAAA,EAAc,GAAA,CAAA;YAErG,IAAIzB,KAAK,CAAC,cAAA,CAAe,EAAE;AACzB,gBAAA,IAAIA,KAAK,CAAC,cAAA,CAAe,KAAKiC,UAAAA,EAAY;oBACxCjC,KAAK,CAAC,eAAA,CAAgB,GAAGc,OAAAA,EAASW,YAAAA;AACpC,gBAAA;YACF,CAAA,MAAO;gBACLzB,KAAK,CAAC,eAAe,GAAGiC,UAAAA;AAC1B,YAAA;AACF,QAAA;AACF,IAAA;AAEA,IAAA,IAAI7B,MAAAA,EAAQ;AACV,QAAA,MAAM,EAAEkB,eAAe,EAAEQ,SAAS,EAAEI,gBAAgB,EAAEX,WAAW,EAAEE,YAAY,EAAE,GAAGN,aAAa,GAAGf,MAAAA;QACpGM,UAAAA,CAAW,IAAA;YACT,IAAIC,MAAAA,CAAOC,IAAI,CAACO,WAAAA,CAAAA,CAAaN,MAAM,GAAG,CAAA,EAAGhB,KAAK,qDAAA,EAAuDsB,WAAAA,CAAAA;YAErG,IAAIG,eAAAA,IAAmBtB,MAAM0B,UAAU,IAAI1B,MAAM0B,UAAU,KAAKJ,eAAAA,EAC9DvB,KAAAA,CAAM,6DAAA,EAA+D;gBACnEoC,eAAAA,EAAiBb,eAAAA;AACjBc,gBAAAA,mBAAAA,EAAqBpC,MAAM0B;AAC7B,aAAA,CAAA;AACJ,QAAA,CAAA,CAAA;QAEAf,MAAAA,CAAOS,MAAM,CAACpB,KAAAA,EAAO;YACnBqC,UAAAA,EAAYP,SAAAA;YACZQ,KAAAA,EAAOf,WAAAA;YACP,kBAAA,EAAoBW;AACtB,SAAA,CAAA;;QAGA,IAAIlC,KAAK,CAAC,cAAA,CAAe,EAAE;AACzB,YAAA,IAAIA,KAAK,CAAC,cAAA,CAAe,KAAKyB,YAAAA,EAAc;gBAC1CzB,KAAK,CAAC,eAAe,GAAGyB,YAAAA;AAC1B,YAAA;QACF,CAAA,MAAO;YACLzB,KAAK,CAAC,eAAe,GAAGyB,YAAAA;AAC1B,QAAA;AACF,IAAA;;;AAKAxB,IAAAA,OAAAA,CAAQI,cAAc,GAAGA,cAAAA;AACzB,IAAA,IAAIE,MAAMgC,YAAAA,EAAc;AACtBtC,QAAAA,OAAAA,CAAQM,IAAI,GAAG;AACbiC,YAAAA,GAAAA,EAAKjC,KAAKgC,YAAY;YACtBE,GAAAA,EAAK;AACP,SAAA;QAEA/B,UAAAA,CAAW,IAAA;AACTZ,YAAAA,MAAAA,CAAOD,IAAI,CAAC,mFAAA,CAAA;AACd,QAAA,CAAA,CAAA;AACF,IAAA;IAEA,OAAO;AAAEG,QAAAA,KAAAA,EAAO0C,iBAAAA,CAAkB1C,KAAAA,CAAAA;AAAQC,QAAAA,OAAAA,EAASyC,iBAAAA,CAAkBzC,OAAAA;AAAS,KAAA;AAChF;AAEA,SAASyC,kBAAqDC,GAAM,EAAA;AAClE,IAAA,OAAOhC,MAAAA,CAAOiC,WAAW,CAACjC,MAAAA,CAAOkC,OAAO,CAACF,GAAAA,CAAAA,CAAKG,MAAM,CAAC,CAAC,GAAGC,KAAAA,CAAM,GAAKA,KAAAA,IAAS,QAAQA,KAAAA,KAAU,EAAA,CAAA,CAAA;AACjG;AAEA,SAASnB,YAAAA,CAAaf,MAA0B,EAAEmC,MAAc,EAAA;IAC9D,IAAI,CAACnC,QAAQ,OAAOA,MAAAA;;AAGpB,IAAA,MAAMkC,QAAQE,UAAAA,CAAWpC,MAAAA,CAAAA;AACzB,IAAA,IAAIqC,MAAAA,CAAOC,KAAK,CAACJ,KAAAA,CAAAA,EAAQ,OAAOlC,MAAAA;IAEhC,OAAO,CAAC,KAAK,EAAEA,MAAAA,CAAO,GAAG,EAAEmC,MAAAA,CAAO,CAAC,CAAC;AACtC;;;;"}