{"version":3,"file":"index-RMoTs0Ce.mjs","sources":["../../admin/src/pluginId.ts","../../admin/src/components/Initializer.tsx","../../admin/src/components/PluginIcon.tsx","../../admin/src/utils/getLocaleFromUrl.ts","../../admin/src/utils/getTranslation.ts","../../admin/src/components/LLMButton.tsx","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'strapi-llm-translator';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n  setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n  const ref = useRef(setPlugin);\n\n  useEffect(() => {\n    ref.current(PLUGIN_ID);\n  }, []);\n\n  return null;\n};\n\nexport { Initializer };\n","import { SVGProps } from 'react';\nimport { DefaultTheme, useTheme } from 'styled-components';\n\ndeclare module 'styled-components' {\n  export interface DefaultTheme {\n    colors: {\n      [key: string]: string;\n    };\n  }\n}\n\ninterface IconProps extends Omit<SVGProps<SVGSVGElement>, 'fill' | 'stroke'> {\n  /**\n   * @default \"currentColor\"\n   */\n  fill?: keyof DefaultTheme['colors'] | (string & {});\n  stroke?: keyof DefaultTheme['colors'] | (string & {});\n}\n\nconst PluginIcon = ({\n  fill: fillProp = 'currentColor',\n  stroke: strokeProp,\n  ...props\n}: IconProps) => {\n  const { colors } = useTheme();\n  const fill = String(\n    fillProp && fillProp in colors ? colors[fillProp as keyof DefaultTheme['colors']] : fillProp\n  );\n\n  const stroke =\n    strokeProp && strokeProp in colors\n      ? String(colors[strokeProp as keyof DefaultTheme['colors']])\n      : strokeProp\n        ? String(strokeProp)\n        : undefined;\n\n  return (\n    <svg\n      width=\"32\"\n      height=\"32\"\n      viewBox=\"0 0 32 32\"\n      fill={fill}\n      stroke={stroke}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <path\n        d=\"M28.414 9.171L22.829 3.585C22.6433 3.3992 22.4228 3.25181 22.1801 3.15125C21.9373 3.05069 21.6772 2.99893 21.4145 2.99893C21.1518 2.99893 20.8917 3.05069 20.6489 3.15125C20.4062 3.25181 20.1857 3.3992 20 3.585L4.586 19C4.39938 19.185 4.25145 19.4053 4.15084 19.6481C4.05023 19.8909 3.99896 20.1512 4 20.414V26C4 26.5304 4.21071 27.0391 4.58579 27.4142C4.96086 27.7893 5.46957 28 6 28H11.586C11.8488 28.001 12.1091 27.9498 12.3519 27.8492C12.5947 27.7486 12.815 27.6006 13 27.414L28.414 12C28.5998 11.8143 28.7472 11.5938 28.8478 11.3511C28.9483 11.1084 29.0001 10.8482 29.0001 10.5855C29.0001 10.3228 28.9483 10.0627 28.8478 9.81995C28.7472 9.57725 28.5998 9.35673 28.414 9.171ZM24 13.585L18.414 8L21.414 5L27 10.585L24 13.585Z\"\n        fill=\"currentColor\"\n      />\n      <path\n        d=\"M4 12H2C1.73478 12 1.48043 11.8946 1.29289 11.7071C1.10536 11.5196 1 11.2652 1 11C1 10.7348 1.10536 10.4804 1.29289 10.2929C1.48043 10.1054 1.73478 10 2 10H4V8C4 7.73478 4.10536 7.48043 4.29289 7.29289C4.48043 7.10536 4.73478 7 5 7C5.26522 7 5.51957 7.10536 5.70711 7.29289C5.89464 7.48043 6 7.73478 6 8V10H8C8.26522 10 8.51957 10.1054 8.70711 10.2929C8.89464 10.4804 9 10.7348 9 11C9 11.2652 8.89464 11.5196 8.70711 11.7071C8.51957 11.8946 8.26522 12 8 12H6V14C6 14.2652 5.89464 14.5196 5.70711 14.7071C5.51957 14.8946 5.26522 15 5 15C4.73478 15 4.48043 14.8946 4.29289 14.7071C4.10536 14.5196 4 14.2652 4 14V12Z\"\n        fill=\"currentColor\"\n      />\n      <path\n        d=\"M9 2H10C10.2652 2 10.5196 2.10536 10.7071 2.29289C10.8946 2.48043 11 2.73478 11 3C11 3.26522 10.8946 3.51957 10.7071 3.70711C10.5196 3.89464 10.2652 4 10 4H9V5C9 5.26522 8.89464 5.51957 8.70711 5.70711C8.51957 5.89464 8.26522 6 8 6C7.73478 6 7.48043 5.89464 7.29289 5.70711C7.10536 5.51957 7 5.26522 7 5V4H6C5.73478 4 5.48043 3.89464 5.29289 3.70711C5.10536 3.51957 5 3.26522 5 3C5 2.73478 5.10536 2.48043 5.29289 2.29289C5.48043 2.10536 5.73478 2 6 2H7V1C7 0.734784 7.10536 0.48043 7.29289 0.292893C7.48043 0.105357 7.73478 0 8 0C8.26522 0 8.51957 0.105357 8.70711 0.292893C8.89464 0.48043 9 0.734784 9 1V2Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n};\n\nexport { PluginIcon };\n","export const getLocaleFromUrl = (): string => {\n  try {\n    // Works for both main URL and hash fragment\n    const params = new URL(window.location.href).searchParams;\n    return params.get('plugins[i18n][locale]') || 'en';\n  } catch {\n    return 'en';\n  }\n};\n","import { PLUGIN_ID } from '../pluginId';\n\nconst getTranslation = (id: string) => `${PLUGIN_ID}.${id}`;\n\nexport { getTranslation };\n","import { useIntl } from 'react-intl';\nimport { CheckCircle, Magic, WarningCircle } from '@strapi/icons';\nimport { Button } from '@strapi/design-system';\nimport {\n  unstable_useContentManagerContext as useContentManagerContext,\n  useFetchClient,\n  useNotification,\n} from '@strapi/strapi/admin';\nimport { useState } from 'react';\n\nimport {\n  ExtendedContentType,\n  Form,\n  LLMGenerateRequestBody,\n  TranslationResponse,\n  TranslatorButtonState,\n} from 'custom';\nimport { getLocaleFromUrl } from '../utils/getLocaleFromUrl';\nimport { getTranslation } from '../utils/getTranslation';\nimport { PLUGIN_ID } from '../../src/pluginId';\n\nconst LLMButton = () => {\n  const [loading, setIsLoading] = useState(false);\n  const [success, setSuccess] = useState(false);\n  const [error, setError] = useState(false);\n\n  const { formatMessage } = useIntl();\n  const { form, contentType, components } = useContentManagerContext();\n  const { post } = useFetchClient();\n\n  const { toggleNotification } = useNotification();\n\n  const isI18nEnabled =\n    (contentType as ExtendedContentType)?.pluginOptions?.i18n?.localized || false;\n  const { values, onChange } = form as Form;\n\n  if (!isI18nEnabled) {\n    return null;\n  }\n\n  const currentLocale = getLocaleFromUrl();\n\n  // Button state: loading, success, error, idle\n  const getButtonState = (): TranslatorButtonState => {\n    if (loading) {\n      return {\n        variant: 'secondary',\n        icon: Magic,\n        loading: true,\n        disabled: true,\n        tooltip: formatMessage({\n          id: getTranslation('button.tooltip.loading'),\n          defaultMessage: 'Content is being translated',\n        }),\n        title: formatMessage({\n          id: getTranslation('button.label.loading'),\n          defaultMessage: 'Translating content...',\n        }),\n      };\n    }\n    if (success) {\n      return {\n        variant: 'success',\n        icon: CheckCircle,\n        loading: false,\n        disabled: true,\n        tooltip: formatMessage({\n          id: getTranslation('button.tooltip.success'),\n          defaultMessage: 'Content has been translated successfully',\n        }),\n        title: formatMessage({\n          id: getTranslation('button.label.success'),\n          defaultMessage: 'Translation completed',\n        }),\n      };\n    }\n    if (error) {\n      return {\n        variant: 'danger',\n        icon: WarningCircle,\n        loading: false,\n        disabled: false,\n        tooltip: formatMessage({\n          id: getTranslation('button.tooltip.error'),\n          defaultMessage: 'Translation failed. Click to try again',\n        }),\n        title: formatMessage({\n          id: getTranslation('button.label.error'),\n          defaultMessage: 'Translation failed',\n        }),\n      };\n    }\n    return {\n      variant: 'secondary',\n      icon: Magic,\n      loading: false,\n      disabled: false,\n      tooltip: formatMessage({\n        id: getTranslation('button.tooltip.idle'),\n        defaultMessage: 'Translate content using AI',\n      }),\n      title: formatMessage({\n        id: getTranslation('button.label.idle'),\n        defaultMessage: 'Translate with AI',\n      }),\n    };\n  };\n\n  const resetState = () => {\n    setSuccess(false);\n    setError(false);\n    setIsLoading(false);\n  };\n\n  const handleLLMRequest = async () => {\n    try {\n      resetState();\n      setIsLoading(true);\n\n      const dataToSend: LLMGenerateRequestBody = {\n        contentType,\n        fields: values,\n        components,\n        targetLanguage: currentLocale,\n      };\n\n      const { data: response } = await post<TranslationResponse>(`/${PLUGIN_ID}/generate`, {\n        ...dataToSend,\n      });\n\n      if (!response.meta.ok) {\n        throw new Error(response.meta.message);\n      }\n\n      // Update the form with translated content\n      if (response.data) {\n        Object.entries(response.data).forEach(([key, value]) => {\n          if (values[key] !== undefined) {\n            onChange({ target: { name: key, value } });\n          }\n        });\n        setSuccess(true);\n        toggleNotification({\n          type: 'success',\n          message: formatMessage({\n            id: getTranslation('notification.success'),\n            defaultMessage: 'Translation completed successfully',\n          }),\n        });\n      }\n    } catch (error) {\n      setError(true);\n      toggleNotification({\n        type: 'danger',\n        message: formatMessage(\n          {\n            id: `${getTranslation('notification.error')}: ${error}`,\n            defaultMessage: `Error during translation: ${error}`,\n          },\n          { error: (error as Error).message }\n        ),\n      });\n    } finally {\n      setIsLoading(false);\n    }\n  };\n\n  const buttonState = getButtonState();\n\n  return (\n    <Button\n      variant={buttonState.variant}\n      startIcon={<buttonState.icon />}\n      fullWidth\n      loading={buttonState.loading}\n      onClick={handleLLMRequest}\n      disabled={!isI18nEnabled || buttonState.disabled}\n      title={buttonState.tooltip}\n    >\n      {buttonState.title}\n    </Button>\n  );\n};\n\nexport default LLMButton;\n","// import { getTranslation } from './utils/getTranslation';\nimport { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport { PluginIcon } from './components/PluginIcon';\nimport LLMButton from './components/LLMButton';\n\nexport default {\n  register(app: any) {\n    app.addMenuLink({\n      to: `plugins/${PLUGIN_ID}`,\n      icon: PluginIcon,\n      intlLabel: {\n        id: `${PLUGIN_ID}.plugin.name`,\n        defaultMessage: PLUGIN_ID,\n      },\n      Component: async () => {\n        const { App } = await import('./pages/App');\n\n        return App;\n      },\n    });\n\n    app.registerPlugin({\n      id: PLUGIN_ID,\n      initializer: Initializer,\n      isReady: false,\n      name: PLUGIN_ID,\n    });\n  },\n\n  bootstrap(app: any) {\n    // Adds the Button to the Entry Area on the right\n    app.getPlugin('content-manager').injectComponent('editView', 'right-links', {\n      name: 'llm-assistant-button',\n      Component: LLMButton,\n    });\n  },\n\n  async registerTrads({ locales }: { locales: string[] }) {\n    return Promise.all(\n      locales.map(async (locale) => {\n        try {\n          const { default: data } = await import(`./translations/${locale}.json`);\n\n          return { data, locale };\n        } catch {\n          return { data: {}, locale };\n        }\n      })\n    );\n  },\n};\n"],"names":["useContentManagerContext","error"],"mappings":"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"}