@intlayer/design-system 8.10.1 → 8.11.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.
Files changed (215) hide show
  1. package/dist/esm/api/hooks/ai.mjs +66 -0
  2. package/dist/esm/api/hooks/ai.mjs.map +1 -0
  3. package/dist/esm/api/hooks/audit.mjs +34 -0
  4. package/dist/esm/api/hooks/audit.mjs.map +1 -0
  5. package/dist/esm/api/hooks/auth.mjs +217 -0
  6. package/dist/esm/api/hooks/auth.mjs.map +1 -0
  7. package/dist/esm/api/hooks/bitbucket.mjs +39 -0
  8. package/dist/esm/api/hooks/bitbucket.mjs.map +1 -0
  9. package/dist/esm/api/hooks/dictionary.mjs +105 -0
  10. package/dist/esm/api/hooks/dictionary.mjs.map +1 -0
  11. package/dist/esm/api/hooks/discussions.mjs +37 -0
  12. package/dist/esm/api/hooks/discussions.mjs.map +1 -0
  13. package/dist/esm/api/hooks/editor.mjs +24 -0
  14. package/dist/esm/api/hooks/editor.mjs.map +1 -0
  15. package/dist/esm/api/hooks/github.mjs +54 -0
  16. package/dist/esm/api/hooks/github.mjs.map +1 -0
  17. package/dist/esm/api/hooks/gitlab.mjs +43 -0
  18. package/dist/esm/api/hooks/gitlab.mjs.map +1 -0
  19. package/dist/esm/api/hooks/newsletter.mjs +31 -0
  20. package/dist/esm/api/hooks/newsletter.mjs.map +1 -0
  21. package/dist/esm/api/hooks/organization.mjs +123 -0
  22. package/dist/esm/api/hooks/organization.mjs.map +1 -0
  23. package/dist/esm/api/hooks/project.mjs +187 -0
  24. package/dist/esm/api/hooks/project.mjs.map +1 -0
  25. package/dist/esm/api/hooks/reviewer.mjs +288 -0
  26. package/dist/esm/api/hooks/reviewer.mjs.map +1 -0
  27. package/dist/esm/api/hooks/search.mjs +18 -0
  28. package/dist/esm/api/hooks/search.mjs.map +1 -0
  29. package/dist/esm/api/hooks/showcaseProject.mjs +95 -0
  30. package/dist/esm/api/hooks/showcaseProject.mjs.map +1 -0
  31. package/dist/esm/api/hooks/stripe.mjs +261 -0
  32. package/dist/esm/api/hooks/stripe.mjs.map +1 -0
  33. package/dist/esm/api/hooks/tag.mjs +45 -0
  34. package/dist/esm/api/hooks/tag.mjs.map +1 -0
  35. package/dist/esm/api/hooks/translate.mjs +47 -0
  36. package/dist/esm/api/hooks/translate.mjs.map +1 -0
  37. package/dist/esm/api/hooks/user.mjs +58 -0
  38. package/dist/esm/api/hooks/user.mjs.map +1 -0
  39. package/dist/esm/api/hooks/utils.mjs +30 -0
  40. package/dist/esm/api/hooks/utils.mjs.map +1 -0
  41. package/dist/esm/api/index.mjs +26 -0
  42. package/dist/esm/{hooks → api}/useAuth/useAuth.mjs +1 -1
  43. package/dist/esm/api/useAuth/useAuth.mjs.map +1 -0
  44. package/dist/esm/{hooks → api}/useAuth/useOAuth2.mjs +3 -3
  45. package/dist/esm/api/useAuth/useOAuth2.mjs.map +1 -0
  46. package/dist/esm/{hooks → api}/useAuth/useSession.mjs +3 -4
  47. package/dist/esm/api/useAuth/useSession.mjs.map +1 -0
  48. package/dist/esm/api/useIntlayerAPI.mjs +123 -0
  49. package/dist/esm/api/useIntlayerAPI.mjs.map +1 -0
  50. package/dist/esm/{hooks → api}/useUser/index.mjs +2 -2
  51. package/dist/esm/api/useUser/index.mjs.map +1 -0
  52. package/dist/esm/components/Badge/index.mjs +1 -3
  53. package/dist/esm/components/Badge/index.mjs.map +1 -1
  54. package/dist/esm/components/Breadcrumb/index.mjs +0 -1
  55. package/dist/esm/components/Breadcrumb/index.mjs.map +1 -1
  56. package/dist/esm/components/Button/Button.mjs +3 -5
  57. package/dist/esm/components/Button/Button.mjs.map +1 -1
  58. package/dist/esm/components/Carousel/index.mjs +3 -3
  59. package/dist/esm/components/Carousel/index.mjs.map +1 -1
  60. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
  61. package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs.map +1 -1
  62. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +1 -1
  63. package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
  64. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +3 -2
  65. package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs.map +1 -1
  66. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +4 -2
  67. package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs.map +1 -1
  68. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -2
  69. package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs.map +1 -1
  70. package/dist/esm/components/ExpandCollapse/ExpandCollapse.mjs +2 -2
  71. package/dist/esm/components/ExpandCollapse/ExpandCollapse.mjs.map +1 -1
  72. package/dist/esm/components/IDE/FileList.mjs +1 -1
  73. package/dist/esm/components/IDE/FileList.mjs.map +1 -1
  74. package/dist/esm/components/IDE/IDE.mjs +1 -1
  75. package/dist/esm/components/IDE/IDE.mjs.map +1 -1
  76. package/dist/esm/components/Input/Checkbox.mjs +1 -3
  77. package/dist/esm/components/Input/Checkbox.mjs.map +1 -1
  78. package/dist/esm/components/Label/index.mjs +2 -2
  79. package/dist/esm/components/Label/index.mjs.map +1 -1
  80. package/dist/esm/components/LanguageBackground/LanguageSection.mjs +8 -6
  81. package/dist/esm/components/LanguageBackground/LanguageSection.mjs.map +1 -1
  82. package/dist/esm/components/LanguageBackground/index.mjs +13 -5
  83. package/dist/esm/components/LanguageBackground/index.mjs.map +1 -1
  84. package/dist/esm/components/Link/Link.mjs +0 -7
  85. package/dist/esm/components/Link/Link.mjs.map +1 -1
  86. package/dist/esm/components/Loader/spinner.mjs +1 -1
  87. package/dist/esm/components/Loader/spinner.mjs.map +1 -1
  88. package/dist/esm/components/Pagination/Pagination.mjs +1 -2
  89. package/dist/esm/components/Pagination/Pagination.mjs.map +1 -1
  90. package/dist/esm/components/Popover/dynamic.mjs +2 -2
  91. package/dist/esm/components/Popover/dynamic.mjs.map +1 -1
  92. package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +3 -5
  93. package/dist/esm/components/SwitchSelector/SwitchSelector.mjs.map +1 -1
  94. package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs +3 -3
  95. package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs.map +1 -1
  96. package/dist/esm/components/TabSelector/TabSelector.mjs +3 -3
  97. package/dist/esm/components/TabSelector/TabSelector.mjs.map +1 -1
  98. package/dist/esm/components/Tag/index.mjs +1 -1
  99. package/dist/esm/components/Tag/index.mjs.map +1 -1
  100. package/dist/esm/components/Terminal/Terminal.mjs +1 -1
  101. package/dist/esm/components/Terminal/Terminal.mjs.map +1 -1
  102. package/dist/esm/components/TextArea/AutoSizeTextArea.mjs +2 -2
  103. package/dist/esm/components/TextArea/AutoSizeTextArea.mjs.map +1 -1
  104. package/dist/esm/components/TextArea/ContentEditableTextArea.mjs +3 -3
  105. package/dist/esm/components/TextArea/ContentEditableTextArea.mjs.map +1 -1
  106. package/dist/esm/components/Toaster/Toast.mjs +3 -3
  107. package/dist/esm/components/Toaster/Toast.mjs.map +1 -1
  108. package/dist/esm/components/WithResizer/index.mjs +7 -2
  109. package/dist/esm/components/WithResizer/index.mjs.map +1 -1
  110. package/dist/esm/hooks/index.mjs +1 -7
  111. package/dist/esm/libs/auth.mjs +1 -1
  112. package/dist/esm/routes.mjs +23 -1
  113. package/dist/esm/routes.mjs.map +1 -1
  114. package/dist/types/api/hooks/ai.d.ts +12 -0
  115. package/dist/types/api/hooks/ai.d.ts.map +1 -0
  116. package/dist/types/api/hooks/audit.d.ts +10 -0
  117. package/dist/types/api/hooks/audit.d.ts.map +1 -0
  118. package/dist/types/api/hooks/auth.d.ts +29 -0
  119. package/dist/types/api/hooks/auth.d.ts.map +1 -0
  120. package/dist/types/api/hooks/bitbucket.d.ts +8 -0
  121. package/dist/types/api/hooks/bitbucket.d.ts.map +1 -0
  122. package/dist/types/api/hooks/dictionary.d.ts +15 -0
  123. package/dist/types/api/hooks/dictionary.d.ts.map +1 -0
  124. package/dist/types/api/hooks/discussions.d.ts +8 -0
  125. package/dist/types/api/hooks/discussions.d.ts.map +1 -0
  126. package/dist/types/api/hooks/editor.d.ts +6 -0
  127. package/dist/types/api/hooks/editor.d.ts.map +1 -0
  128. package/dist/types/api/hooks/github.d.ts +12 -0
  129. package/dist/types/api/hooks/github.d.ts.map +1 -0
  130. package/dist/types/api/hooks/gitlab.d.ts +8 -0
  131. package/dist/types/api/hooks/gitlab.d.ts.map +1 -0
  132. package/dist/types/api/hooks/newsletter.d.ts +7 -0
  133. package/dist/types/api/hooks/newsletter.d.ts.map +1 -0
  134. package/dist/types/api/hooks/organization.d.ts +16 -0
  135. package/dist/types/api/hooks/organization.d.ts.map +1 -0
  136. package/dist/types/api/hooks/project.d.ts +23 -0
  137. package/dist/types/api/hooks/project.d.ts.map +1 -0
  138. package/dist/types/api/hooks/reviewer.d.ts +39 -0
  139. package/dist/types/api/hooks/reviewer.d.ts.map +1 -0
  140. package/dist/types/api/hooks/search.d.ts +7 -0
  141. package/dist/types/api/hooks/search.d.ts.map +1 -0
  142. package/dist/types/api/hooks/showcaseProject.d.ts +16 -0
  143. package/dist/types/api/hooks/showcaseProject.d.ts.map +1 -0
  144. package/dist/types/api/hooks/stripe.d.ts +33 -0
  145. package/dist/types/api/hooks/stripe.d.ts.map +1 -0
  146. package/dist/types/api/hooks/tag.d.ts +11 -0
  147. package/dist/types/api/hooks/tag.d.ts.map +1 -0
  148. package/dist/types/api/hooks/translate.d.ts +8 -0
  149. package/dist/types/api/hooks/translate.d.ts.map +1 -0
  150. package/dist/types/api/hooks/user.d.ts +13 -0
  151. package/dist/types/api/hooks/user.d.ts.map +1 -0
  152. package/dist/types/api/hooks/utils.d.ts +23 -0
  153. package/dist/types/api/hooks/utils.d.ts.map +1 -0
  154. package/dist/types/api/index.d.ts +25 -0
  155. package/dist/types/{hooks → api}/useAuth/useAuth.d.ts +1 -1
  156. package/dist/types/api/useAuth/useAuth.d.ts.map +1 -0
  157. package/dist/types/{hooks → api}/useAuth/useOAuth2.d.ts +1 -1
  158. package/dist/types/api/useAuth/useOAuth2.d.ts.map +1 -0
  159. package/dist/types/{hooks → api}/useAuth/useSession.d.ts +1 -1
  160. package/dist/types/api/useAuth/useSession.d.ts.map +1 -0
  161. package/dist/types/api/useIntlayerAPI.d.ts +297 -0
  162. package/dist/types/api/useIntlayerAPI.d.ts.map +1 -0
  163. package/dist/types/{hooks → api}/useUser/index.d.ts +1 -1
  164. package/dist/types/api/useUser/index.d.ts.map +1 -0
  165. package/dist/types/components/Badge/index.d.ts +3 -4
  166. package/dist/types/components/Badge/index.d.ts.map +1 -1
  167. package/dist/types/components/Breadcrumb/index.d.ts.map +1 -1
  168. package/dist/types/components/Button/Button.d.ts +5 -6
  169. package/dist/types/components/Button/Button.d.ts.map +1 -1
  170. package/dist/types/components/Carousel/index.d.ts.map +1 -1
  171. package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +1 -1
  172. package/dist/types/components/Container/index.d.ts +4 -4
  173. package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts.map +1 -1
  174. package/dist/types/components/ExpandCollapse/ExpandCollapse.d.ts.map +1 -1
  175. package/dist/types/components/Input/Checkbox.d.ts +1 -2
  176. package/dist/types/components/Input/Checkbox.d.ts.map +1 -1
  177. package/dist/types/components/LanguageBackground/index.d.ts.map +1 -1
  178. package/dist/types/components/Link/Link.d.ts +2 -3
  179. package/dist/types/components/Link/Link.d.ts.map +1 -1
  180. package/dist/types/components/Loader/spinner.d.ts +1 -1
  181. package/dist/types/components/Pagination/Pagination.d.ts +1 -1
  182. package/dist/types/components/Pagination/Pagination.d.ts.map +1 -1
  183. package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +2 -3
  184. package/dist/types/components/SwitchSelector/SwitchSelector.d.ts.map +1 -1
  185. package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +1 -1
  186. package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts.map +1 -1
  187. package/dist/types/components/TabSelector/TabSelector.d.ts +2 -2
  188. package/dist/types/components/TabSelector/TabSelector.d.ts.map +1 -1
  189. package/dist/types/components/Tag/index.d.ts +2 -2
  190. package/dist/types/components/TextArea/ContentEditableTextArea.d.ts.map +1 -1
  191. package/dist/types/components/Toaster/Toast.d.ts +1 -1
  192. package/dist/types/hooks/index.d.ts +1 -7
  193. package/dist/types/providers/ReactQueryProvider.d.ts +1 -1
  194. package/dist/types/routes.d.ts +23 -1
  195. package/dist/types/routes.d.ts.map +1 -1
  196. package/package.json +35 -30
  197. package/tailwind.css +0 -19
  198. package/dist/esm/hooks/reactQuery.mjs +0 -1187
  199. package/dist/esm/hooks/reactQuery.mjs.map +0 -1
  200. package/dist/esm/hooks/useAuth/useAuth.mjs.map +0 -1
  201. package/dist/esm/hooks/useAuth/useOAuth2.mjs.map +0 -1
  202. package/dist/esm/hooks/useAuth/useSession.mjs.map +0 -1
  203. package/dist/esm/hooks/useIntlayerAPI.mjs +0 -22
  204. package/dist/esm/hooks/useIntlayerAPI.mjs.map +0 -1
  205. package/dist/esm/hooks/useUser/index.mjs.map +0 -1
  206. package/dist/types/hooks/reactQuery.d.ts +0 -188
  207. package/dist/types/hooks/reactQuery.d.ts.map +0 -1
  208. package/dist/types/hooks/useAuth/useAuth.d.ts.map +0 -1
  209. package/dist/types/hooks/useAuth/useOAuth2.d.ts.map +0 -1
  210. package/dist/types/hooks/useAuth/useSession.d.ts.map +0 -1
  211. package/dist/types/hooks/useIntlayerAPI.d.ts +0 -14
  212. package/dist/types/hooks/useIntlayerAPI.d.ts.map +0 -1
  213. package/dist/types/hooks/useUser/index.d.ts.map +0 -1
  214. /package/dist/esm/{hooks → api}/useAuth/index.mjs +0 -0
  215. /package/dist/types/{hooks → api}/useAuth/index.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ContentEditorTextArea.mjs","names":[],"sources":["../../../../src/components/ContentEditor/ContentEditorTextArea.tsx"],"sourcesContent":["'use client';\n\nimport { useUser } from '@hooks/useUser';\nimport { Check, X } from 'lucide-react';\nimport {\n type ChangeEventHandler,\n type FC,\n type ReactNode,\n useEffect,\n useState,\n} from 'react';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { AutoCompleteTextarea, type AutoSizedTextAreaProps } from '../TextArea';\n\n/** Props for the ContentEditorTextArea component */\nexport type ContentEditorTextAreaProps = {\n /** The current content to display and edit */\n children: string;\n /** Callback function called when content is saved/validated */\n onContentChange: (content: string) => void;\n /** Whether the editor is disabled */\n disabled?: boolean;\n /** Optional validation function to check content validity */\n validate?: (content: string) => boolean;\n /** Additional buttons to display alongside edit actions */\n additionalButtons?: ReactNode;\n} & Omit<AutoSizedTextAreaProps, 'children'>;\n\n/**\n * ContentEditorTextArea Component\n *\n * An inline editing component for multi-line text with autocomplete functionality,\n * user authentication integration, and validation support. This component combines\n * the auto-sizing textarea with smart autocomplete features.\n *\n * ## Features\n * - **Auto-sizing Textarea**: Automatically adjusts height to content\n * - **Autocomplete Integration**: Smart text completion when user is authenticated\n * - **Validation Support**: Optional content validation with visual feedback\n * - **Action Buttons**: Built-in save/cancel with support for additional buttons\n * - **Keyboard Shortcuts**: Enter to save, Escape to cancel\n * - **User Authentication**: Autocomplete features activate based on auth status\n * - **Accessibility**: Full ARIA support and keyboard navigation\n *\n * ## Accessibility\n * - Proper ARIA labels and descriptions for all controls\n * - Keyboard navigation (Tab, Enter, Escape)\n * - Screen reader support for validation states and user auth status\n * - Focus management and visual indicators\n *\n * @param children - Current textarea content\n * @param onContentChange - Callback when content is saved\n * @param disabled - Whether the editor is disabled\n * @param validate - Optional validation function\n * @param additionalButtons - Extra buttons to display\n * @param props - Additional AutoSizedTextArea component props\n */\nexport const ContentEditorTextArea: FC<ContentEditorTextAreaProps> = ({\n children,\n onContentChange,\n disabled,\n validate,\n additionalButtons,\n ...props\n}) => {\n const { isAuthenticated } = useUser();\n const [newValue, setNewValue] = useState<string>(children);\n const [resetIncrementor, setResetIncrementor] = useState<number>(0); // To reset the textarea on cancel\n const isEdited: boolean = newValue !== children;\n\n const handleCancel = () => {\n setNewValue(children);\n setResetIncrementor((prev) => prev + 1);\n };\n\n const handleValid = () => {\n onContentChange(newValue);\n };\n\n const handleOnContentChange: ChangeEventHandler<HTMLTextAreaElement> = (e) =>\n setNewValue(e.currentTarget.value ?? '');\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && !disabled && isValid) {\n e.preventDefault();\n handleValid();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n handleCancel();\n }\n };\n\n useEffect(() => {\n setNewValue(children);\n // Force textarea to reset when children changes externally\n setResetIncrementor((prev) => prev + 1);\n }, [children]);\n\n const isValid = validate?.(newValue) ?? true;\n\n return (\n <div\n className=\"flex size-full flex-col items-center justify-between gap-2\"\n key={children}\n role=\"group\"\n aria-label=\"Content editor textarea\"\n >\n <AutoCompleteTextarea\n onChange={handleOnContentChange}\n onKeyDown={handleKeyDown}\n key={resetIncrementor}\n variant=\"invisible\"\n className=\"size-full\"\n value={children}\n isActive={isAuthenticated}\n disabled={disabled}\n aria-label=\"Editable textarea content\"\n aria-describedby={\n isEdited || additionalButtons\n ? 'content-editor-textarea-actions'\n : undefined\n }\n aria-invalid={!isValid}\n {...props}\n />\n {(isEdited || additionalButtons) && (\n <div\n id=\"content-editor-textarea-actions\"\n className=\"flex w-full items-center justify-end gap-2\"\n role=\"group\"\n aria-label=\"Edit actions\"\n >\n {isEdited && (\n <>\n <Button\n Icon={Check}\n label={`Save changes${!isValid ? ' (invalid content)' : ''}`}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n size={ButtonSize.ICON_SM}\n className=\"cursor-pointer hover:scale-110\"\n disabled={disabled || !isValid}\n onClick={handleValid}\n aria-describedby={\n !isValid ? 'textarea-validation-error' : undefined\n }\n />\n <Button\n Icon={X}\n label=\"Cancel changes\"\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"cursor-pointer hover:scale-110\"\n onClick={handleCancel}\n disabled={disabled}\n />\n </>\n )}\n {additionalButtons}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAa,yBAAyD,EACpE,UACA,iBACA,UACA,UACA,mBACA,GAAG,YACC;CACJ,MAAM,EAAE,oBAAoB,QAAQ;CACpC,MAAM,CAAC,UAAU,eAAe,SAAiB,QAAQ;CACzD,MAAM,CAAC,kBAAkB,uBAAuB,SAAiB,CAAC;CAClE,MAAM,WAAoB,aAAa;CAEvC,MAAM,qBAAqB;EACzB,YAAY,QAAQ;EACpB,qBAAqB,SAAS,OAAO,CAAC;CACxC;CAEA,MAAM,oBAAoB;EACxB,gBAAgB,QAAQ;CAC1B;CAEA,MAAM,yBAAkE,MACtE,YAAY,EAAE,cAAc,SAAS,EAAE;CAEzC,MAAM,iBAAiB,MAAgD;EACrE,IAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,YAAY,CAAC,YAAY,SAAS;GACzE,EAAE,eAAe;GACjB,YAAY;EACd,OAAO,IAAI,EAAE,QAAQ,UAAU;GAC7B,EAAE,eAAe;GACjB,aAAa;EACf;CACF;CAEA,gBAAgB;EACd,YAAY,QAAQ;EAEpB,qBAAqB,SAAS,OAAO,CAAC;CACxC,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,UAAU,WAAW,QAAQ,KAAK;CAExC,OACE,qBAAC,OAAD;EACE,WAAU;EAEV,MAAK;EACL,cAAW;YAJb,CAME,oBAAC,sBAAD;GACE,UAAU;GACV,WAAW;GAEX,SAAQ;GACR,WAAU;GACV,OAAO;GACP,UAAU;GACA;GACV,cAAW;GACX,oBACE,YAAY,oBACR,oCACA;GAEN,gBAAc,CAAC;GACf,GAAI;EACL,GAdM,gBAcN,IACC,YAAY,sBACZ,qBAAC,OAAD;GACE,IAAG;GACH,WAAU;GACV,MAAK;GACL,cAAW;aAJb,CAMG,YACC,8CACE,oBAAC,QAAD;IACE,MAAM;IACN,OAAO,eAAe,CAAC,UAAU,uBAAuB;IACxD;IACA;IACA;IACA,WAAU;IACV,UAAU,YAAY,CAAC;IACvB,SAAS;IACT,oBACE,CAAC,UAAU,8BAA8B;GAE5C,IACD,oBAAC,QAAD;IACE,MAAM;IACN,OAAM;IACN;IACA;IACA;IACA,WAAU;IACV,SAAS;IACC;GACX,EACD,MAEH,iBACE;IAEJ;IA3DE,QA2DF;AAET"}
1
+ {"version":3,"file":"ContentEditorTextArea.mjs","names":[],"sources":["../../../../src/components/ContentEditor/ContentEditorTextArea.tsx"],"sourcesContent":["'use client';\n\nimport { useUser } from '@api/useUser';\nimport { Check, X } from 'lucide-react';\nimport {\n type ChangeEventHandler,\n type FC,\n type ReactNode,\n useEffect,\n useState,\n} from 'react';\nimport { Button, ButtonColor, ButtonSize, ButtonVariant } from '../Button';\nimport { AutoCompleteTextarea, type AutoSizedTextAreaProps } from '../TextArea';\n\n/** Props for the ContentEditorTextArea component */\nexport type ContentEditorTextAreaProps = {\n /** The current content to display and edit */\n children: string;\n /** Callback function called when content is saved/validated */\n onContentChange: (content: string) => void;\n /** Whether the editor is disabled */\n disabled?: boolean;\n /** Optional validation function to check content validity */\n validate?: (content: string) => boolean;\n /** Additional buttons to display alongside edit actions */\n additionalButtons?: ReactNode;\n} & Omit<AutoSizedTextAreaProps, 'children'>;\n\n/**\n * ContentEditorTextArea Component\n *\n * An inline editing component for multi-line text with autocomplete functionality,\n * user authentication integration, and validation support. This component combines\n * the auto-sizing textarea with smart autocomplete features.\n *\n * ## Features\n * - **Auto-sizing Textarea**: Automatically adjusts height to content\n * - **Autocomplete Integration**: Smart text completion when user is authenticated\n * - **Validation Support**: Optional content validation with visual feedback\n * - **Action Buttons**: Built-in save/cancel with support for additional buttons\n * - **Keyboard Shortcuts**: Enter to save, Escape to cancel\n * - **User Authentication**: Autocomplete features activate based on auth status\n * - **Accessibility**: Full ARIA support and keyboard navigation\n *\n * ## Accessibility\n * - Proper ARIA labels and descriptions for all controls\n * - Keyboard navigation (Tab, Enter, Escape)\n * - Screen reader support for validation states and user auth status\n * - Focus management and visual indicators\n *\n * @param children - Current textarea content\n * @param onContentChange - Callback when content is saved\n * @param disabled - Whether the editor is disabled\n * @param validate - Optional validation function\n * @param additionalButtons - Extra buttons to display\n * @param props - Additional AutoSizedTextArea component props\n */\nexport const ContentEditorTextArea: FC<ContentEditorTextAreaProps> = ({\n children,\n onContentChange,\n disabled,\n validate,\n additionalButtons,\n ...props\n}) => {\n const { isAuthenticated } = useUser();\n const [newValue, setNewValue] = useState<string>(children);\n const [resetIncrementor, setResetIncrementor] = useState<number>(0); // To reset the textarea on cancel\n const isEdited: boolean = newValue !== children;\n\n const handleCancel = () => {\n setNewValue(children);\n setResetIncrementor((prev) => prev + 1);\n };\n\n const handleValid = () => {\n onContentChange(newValue);\n };\n\n const handleOnContentChange: ChangeEventHandler<HTMLTextAreaElement> = (e) =>\n setNewValue(e.currentTarget.value ?? '');\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && !disabled && isValid) {\n e.preventDefault();\n handleValid();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n handleCancel();\n }\n };\n\n useEffect(() => {\n setNewValue(children);\n // Force textarea to reset when children changes externally\n setResetIncrementor((prev) => prev + 1);\n }, [children]);\n\n const isValid = validate?.(newValue) ?? true;\n\n return (\n <div\n className=\"flex size-full flex-col items-center justify-between gap-2\"\n key={children}\n role=\"group\"\n aria-label=\"Content editor textarea\"\n >\n <AutoCompleteTextarea\n onChange={handleOnContentChange}\n onKeyDown={handleKeyDown}\n key={resetIncrementor}\n variant=\"invisible\"\n className=\"size-full\"\n value={children}\n isActive={isAuthenticated}\n disabled={disabled}\n aria-label=\"Editable textarea content\"\n aria-describedby={\n isEdited || additionalButtons\n ? 'content-editor-textarea-actions'\n : undefined\n }\n aria-invalid={!isValid}\n {...props}\n />\n {(isEdited || additionalButtons) && (\n <div\n id=\"content-editor-textarea-actions\"\n className=\"flex w-full items-center justify-end gap-2\"\n role=\"group\"\n aria-label=\"Edit actions\"\n >\n {isEdited && (\n <>\n <Button\n Icon={Check}\n label={`Save changes${!isValid ? ' (invalid content)' : ''}`}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n size={ButtonSize.ICON_SM}\n className=\"cursor-pointer hover:scale-110\"\n disabled={disabled || !isValid}\n onClick={handleValid}\n aria-describedby={\n !isValid ? 'textarea-validation-error' : undefined\n }\n />\n <Button\n Icon={X}\n label=\"Cancel changes\"\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"cursor-pointer hover:scale-110\"\n onClick={handleCancel}\n disabled={disabled}\n />\n </>\n )}\n {additionalButtons}\n </div>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,MAAa,yBAAyD,EACpE,UACA,iBACA,UACA,UACA,mBACA,GAAG,YACC;CACJ,MAAM,EAAE,oBAAoB,QAAQ;CACpC,MAAM,CAAC,UAAU,eAAe,SAAiB,QAAQ;CACzD,MAAM,CAAC,kBAAkB,uBAAuB,SAAiB,CAAC;CAClE,MAAM,WAAoB,aAAa;CAEvC,MAAM,qBAAqB;EACzB,YAAY,QAAQ;EACpB,qBAAqB,SAAS,OAAO,CAAC;CACxC;CAEA,MAAM,oBAAoB;EACxB,gBAAgB,QAAQ;CAC1B;CAEA,MAAM,yBAAkE,MACtE,YAAY,EAAE,cAAc,SAAS,EAAE;CAEzC,MAAM,iBAAiB,MAAgD;EACrE,IAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,YAAY,CAAC,YAAY,SAAS;GACzE,EAAE,eAAe;GACjB,YAAY;EACd,OAAO,IAAI,EAAE,QAAQ,UAAU;GAC7B,EAAE,eAAe;GACjB,aAAa;EACf;CACF;CAEA,gBAAgB;EACd,YAAY,QAAQ;EAEpB,qBAAqB,SAAS,OAAO,CAAC;CACxC,GAAG,CAAC,QAAQ,CAAC;CAEb,MAAM,UAAU,WAAW,QAAQ,KAAK;CAExC,OACE,qBAAC,OAAD;EACE,WAAU;EAEV,MAAK;EACL,cAAW;YAJb,CAME,oBAAC,sBAAD;GACE,UAAU;GACV,WAAW;GAEX,SAAQ;GACR,WAAU;GACV,OAAO;GACP,UAAU;GACA;GACV,cAAW;GACX,oBACE,YAAY,oBACR,oCACA;GAEN,gBAAc,CAAC;GACf,GAAI;EACL,GAdM,gBAcN,IACC,YAAY,sBACZ,qBAAC,OAAD;GACE,IAAG;GACH,WAAU;GACV,MAAK;GACL,cAAW;aAJb,CAMG,YACC,8CACE,oBAAC,QAAD;IACE,MAAM;IACN,OAAO,eAAe,CAAC,UAAU,uBAAuB;IACxD;IACA;IACA;IACA,WAAU;IACV,UAAU,YAAY,CAAC;IACvB,SAAS;IACT,oBACE,CAAC,UAAU,8BAA8B;GAE5C,IACD,oBAAC,QAAD;IACE,MAAM;IACN,OAAM;IACN;IACA;IACA;IACA,WAAU;IACV,SAAS;IACC;GACX,EACD,MAEH,iBACE;IAEJ;IA3DE,QA2DF;AAET"}
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import { useAuditContentDeclarationField } from "../../../hooks/reactQuery.mjs";
3
+ import { useAuditContentDeclarationField } from "../../../api/hooks/ai.mjs";
4
4
  import { Container } from "../../Container/index.mjs";
5
5
  import { Loader } from "../../Loader/index.mjs";
6
6
  import { Button, ButtonColor, ButtonSize, ButtonTextAlign, ButtonVariant } from "../../Button/Button.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"TextEditor.mjs","names":["ContentEditorTextAreaBase","ContentEditorInputBase"],"sources":["../../../../../src/components/DictionaryFieldEditor/ContentEditorView/TextEditor.tsx"],"sourcesContent":["'use client';\n\nimport { Accordion } from '@components/Accordion';\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonTextAlign,\n ButtonVariant,\n} from '@components/Button';\nimport { Container } from '@components/Container';\nimport {\n ContentEditorInput as ContentEditorInputBase,\n type ContentEditorInputProps as ContentEditorInputPropsBase,\n} from '@components/ContentEditor/ContentEditorInput';\nimport {\n ContentEditorTextArea as ContentEditorTextAreaBase,\n type ContentEditorTextAreaProps as ContentEditorTextAreaPropsBase,\n} from '@components/ContentEditor/ContentEditorTextArea';\nimport { renameKey } from '@components/DictionaryFieldEditor/ContentEditorView/object';\nimport { InputVariant } from '@components/Input';\nimport { Label } from '@components/Label';\nimport { Loader } from '@components/Loader';\nimport { useLocaleSwitcherContent } from '@components/LocaleSwitcherContentDropDown';\nimport {\n SwitchSelector,\n type SwitchSelectorChoices,\n SwitchSelectorColor,\n type SwitchSelectorProps,\n SwitchSelectorSize,\n} from '@components/SwitchSelector';\nimport { useAuditContentDeclarationField } from '@hooks/reactQuery';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getEmptyNode,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getLocaleName } from '@intlayer/core/localization';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n GenderContent,\n HTMLContent,\n InsertionContent,\n MarkdownContent,\n PluralContent,\n TranslationContent,\n} from '@intlayer/core/transpiler';\nimport { useConfiguration, useEditedContent } from '@intlayer/editor-react';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport type { LocalesValues } from '@intlayer/types/module_augmentation';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { Plus, Trash, WandSparkles } from 'lucide-react';\nimport {\n type FC,\n Fragment,\n lazy,\n memo,\n type ReactNode,\n Suspense,\n useState,\n} from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport { EnumKeyInput } from '../EnumKeyInput';\nimport { SafeHtmlRenderer } from './SafeHtmlRenderer';\n\nconst LazyMarkdownRenderer = lazy(() =>\n import('@components/MarkDownRender').then((m) => ({\n default: m.MarkdownRenderer,\n }))\n);\n\n// Renders children only after the accordion is first opened (mount-once pattern).\n// Prevents deeply nested sub-trees from mounting on initial render.\ntype CollapsibleEditorProps = TextEditorProps & { label: string };\nconst CollapsibleEditor = memo<CollapsibleEditorProps>(\n function CollapsibleEditor({ label, ...editorProps }) {\n const [hasOpened, setHasOpened] = useState(false);\n return (\n <Accordion\n header={label}\n label={label}\n onToggle={(isOpen) => {\n if (isOpen && !hasOpened) setHasOpened(true);\n }}\n >\n {hasOpened ? <TextEditor {...editorProps} /> : null}\n </Accordion>\n );\n }\n);\n\nexport const traceKeys: string[] = ['filePath', 'id', 'nodeType'];\n\ntype ContentEditorTextAreaProps = Omit<\n ContentEditorTextAreaPropsBase,\n 'onContentChange'\n> & {\n keyPath: KeyPath[];\n dictionary: Dictionary;\n};\n\nconst ContentEditorTextArea: FC<ContentEditorTextAreaProps> = ({\n keyPath,\n dictionary,\n ...props\n}) => {\n const { editedContent, addEditedContent } = useEditedContent();\n const configuration = useConfiguration();\n const { mutate: auditContentDeclarationField, isPending: isAuditing } =\n useAuditContentDeclarationField();\n\n return (\n <ContentEditorTextAreaBase\n variant={InputVariant.DEFAULT}\n onContentChange={(newValue) =>\n addEditedContent(dictionary.localId!, newValue, keyPath)\n }\n additionalButtons={\n <Button\n Icon={WandSparkles}\n label=\"Audit\"\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"cursor-pointer hover:scale-110\"\n isLoading={isAuditing}\n onClick={() => {\n auditContentDeclarationField(\n {\n fileContent: JSON.stringify({\n ...dictionary,\n ...(editedContent?.[dictionary.localId!] ?? {}),\n }),\n keyPath,\n locales: configuration?.internationalization.locales ?? [],\n aiOptions: {\n apiKey: configuration?.ai?.apiKey,\n model: configuration?.ai?.model,\n temperature: configuration?.ai?.temperature,\n },\n },\n {\n onSuccess: (response) => {\n if (!response?.data) return;\n\n try {\n const editedContent = response.data.fileContent as string;\n\n addEditedContent(\n dictionary.localId!,\n editedContent,\n keyPath\n );\n } catch (error) {\n console.error(error);\n }\n },\n }\n );\n }}\n />\n }\n {...props}\n />\n );\n};\n\ntype ContentEditorInputProps = Omit<\n ContentEditorInputPropsBase,\n 'onContentChange'\n> & {\n keyPath: KeyPath[];\n dictionary: Dictionary;\n};\n\nconst ContentEditorInput: FC<ContentEditorInputProps> = ({\n keyPath,\n dictionary,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n return (\n <ContentEditorInputBase\n variant={InputVariant.DEFAULT}\n onContentChange={(newValue) =>\n addEditedContent(dictionary.localId!, newValue, keyPath)\n }\n {...props}\n />\n );\n};\n\nconst toggleContent = [\n {\n content: 'False',\n value: false,\n },\n {\n content: 'True',\n value: true,\n },\n] as SwitchSelectorChoices<boolean>;\n\ntype ContentEditorToggleProps = SwitchSelectorProps & {\n dictionary: Dictionary;\n keyPath: KeyPath[];\n};\n\nconst ContentEditorToggle: FC<ContentEditorToggleProps> = ({\n dictionary,\n keyPath,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n return (\n <SwitchSelector\n choices={toggleContent}\n value={true}\n onChange={(value) =>\n addEditedContent(dictionary.localId!, value, keyPath)\n }\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n {...props}\n />\n );\n};\n\nexport type TextEditorProps = {\n dictionary: Dictionary;\n keyPath: KeyPath[];\n section: ContentNode;\n isDarkMode?: boolean;\n renderSection?: (content: string) => ReactNode;\n onContentChange?: (newValue: string) => void;\n};\n\nconst TranslationTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}: TextEditorProps) => {\n const { locale, defaultLocale } = useLocale();\n const { selectedLocales } = useLocaleSwitcherContent();\n\n const content: any = (section as TranslationContent<string>)[\n NodeTypes.TRANSLATION\n ];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {selectedLocales.map((translationKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-translation-${translationKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full p-2 text-xs\">\n <td className=\"flex w-full\">\n {getLocaleName(translationKey, locale)}\n </td>\n </tr>\n <tr className=\"flex\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[translationKey] ??\n getEmptyNode(content[defaultLocale])\n }\n keyPath={[\n ...keyPath,\n { type: NodeTypes.TRANSLATION, key: translationKey },\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst EnumerationTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const { addEditedContent } = useEditedContent();\n const { addNewEnumeration, removeEnumeration } =\n useIntlayer('navigation-view');\n\n const content = (section as EnumerationContent<string>)[\n NodeTypes.ENUMERATION\n ];\n const firstKey = Object.keys(content)[0] as keyof typeof content;\n\n return (\n <div className=\"flex flex-col gap-2\">\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {Object.keys(\n (section as EnumerationContent<ContentNode>)[NodeTypes.ENUMERATION]\n ).map((enumKey) => {\n const childrenKeyPath = [\n ...keyPath,\n { type: NodeTypes.ENUMERATION, key: enumKey },\n ] as KeyPath[];\n const uniqueKey = `${JSON.stringify(keyPath)}-enumeration-${enumKey}`;\n\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full\">\n <td className=\"flex w-full\">\n <div className=\"flex flex-1\">\n <Button\n label={removeEnumeration.label.value}\n variant=\"hoverable\"\n size=\"sm\"\n color=\"error\"\n className=\"ml-auto text-neutral hover:text-error\"\n Icon={Trash}\n onClick={() =>\n addEditedContent(\n dictionary.localId!,\n undefined,\n childrenKeyPath\n )\n }\n >\n {removeEnumeration.text}\n </Button>\n </div>\n </td>\n </tr>\n <tr className=\"w-full p-2\">\n <td className=\"flex w-full\">\n <EnumKeyInput\n value={enumKey}\n onChange={(value) => {\n const preValueContent = (\n section as EnumerationContent<string>\n )[NodeTypes.ENUMERATION];\n\n const newValueContent = renameKey(\n preValueContent,\n enumKey as keyof typeof preValueContent,\n value\n );\n const newValue = {\n ...(section as EnumerationContent<string>),\n [NodeTypes.ENUMERATION]: newValueContent,\n };\n\n console.log('newValue', newValue);\n\n addEditedContent(\n dictionary.localId!,\n newValue,\n keyPath\n );\n }}\n />\n </td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditor\n section={\n content[enumKey as keyof typeof content] ??\n getEmptyNode(content[firstKey])\n }\n keyPath={childrenKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n\n <Button\n label={addNewEnumeration.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n isFullWidth\n onClick={() =>\n addEditedContent(\n dictionary.localId!,\n getEmptyNode(content[firstKey]) ?? '',\n [...keyPath, { type: NodeTypes.ENUMERATION, key: 'unknown' }]\n )\n }\n Icon={Plus}\n className=\"m-2\"\n >\n {addNewEnumeration.text}\n </Button>\n </div>\n );\n};\n\nconst ConditionTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as ConditionContent<string>)[NodeTypes.CONDITION];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {['true', 'false', 'fallback'].map((condKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-condition-${condKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{String(condKey)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[condKey as keyof typeof content] ??\n getEmptyNode(content.true)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.CONDITION,\n key: condKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst GenderTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as GenderContent<string>)[NodeTypes.GENDER];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {['male', 'female', 'fallback'].map((condKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-gender-${condKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{String(condKey)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[condKey as keyof typeof content] ??\n getEmptyNode(content.male)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.GENDER,\n key: condKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'];\n\nconst PluralTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as PluralContent<string>)[NodeTypes.PLURAL];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {PLURAL_CATEGORIES.map((pluralKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-plural-${pluralKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{pluralKey}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[pluralKey as keyof typeof content] ??\n getEmptyNode(content.other)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.PLURAL,\n key: pluralKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst ArrayTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const { addEditedContent } = useEditedContent();\n const { addNewElement, removeElement } = useIntlayer('navigation-view');\n\n return (\n <div className=\"flex flex-col gap-2\">\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {(section as unknown as ContentNode[]).map((subSection, index) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-array-${index}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full p-2\">\n <td className=\"flex w-full\">\n <div className=\"flex w-full items-center justify-between gap-2\">\n <span className=\"text-xs\">{String(index)}</span>\n <Button\n label={removeElement.label.value}\n variant=\"hoverable\"\n size=\"sm\"\n color=\"error\"\n className=\"ml-auto text-neutral hover:text-error\"\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: index, // Fixed: Use index instead of length\n },\n ];\n addEditedContent(\n dictionary.localId!,\n undefined,\n newKeyPath\n );\n }}\n Icon={Trash}\n >\n {removeElement.text}\n </Button>\n </div>\n </td>\n </tr>\n\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n subSection ??\n getEmptyNode((section as unknown as ContentNode[])[0])\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: index,\n },\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n <Button\n label={addNewElement.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n isFullWidth\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: (section as unknown as ContentNode[]).length, // Keeps length for adding new items\n },\n ];\n addEditedContent(\n dictionary.localId!,\n getEmptyNode((section as unknown as ContentNode[])[0]) ?? '',\n newKeyPath,\n false\n );\n }}\n Icon={Plus}\n >\n {addNewElement.text}\n </Button>\n </div>\n );\n};\n\nconst ObjectTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const typedSection = section as unknown as Record<string, ContentNode>;\n const firstKey = Object.keys(typedSection)[0] as keyof typeof section;\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex flex-col gap-2\">\n {Object.keys(typedSection).map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key },\n ];\n const subSection =\n typedSection[key as keyof typeof section] ??\n getEmptyNode(typedSection[firstKey]);\n const uniqueKey = `${JSON.stringify(keyPath)}-object-${key}`;\n // Collapse any object/array (typed or plain) — only true primitives render inline.\n // getIsEditableSection can't be used here: it inspects getNodeChildren(), which for\n // translation nodes returns the first locale value (a string), causing translation\n // subtrees to be mistakenly treated as leaves and mounted all at once.\n const isLeaf = subSection === null || typeof subSection !== 'object';\n\n if (isLeaf) {\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 p-2 text-xs\">\n <td className=\"flex w-full\">{String(key)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditor\n section={subSection}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n }\n\n return (\n <tr\n key={uniqueKey}\n className=\"block w-full border-neutral/10 border-t py-1\"\n >\n <td className=\"flex w-full\">\n <CollapsibleEditor\n label={camelCaseToSentence(key)}\n section={subSection}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nenum MarkdownViewMode {\n Edit,\n Preview,\n}\n\nenum HtmlViewMode {\n Edit,\n Preview,\n}\n\nconst HtmlTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n}) => {\n const [mode, setMode] = useState(HtmlViewMode.Edit);\n const toggleContent = [\n {\n content: 'Edit',\n value: HtmlViewMode.Edit,\n },\n {\n content: 'Preview',\n value: HtmlViewMode.Preview,\n },\n ] as SwitchSelectorChoices<HtmlViewMode>;\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.HTML }];\n\n const content = (section as HTMLContent<ContentNode>)[\n NodeTypes.HTML\n ] as ContentNode;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <SwitchSelector\n choices={toggleContent}\n value={mode}\n onChange={setMode}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"ml-auto\"\n />\n\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={\n mode === HtmlViewMode.Preview\n ? (rawContent) => <SafeHtmlRenderer rawContent={rawContent} />\n : undefined\n }\n />\n </div>\n );\n};\n\nconst MarkdownTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n isDarkMode,\n}) => {\n const [mode, setMode] = useState(MarkdownViewMode.Edit);\n const toggleContent = [\n {\n content: 'Edit',\n value: MarkdownViewMode.Edit,\n },\n {\n content: 'Preview',\n value: MarkdownViewMode.Preview,\n },\n ] as SwitchSelectorChoices<MarkdownViewMode>;\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.MARKDOWN }];\n\n const content = ((section as MarkdownContent<ContentNode>)[\n NodeTypes.MARKDOWN\n ] ?? '') as ContentNode;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <SwitchSelector\n choices={toggleContent}\n value={mode}\n onChange={setMode}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"ml-auto\"\n />\n\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={\n mode === MarkdownViewMode.Preview\n ? (content) => (\n <Suspense fallback={<Loader />}>\n <LazyMarkdownRenderer isDarkMode={isDarkMode}>\n {content}\n </LazyMarkdownRenderer>\n </Suspense>\n )\n : undefined\n }\n />\n </div>\n );\n};\n\nconst InsertionTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n ...props\n}) => {\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.INSERTION }];\n\n const content = (section as InsertionContent<ContentNode>)[\n NodeTypes.INSERTION\n ];\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n {...props}\n />\n </div>\n );\n};\n\nconst FileTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n ...props\n}) => {\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.FILE }];\n\n const fileUrl = (section as FileContent)[NodeTypes.FILE];\n const { content } = section as FileContent;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <span className=\"text-neutral text-sm\">{fileUrl} </span>\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n {...props}\n />\n </div>\n );\n};\n\nconst NestedTextEditor: FC<TextEditorProps> = ({\n keyPath,\n dictionary,\n renderSection,\n section,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n const content = (section as any)[NodeTypes.NESTED];\n const childrenKeyPath = [...keyPath, { type: NodeTypes.NESTED }] as KeyPath[];\n\n return (\n <div className=\"flex w-full flex-col gap-4 p-2\">\n <Label>Dictionary key</Label>\n <ContentEditorInputBase\n aria-label=\"Edit field\"\n type=\"text\"\n variant={InputVariant.DEFAULT}\n {...props}\n onContentChange={(newValue) => {\n addEditedContent(\n dictionary.localId!,\n {\n ...content,\n dictionaryKey: String(newValue),\n },\n childrenKeyPath\n );\n }}\n >\n {content.dictionaryKey ?? ''}\n </ContentEditorInputBase>\n\n <Label>Path (optional)</Label>\n <ContentEditorInputBase\n aria-label=\"Edit field\"\n type=\"text\"\n variant={InputVariant.DEFAULT}\n {...props}\n onContentChange={(newValue) => {\n addEditedContent(\n dictionary.localId!,\n {\n ...content,\n path: newValue !== '' ? newValue : undefined,\n },\n childrenKeyPath\n );\n }}\n >\n {content.path ?? ''}\n </ContentEditorInputBase>\n </div>\n );\n};\n\nexport const TextEditor = memo<TextEditorProps>(function TextEditor({\n section,\n keyPath,\n dictionary,\n renderSection,\n isDarkMode,\n}) {\n const { tsxNotEditable } = useIntlayer('navigation-view');\n const nodeType = getNodeType(section);\n\n if (nodeType === NodeTypes.REACT_NODE) {\n return (\n <div className=\"flex w-full flex-col gap-2\">\n <span>(React Node)</span>\n <span className=\"flex text-neutral text-xs\">{tsxNotEditable}</span>\n </div>\n );\n }\n\n if (nodeType === NodeTypes.NESTED) {\n return (\n <NestedTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return (\n <TranslationTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.ENUMERATION) {\n return (\n <EnumerationTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.CONDITION) {\n return (\n <ConditionTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.GENDER) {\n return (\n <GenderTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.PLURAL) {\n return (\n <PluralTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.INSERTION) {\n return (\n <InsertionTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.MARKDOWN) {\n return (\n <MarkdownTextEditor\n dictionary={dictionary}\n keyPath={keyPath}\n section={section}\n isDarkMode={isDarkMode}\n />\n );\n }\n\n if (nodeType === NodeTypes.HTML) {\n return (\n <HtmlTextEditor\n dictionary={dictionary}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.FILE) {\n return (\n <FileTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n return (\n <ArrayTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.OBJECT) {\n return (\n <ObjectTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.NUMBER) {\n return (\n <div className=\"w-full p-2\">\n <ContentEditorInput\n dictionary={dictionary}\n keyPath={keyPath}\n type=\"number\"\n aria-label=\"Edit field\"\n >\n {section as number}\n </ContentEditorInput>\n </div>\n );\n }\n\n if (nodeType === NodeTypes.TEXT) {\n return (\n <div className=\"w-full p-2\">\n {typeof renderSection === 'function' ? (\n renderSection(section as string)\n ) : (\n <ContentEditorTextArea\n variant={InputVariant.DEFAULT}\n aria-label=\"Edit field\"\n keyPath={keyPath}\n dictionary={dictionary}\n >\n {section as string}\n </ContentEditorTextArea>\n )}\n </div>\n );\n }\n\n if (nodeType === NodeTypes.BOOLEAN) {\n return (\n <div className=\"w-full p-2\">\n <ContentEditorToggle\n dictionary={dictionary}\n keyPath={keyPath}\n value={section as boolean}\n />\n </div>\n );\n }\n\n return (\n <div className=\"w-full p-2\">\n Error. Format not supported.\n {JSON.stringify(section, null, 2)}\n {JSON.stringify(keyPath, null, 2)}\n NodeType : {nodeType}\n </div>\n );\n});\n\nexport const TextEditorContainer = memo<TextEditorProps>(\n function TextEditorContainer(props) {\n return (\n <Container\n border\n background=\"none\"\n className=\"top-6 flex h-full flex-1 flex-col gap-6 overflow-hidden p-2 md:sticky\"\n roundedSize=\"2xl\"\n >\n <TextEditor {...props} />\n </Container>\n );\n }\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"TextEditor.mjs","names":["ContentEditorTextAreaBase","ContentEditorInputBase"],"sources":["../../../../../src/components/DictionaryFieldEditor/ContentEditorView/TextEditor.tsx"],"sourcesContent":["'use client';\n\nimport { useAuditContentDeclarationField } from '@api/index';\nimport { Accordion } from '@components/Accordion';\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonTextAlign,\n ButtonVariant,\n} from '@components/Button';\nimport { Container } from '@components/Container';\nimport {\n ContentEditorInput as ContentEditorInputBase,\n type ContentEditorInputProps as ContentEditorInputPropsBase,\n} from '@components/ContentEditor/ContentEditorInput';\nimport {\n ContentEditorTextArea as ContentEditorTextAreaBase,\n type ContentEditorTextAreaProps as ContentEditorTextAreaPropsBase,\n} from '@components/ContentEditor/ContentEditorTextArea';\nimport { renameKey } from '@components/DictionaryFieldEditor/ContentEditorView/object';\nimport { InputVariant } from '@components/Input';\nimport { Label } from '@components/Label';\nimport { Loader } from '@components/Loader';\nimport { useLocaleSwitcherContent } from '@components/LocaleSwitcherContentDropDown';\nimport {\n SwitchSelector,\n type SwitchSelectorChoices,\n SwitchSelectorColor,\n type SwitchSelectorProps,\n SwitchSelectorSize,\n} from '@components/SwitchSelector';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getEmptyNode,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { getLocaleName } from '@intlayer/core/localization';\nimport type {\n ConditionContent,\n EnumerationContent,\n FileContent,\n GenderContent,\n HTMLContent,\n InsertionContent,\n MarkdownContent,\n PluralContent,\n TranslationContent,\n} from '@intlayer/core/transpiler';\nimport { useConfiguration, useEditedContent } from '@intlayer/editor-react';\nimport type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { Plus, Trash, WandSparkles } from 'lucide-react';\nimport {\n type FC,\n Fragment,\n lazy,\n memo,\n type ReactNode,\n Suspense,\n useState,\n} from 'react';\nimport { useIntlayer, useLocale } from 'react-intlayer';\nimport { EnumKeyInput } from '../EnumKeyInput';\nimport { SafeHtmlRenderer } from './SafeHtmlRenderer';\n\nconst LazyMarkdownRenderer = lazy(() =>\n import('@components/MarkDownRender').then((m) => ({\n default: m.MarkdownRenderer,\n }))\n);\n\n// Renders children only after the accordion is first opened (mount-once pattern).\n// Prevents deeply nested sub-trees from mounting on initial render.\ntype CollapsibleEditorProps = TextEditorProps & { label: string };\nconst CollapsibleEditor = memo<CollapsibleEditorProps>(\n function CollapsibleEditor({ label, ...editorProps }) {\n const [hasOpened, setHasOpened] = useState(false);\n return (\n <Accordion\n header={label}\n label={label}\n onToggle={(isOpen) => {\n if (isOpen && !hasOpened) setHasOpened(true);\n }}\n >\n {hasOpened ? <TextEditor {...editorProps} /> : null}\n </Accordion>\n );\n }\n);\n\nexport const traceKeys: string[] = ['filePath', 'id', 'nodeType'];\n\ntype ContentEditorTextAreaProps = Omit<\n ContentEditorTextAreaPropsBase,\n 'onContentChange'\n> & {\n keyPath: KeyPath[];\n dictionary: Dictionary;\n};\n\nconst ContentEditorTextArea: FC<ContentEditorTextAreaProps> = ({\n keyPath,\n dictionary,\n ...props\n}) => {\n const { editedContent, addEditedContent } = useEditedContent();\n const configuration = useConfiguration();\n const { mutate: auditContentDeclarationField, isPending: isAuditing } =\n useAuditContentDeclarationField();\n\n return (\n <ContentEditorTextAreaBase\n variant={InputVariant.DEFAULT}\n onContentChange={(newValue) =>\n addEditedContent(dictionary.localId!, newValue, keyPath)\n }\n additionalButtons={\n <Button\n Icon={WandSparkles}\n label=\"Audit\"\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"cursor-pointer hover:scale-110\"\n isLoading={isAuditing}\n onClick={() => {\n auditContentDeclarationField(\n {\n fileContent: JSON.stringify({\n ...dictionary,\n ...(editedContent?.[dictionary.localId!] ?? {}),\n }),\n keyPath,\n locales: configuration?.internationalization.locales ?? [],\n aiOptions: {\n apiKey: configuration?.ai?.apiKey,\n model: configuration?.ai?.model,\n temperature: configuration?.ai?.temperature,\n },\n },\n {\n onSuccess: (response) => {\n if (!response?.data) return;\n\n try {\n const editedContent = response.data.fileContent as string;\n\n addEditedContent(\n dictionary.localId!,\n editedContent,\n keyPath\n );\n } catch (error) {\n console.error(error);\n }\n },\n }\n );\n }}\n />\n }\n {...props}\n />\n );\n};\n\ntype ContentEditorInputProps = Omit<\n ContentEditorInputPropsBase,\n 'onContentChange'\n> & {\n keyPath: KeyPath[];\n dictionary: Dictionary;\n};\n\nconst ContentEditorInput: FC<ContentEditorInputProps> = ({\n keyPath,\n dictionary,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n return (\n <ContentEditorInputBase\n variant={InputVariant.DEFAULT}\n onContentChange={(newValue) =>\n addEditedContent(dictionary.localId!, newValue, keyPath)\n }\n {...props}\n />\n );\n};\n\nconst toggleContent = [\n {\n content: 'False',\n value: false,\n },\n {\n content: 'True',\n value: true,\n },\n] as SwitchSelectorChoices<boolean>;\n\ntype ContentEditorToggleProps = SwitchSelectorProps & {\n dictionary: Dictionary;\n keyPath: KeyPath[];\n};\n\nconst ContentEditorToggle: FC<ContentEditorToggleProps> = ({\n dictionary,\n keyPath,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n return (\n <SwitchSelector\n choices={toggleContent}\n value={true}\n onChange={(value) =>\n addEditedContent(dictionary.localId!, value, keyPath)\n }\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n {...props}\n />\n );\n};\n\nexport type TextEditorProps = {\n dictionary: Dictionary;\n keyPath: KeyPath[];\n section: ContentNode;\n isDarkMode?: boolean;\n renderSection?: (content: string) => ReactNode;\n onContentChange?: (newValue: string) => void;\n};\n\nconst TranslationTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}: TextEditorProps) => {\n const { locale, defaultLocale } = useLocale();\n const { selectedLocales } = useLocaleSwitcherContent();\n\n const content: any = (section as TranslationContent<string>)[\n NodeTypes.TRANSLATION\n ];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {selectedLocales.map((translationKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-translation-${translationKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full p-2 text-xs\">\n <td className=\"flex w-full\">\n {getLocaleName(translationKey, locale)}\n </td>\n </tr>\n <tr className=\"flex\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[translationKey] ??\n getEmptyNode(content[defaultLocale])\n }\n keyPath={[\n ...keyPath,\n { type: NodeTypes.TRANSLATION, key: translationKey },\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst EnumerationTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const { addEditedContent } = useEditedContent();\n const { addNewEnumeration, removeEnumeration } =\n useIntlayer('navigation-view');\n\n const content = (section as EnumerationContent<string>)[\n NodeTypes.ENUMERATION\n ];\n const firstKey = Object.keys(content)[0] as keyof typeof content;\n\n return (\n <div className=\"flex flex-col gap-2\">\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {Object.keys(\n (section as EnumerationContent<ContentNode>)[NodeTypes.ENUMERATION]\n ).map((enumKey) => {\n const childrenKeyPath = [\n ...keyPath,\n { type: NodeTypes.ENUMERATION, key: enumKey },\n ] as KeyPath[];\n const uniqueKey = `${JSON.stringify(keyPath)}-enumeration-${enumKey}`;\n\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full\">\n <td className=\"flex w-full\">\n <div className=\"flex flex-1\">\n <Button\n label={removeEnumeration.label.value}\n variant=\"hoverable\"\n size=\"sm\"\n color=\"error\"\n className=\"ml-auto text-neutral hover:text-error\"\n Icon={Trash}\n onClick={() =>\n addEditedContent(\n dictionary.localId!,\n undefined,\n childrenKeyPath\n )\n }\n >\n {removeEnumeration.text}\n </Button>\n </div>\n </td>\n </tr>\n <tr className=\"w-full p-2\">\n <td className=\"flex w-full\">\n <EnumKeyInput\n value={enumKey}\n onChange={(value) => {\n const preValueContent = (\n section as EnumerationContent<string>\n )[NodeTypes.ENUMERATION];\n\n const newValueContent = renameKey(\n preValueContent,\n enumKey as keyof typeof preValueContent,\n value\n );\n const newValue = {\n ...(section as EnumerationContent<string>),\n [NodeTypes.ENUMERATION]: newValueContent,\n };\n\n console.log('newValue', newValue);\n\n addEditedContent(\n dictionary.localId!,\n newValue,\n keyPath\n );\n }}\n />\n </td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditor\n section={\n content[enumKey as keyof typeof content] ??\n getEmptyNode(content[firstKey])\n }\n keyPath={childrenKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n\n <Button\n label={addNewEnumeration.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n isFullWidth\n onClick={() =>\n addEditedContent(\n dictionary.localId!,\n getEmptyNode(content[firstKey]) ?? '',\n [...keyPath, { type: NodeTypes.ENUMERATION, key: 'unknown' }]\n )\n }\n Icon={Plus}\n className=\"m-2\"\n >\n {addNewEnumeration.text}\n </Button>\n </div>\n );\n};\n\nconst ConditionTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as ConditionContent<string>)[NodeTypes.CONDITION];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {['true', 'false', 'fallback'].map((condKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-condition-${condKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{String(condKey)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[condKey as keyof typeof content] ??\n getEmptyNode(content.true)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.CONDITION,\n key: condKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst GenderTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as GenderContent<string>)[NodeTypes.GENDER];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {['male', 'female', 'fallback'].map((condKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-gender-${condKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{String(condKey)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[condKey as keyof typeof content] ??\n getEmptyNode(content.male)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.GENDER,\n key: condKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst PLURAL_CATEGORIES = ['zero', 'one', 'two', 'few', 'many', 'other'];\n\nconst PluralTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const content = (section as PluralContent<string>)[NodeTypes.PLURAL];\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {PLURAL_CATEGORIES.map((pluralKey) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-plural-${pluralKey}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 block w-full p-2 text-xs\">\n <td className=\"flex w-full\">{pluralKey}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n content[pluralKey as keyof typeof content] ??\n getEmptyNode(content.other)\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.PLURAL,\n key: pluralKey,\n } as KeyPath,\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nconst ArrayTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const { addEditedContent } = useEditedContent();\n const { addNewElement, removeElement } = useIntlayer('navigation-view');\n\n return (\n <div className=\"flex flex-col gap-2\">\n <table className=\"w-full\">\n <tbody className=\"flex w-full flex-col gap-2\">\n {(section as unknown as ContentNode[]).map((subSection, index) => {\n const uniqueKey = `${JSON.stringify(keyPath)}-array-${index}`;\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 w-full p-2\">\n <td className=\"flex w-full\">\n <div className=\"flex w-full items-center justify-between gap-2\">\n <span className=\"text-xs\">{String(index)}</span>\n <Button\n label={removeElement.label.value}\n variant=\"hoverable\"\n size=\"sm\"\n color=\"error\"\n className=\"ml-auto text-neutral hover:text-error\"\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: index, // Fixed: Use index instead of length\n },\n ];\n addEditedContent(\n dictionary.localId!,\n undefined,\n newKeyPath\n );\n }}\n Icon={Trash}\n >\n {removeElement.text}\n </Button>\n </div>\n </td>\n </tr>\n\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditorContainer\n section={\n subSection ??\n getEmptyNode((section as unknown as ContentNode[])[0])\n }\n keyPath={[\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: index,\n },\n ]}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n })}\n </tbody>\n </table>\n <Button\n label={addNewElement.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n isFullWidth\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: (section as unknown as ContentNode[]).length, // Keeps length for adding new items\n },\n ];\n addEditedContent(\n dictionary.localId!,\n getEmptyNode((section as unknown as ContentNode[])[0]) ?? '',\n newKeyPath,\n false\n );\n }}\n Icon={Plus}\n >\n {addNewElement.text}\n </Button>\n </div>\n );\n};\n\nconst ObjectTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n renderSection,\n}) => {\n const typedSection = section as unknown as Record<string, ContentNode>;\n const firstKey = Object.keys(typedSection)[0] as keyof typeof section;\n\n return (\n <table className=\"w-full\">\n <tbody className=\"flex flex-col gap-2\">\n {Object.keys(typedSection).map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key },\n ];\n const subSection =\n typedSection[key as keyof typeof section] ??\n getEmptyNode(typedSection[firstKey]);\n const uniqueKey = `${JSON.stringify(keyPath)}-object-${key}`;\n // Collapse any object/array (typed or plain) — only true primitives render inline.\n // getIsEditableSection can't be used here: it inspects getNodeChildren(), which for\n // translation nodes returns the first locale value (a string), causing translation\n // subtrees to be mistakenly treated as leaves and mounted all at once.\n const isLeaf = subSection === null || typeof subSection !== 'object';\n\n if (isLeaf) {\n return (\n <Fragment key={uniqueKey}>\n <tr className=\"mt-2 p-2 text-xs\">\n <td className=\"flex w-full\">{String(key)}</td>\n </tr>\n <tr className=\"block w-full\">\n <td className=\"flex w-full\">\n <TextEditor\n section={subSection}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n </Fragment>\n );\n }\n\n return (\n <tr\n key={uniqueKey}\n className=\"block w-full border-neutral/10 border-t py-1\"\n >\n <td className=\"flex w-full\">\n <CollapsibleEditor\n label={camelCaseToSentence(key)}\n section={subSection}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={renderSection}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n};\n\nenum MarkdownViewMode {\n Edit,\n Preview,\n}\n\nenum HtmlViewMode {\n Edit,\n Preview,\n}\n\nconst HtmlTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n}) => {\n const [mode, setMode] = useState(HtmlViewMode.Edit);\n const toggleContent = [\n {\n content: 'Edit',\n value: HtmlViewMode.Edit,\n },\n {\n content: 'Preview',\n value: HtmlViewMode.Preview,\n },\n ] as SwitchSelectorChoices<HtmlViewMode>;\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.HTML }];\n\n const content = (section as HTMLContent<ContentNode>)[\n NodeTypes.HTML\n ] as ContentNode;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <SwitchSelector\n choices={toggleContent}\n value={mode}\n onChange={setMode}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"ml-auto\"\n />\n\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={\n mode === HtmlViewMode.Preview\n ? (rawContent) => <SafeHtmlRenderer rawContent={rawContent} />\n : undefined\n }\n />\n </div>\n );\n};\n\nconst MarkdownTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n dictionary,\n isDarkMode,\n}) => {\n const [mode, setMode] = useState(MarkdownViewMode.Edit);\n const toggleContent = [\n {\n content: 'Edit',\n value: MarkdownViewMode.Edit,\n },\n {\n content: 'Preview',\n value: MarkdownViewMode.Preview,\n },\n ] as SwitchSelectorChoices<MarkdownViewMode>;\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.MARKDOWN }];\n\n const content = ((section as MarkdownContent<ContentNode>)[\n NodeTypes.MARKDOWN\n ] ?? '') as ContentNode;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <SwitchSelector\n choices={toggleContent}\n value={mode}\n onChange={setMode}\n color={SwitchSelectorColor.TEXT}\n size={SwitchSelectorSize.SM}\n className=\"ml-auto\"\n />\n\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n dictionary={dictionary}\n renderSection={\n mode === MarkdownViewMode.Preview\n ? (content) => (\n <Suspense fallback={<Loader />}>\n <LazyMarkdownRenderer isDarkMode={isDarkMode}>\n {content}\n </LazyMarkdownRenderer>\n </Suspense>\n )\n : undefined\n }\n />\n </div>\n );\n};\n\nconst InsertionTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n ...props\n}) => {\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.INSERTION }];\n\n const content = (section as InsertionContent<ContentNode>)[\n NodeTypes.INSERTION\n ];\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n {...props}\n />\n </div>\n );\n};\n\nconst FileTextEditor: FC<TextEditorProps> = ({\n section,\n keyPath,\n ...props\n}) => {\n const childKeyPath: KeyPath[] = [...keyPath, { type: NodeTypes.FILE }];\n\n const fileUrl = (section as FileContent)[NodeTypes.FILE];\n const { content } = section as FileContent;\n\n return (\n <div className=\"flex w-full flex-col justify-center gap-6 p-2\">\n <span className=\"text-neutral text-sm\">{fileUrl} </span>\n <TextEditorContainer\n section={content}\n keyPath={childKeyPath}\n {...props}\n />\n </div>\n );\n};\n\nconst NestedTextEditor: FC<TextEditorProps> = ({\n keyPath,\n dictionary,\n renderSection,\n section,\n ...props\n}) => {\n const { addEditedContent } = useEditedContent();\n\n const content = (section as any)[NodeTypes.NESTED];\n const childrenKeyPath = [...keyPath, { type: NodeTypes.NESTED }] as KeyPath[];\n\n return (\n <div className=\"flex w-full flex-col gap-4 p-2\">\n <Label>Dictionary key</Label>\n <ContentEditorInputBase\n aria-label=\"Edit field\"\n type=\"text\"\n variant={InputVariant.DEFAULT}\n {...props}\n onContentChange={(newValue) => {\n addEditedContent(\n dictionary.localId!,\n {\n ...content,\n dictionaryKey: String(newValue),\n },\n childrenKeyPath\n );\n }}\n >\n {content.dictionaryKey ?? ''}\n </ContentEditorInputBase>\n\n <Label>Path (optional)</Label>\n <ContentEditorInputBase\n aria-label=\"Edit field\"\n type=\"text\"\n variant={InputVariant.DEFAULT}\n {...props}\n onContentChange={(newValue) => {\n addEditedContent(\n dictionary.localId!,\n {\n ...content,\n path: newValue !== '' ? newValue : undefined,\n },\n childrenKeyPath\n );\n }}\n >\n {content.path ?? ''}\n </ContentEditorInputBase>\n </div>\n );\n};\n\nexport const TextEditor = memo<TextEditorProps>(function TextEditor({\n section,\n keyPath,\n dictionary,\n renderSection,\n isDarkMode,\n}) {\n const { tsxNotEditable } = useIntlayer('navigation-view');\n const nodeType = getNodeType(section);\n\n if (nodeType === NodeTypes.REACT_NODE) {\n return (\n <div className=\"flex w-full flex-col gap-2\">\n <span>(React Node)</span>\n <span className=\"flex text-neutral text-xs\">{tsxNotEditable}</span>\n </div>\n );\n }\n\n if (nodeType === NodeTypes.NESTED) {\n return (\n <NestedTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return (\n <TranslationTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.ENUMERATION) {\n return (\n <EnumerationTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.CONDITION) {\n return (\n <ConditionTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.GENDER) {\n return (\n <GenderTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.PLURAL) {\n return (\n <PluralTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.INSERTION) {\n return (\n <InsertionTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.MARKDOWN) {\n return (\n <MarkdownTextEditor\n dictionary={dictionary}\n keyPath={keyPath}\n section={section}\n isDarkMode={isDarkMode}\n />\n );\n }\n\n if (nodeType === NodeTypes.HTML) {\n return (\n <HtmlTextEditor\n dictionary={dictionary}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.FILE) {\n return (\n <FileTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n return (\n <ArrayTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.OBJECT) {\n return (\n <ObjectTextEditor\n dictionary={dictionary}\n renderSection={renderSection}\n keyPath={keyPath}\n section={section}\n />\n );\n }\n\n if (nodeType === NodeTypes.NUMBER) {\n return (\n <div className=\"w-full p-2\">\n <ContentEditorInput\n dictionary={dictionary}\n keyPath={keyPath}\n type=\"number\"\n aria-label=\"Edit field\"\n >\n {section as number}\n </ContentEditorInput>\n </div>\n );\n }\n\n if (nodeType === NodeTypes.TEXT) {\n return (\n <div className=\"w-full p-2\">\n {typeof renderSection === 'function' ? (\n renderSection(section as string)\n ) : (\n <ContentEditorTextArea\n variant={InputVariant.DEFAULT}\n aria-label=\"Edit field\"\n keyPath={keyPath}\n dictionary={dictionary}\n >\n {section as string}\n </ContentEditorTextArea>\n )}\n </div>\n );\n }\n\n if (nodeType === NodeTypes.BOOLEAN) {\n return (\n <div className=\"w-full p-2\">\n <ContentEditorToggle\n dictionary={dictionary}\n keyPath={keyPath}\n value={section as boolean}\n />\n </div>\n );\n }\n\n return (\n <div className=\"w-full p-2\">\n Error. Format not supported.\n {JSON.stringify(section, null, 2)}\n {JSON.stringify(keyPath, null, 2)}\n NodeType : {nodeType}\n </div>\n );\n});\n\nexport const TextEditorContainer = memo<TextEditorProps>(\n function TextEditorContainer(props) {\n return (\n <Container\n border\n background=\"none\"\n className=\"top-6 flex h-full flex-1 flex-col gap-6 overflow-hidden p-2 md:sticky\"\n roundedSize=\"2xl\"\n >\n <TextEditor {...props} />\n </Container>\n );\n }\n);\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { useSession } from "../../../hooks/useAuth/useSession.mjs";
4
- import { useAddDictionary, useGetProjects } from "../../../hooks/reactQuery.mjs";
3
+ import { useSession } from "../../../api/useAuth/useSession.mjs";
4
+ import { useAddDictionary } from "../../../api/hooks/dictionary.mjs";
5
+ import { useGetProjects } from "../../../api/hooks/project.mjs";
5
6
  import { ButtonColor } from "../../Button/Button.mjs";
6
7
  import { MultiSelect } from "../../Select/Multiselect.mjs";
7
8
  import { useForm } from "../../Form/FormBase.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"DictionaryCreationForm.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.tsx"],"sourcesContent":["'use client';\n\nimport { ButtonColor } from '@components/Button';\nimport { Form, useForm } from '@components/Form';\nimport { MultiSelect } from '@components/Select';\nimport { useAddDictionary, useGetProjects } from '@hooks/reactQuery';\nimport { useSession } from '@hooks/useAuth';\nimport type { FC } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport {\n type DictionaryFormData,\n useDictionarySchema,\n} from './useDictionaryFormSchema';\n\ntype DictionaryCreationFormProps = {\n onDictionaryCreated?: () => void;\n};\n\nexport const DictionaryCreationForm: FC<DictionaryCreationFormProps> = ({\n onDictionaryCreated,\n}) => {\n const { session } = useSession();\n const { project } = session ?? {};\n const { mutate: addDictionary, isPending } = useAddDictionary();\n const { data: projectsData } = useGetProjects();\n const DictionarySchema = useDictionarySchema(String(project?.id));\n const { form, isSubmitting } = useForm(DictionarySchema, {\n defaultValues: {\n projectIds: [project?.id],\n },\n });\n const { keyInput, createDictionaryButton, projectInput } =\n useIntlayer('dictionary-form');\n\n const onSubmitSuccess = (data: DictionaryFormData) => {\n addDictionary(\n { dictionary: data },\n {\n onSuccess: () => {\n onDictionaryCreated?.();\n },\n }\n );\n };\n\n return (\n <Form\n schema={DictionarySchema}\n onSubmitSuccess={onSubmitSuccess}\n className=\"m-auto w-full max-w-[400px]\"\n {...form}\n >\n <Form.Input\n name=\"key\"\n label={keyInput.label.value}\n placeholder={keyInput.placeholder.value}\n isRequired\n />\n\n <Form.MultiSelect name=\"projectIds\" label={projectInput.label.value}>\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n projectsData?.data?.find((project) => String(project.id) === value)\n ?.name ?? value\n }\n >\n <MultiSelect.Input placeholder={projectInput.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <MultiSelect.List>\n {projectsData?.data?.map((project) => (\n <MultiSelect.Item\n key={String(project.id)}\n value={String(project.id)}\n >\n {project.name}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </MultiSelect.Content>\n </Form.MultiSelect>\n\n <Form.Button\n className=\"mt-12 ml-auto\"\n type=\"submit\"\n color={ButtonColor.TEXT}\n isLoading={isSubmitting || isPending}\n label={createDictionaryButton.ariaLabel.value}\n isFullWidth\n >\n {createDictionaryButton.text}\n </Form.Button>\n </Form>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAkBA,MAAa,0BAA2D,EACtE,0BACI;CACJ,MAAM,EAAE,YAAY,WAAW;CAC/B,MAAM,EAAE,YAAY,WAAW,CAAC;CAChC,MAAM,EAAE,QAAQ,eAAe,cAAc,iBAAiB;CAC9D,MAAM,EAAE,MAAM,iBAAiB,eAAe;CAC9C,MAAM,mBAAmB,oBAAoB,OAAO,SAAS,EAAE,CAAC;CAChE,MAAM,EAAE,MAAM,iBAAiB,QAAQ,kBAAkB,EACvD,eAAe,EACb,YAAY,CAAC,SAAS,EAAE,EAC1B,EACF,CAAC;CACD,MAAM,EAAE,UAAU,wBAAwB,iBACxC,YAAY,iBAAiB;CAE/B,MAAM,mBAAmB,SAA6B;EACpD,cACE,EAAE,YAAY,KAAK,GACnB,EACE,iBAAiB;GACf,sBAAsB;EACxB,EACF,CACF;CACF;CAEA,OACE,qBAAC,MAAD;EACE,QAAQ;EACS;EACjB,WAAU;EACV,GAAI;YAJN;GAME,oBAAC,KAAK,OAAN;IACE,MAAK;IACL,OAAO,SAAS,MAAM;IACtB,aAAa,SAAS,YAAY;IAClC;GACD;GAED,qBAAC,KAAK,aAAN;IAAkB,MAAK;IAAa,OAAO,aAAa,MAAM;cAA9D,CACE,oBAAC,YAAY,SAAb;KACE,gBAAgB,UACd,cAAc,MAAM,MAAM,YAAY,OAAO,QAAQ,EAAE,MAAM,KAAK,GAC9D,QAAQ;eAGd,oBAAC,YAAY,OAAb,EAAmB,aAAa,aAAa,YAAY,MAAQ;IAC9C,IACrB,oBAAC,YAAY,SAAb,YACE,oBAAC,YAAY,MAAb,YACG,cAAc,MAAM,KAAK,YACxB,oBAAC,YAAY,MAAb;KAEE,OAAO,OAAO,QAAQ,EAAE;eAEvB,QAAQ;IACO,GAJX,OAAO,QAAQ,EAAE,CAIN,CACnB,EACe,GACC,EACL;;GAElB,oBAAC,KAAK,QAAN;IACE,WAAU;IACV,MAAK;IACL;IACA,WAAW,gBAAgB;IAC3B,OAAO,uBAAuB,UAAU;IACxC;cAEC,uBAAuB;GACb;EACT;;AAEV"}
1
+ {"version":3,"file":"DictionaryCreationForm.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.tsx"],"sourcesContent":["'use client';\n\nimport { useAddDictionary, useGetProjects } from '@api/index';\nimport { useSession } from '@api/useAuth';\nimport { ButtonColor } from '@components/Button';\nimport { Form, useForm } from '@components/Form';\nimport { MultiSelect } from '@components/Select';\nimport type { FC } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport {\n type DictionaryFormData,\n useDictionarySchema,\n} from './useDictionaryFormSchema';\n\ntype DictionaryCreationFormProps = {\n onDictionaryCreated?: () => void;\n};\n\nexport const DictionaryCreationForm: FC<DictionaryCreationFormProps> = ({\n onDictionaryCreated,\n}) => {\n const { session } = useSession();\n const { project } = session ?? {};\n const { mutate: addDictionary, isPending } = useAddDictionary();\n const { data: projectsData } = useGetProjects();\n const DictionarySchema = useDictionarySchema(String(project?.id));\n const { form, isSubmitting } = useForm(DictionarySchema, {\n defaultValues: {\n projectIds: [project?.id],\n },\n });\n const { keyInput, createDictionaryButton, projectInput } =\n useIntlayer('dictionary-form');\n\n const onSubmitSuccess = (data: DictionaryFormData) => {\n addDictionary(\n { dictionary: data },\n {\n onSuccess: () => {\n onDictionaryCreated?.();\n },\n }\n );\n };\n\n return (\n <Form\n schema={DictionarySchema}\n onSubmitSuccess={onSubmitSuccess}\n className=\"m-auto w-full max-w-[400px]\"\n {...form}\n >\n <Form.Input\n name=\"key\"\n label={keyInput.label.value}\n placeholder={keyInput.placeholder.value}\n isRequired\n />\n\n <Form.MultiSelect name=\"projectIds\" label={projectInput.label.value}>\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n projectsData?.data?.find((project) => String(project.id) === value)\n ?.name ?? value\n }\n >\n <MultiSelect.Input placeholder={projectInput.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <MultiSelect.List>\n {projectsData?.data?.map((project) => (\n <MultiSelect.Item\n key={String(project.id)}\n value={String(project.id)}\n >\n {project.name}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </MultiSelect.Content>\n </Form.MultiSelect>\n\n <Form.Button\n className=\"mt-12 ml-auto\"\n type=\"submit\"\n color={ButtonColor.TEXT}\n isLoading={isSubmitting || isPending}\n label={createDictionaryButton.ariaLabel.value}\n isFullWidth\n >\n {createDictionaryButton.text}\n </Form.Button>\n </Form>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAkBA,MAAa,0BAA2D,EACtE,0BACI;CACJ,MAAM,EAAE,YAAY,WAAW;CAC/B,MAAM,EAAE,YAAY,WAAW,CAAC;CAChC,MAAM,EAAE,QAAQ,eAAe,cAAc,iBAAiB;CAC9D,MAAM,EAAE,MAAM,iBAAiB,eAAe;CAC9C,MAAM,mBAAmB,oBAAoB,OAAO,SAAS,EAAE,CAAC;CAChE,MAAM,EAAE,MAAM,iBAAiB,QAAQ,kBAAkB,EACvD,eAAe,EACb,YAAY,CAAC,SAAS,EAAE,EAC1B,EACF,CAAC;CACD,MAAM,EAAE,UAAU,wBAAwB,iBACxC,YAAY,iBAAiB;CAE/B,MAAM,mBAAmB,SAA6B;EACpD,cACE,EAAE,YAAY,KAAK,GACnB,EACE,iBAAiB;GACf,sBAAsB;EACxB,EACF,CACF;CACF;CAEA,OACE,qBAAC,MAAD;EACE,QAAQ;EACS;EACjB,WAAU;EACV,GAAI;YAJN;GAME,oBAAC,KAAK,OAAN;IACE,MAAK;IACL,OAAO,SAAS,MAAM;IACtB,aAAa,SAAS,YAAY;IAClC;GACD;GAED,qBAAC,KAAK,aAAN;IAAkB,MAAK;IAAa,OAAO,aAAa,MAAM;cAA9D,CACE,oBAAC,YAAY,SAAb;KACE,gBAAgB,UACd,cAAc,MAAM,MAAM,YAAY,OAAO,QAAQ,EAAE,MAAM,KAAK,GAC9D,QAAQ;eAGd,oBAAC,YAAY,OAAb,EAAmB,aAAa,aAAa,YAAY,MAAQ;IAC9C,IACrB,oBAAC,YAAY,SAAb,YACE,oBAAC,YAAY,MAAb,YACG,cAAc,MAAM,KAAK,YACxB,oBAAC,YAAY,MAAb;KAEE,OAAO,OAAO,QAAQ,EAAE;eAEvB,QAAQ;IACO,GAJX,OAAO,QAAQ,EAAE,CAIN,CACnB,EACe,GACC,EACL;;GAElB,oBAAC,KAAK,QAAN;IACE,WAAU;IACV,MAAK;IACL;IACA,WAAW,gBAAgB;IAC3B,OAAO,uBAAuB,UAAU;IACxC;cAEC,uBAAuB;GACb;EACT;;AAEV"}
@@ -1,7 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { useSession } from "../../../hooks/useAuth/useSession.mjs";
4
- import { useAuditContentDeclarationMetadata, useGetProjects, useGetTags } from "../../../hooks/reactQuery.mjs";
3
+ import { useSession } from "../../../api/useAuth/useSession.mjs";
4
+ import { useAuditContentDeclarationMetadata } from "../../../api/hooks/ai.mjs";
5
+ import { useGetProjects } from "../../../api/hooks/project.mjs";
6
+ import { useGetTags } from "../../../api/hooks/tag.mjs";
5
7
  import { Loader } from "../../Loader/index.mjs";
6
8
  import { ButtonColor, ButtonSize, ButtonVariant } from "../../Button/Button.mjs";
7
9
  import { Checkbox } from "../../Input/Checkbox.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"DictionaryDetailsForm.mjs","names":["useForm"],"sources":["../../../../../src/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.tsx"],"sourcesContent":["'use client';\n\nimport { ButtonColor, ButtonSize, ButtonVariant } from '@components/Button';\nimport { Form, useForm } from '@components/Form';\nimport { Checkbox } from '@components/Input';\nimport { Loader } from '@components/Loader';\nimport { MultiSelect, Select } from '@components/Select';\nimport {\n useAuditContentDeclarationMetadata,\n useGetProjects,\n useGetTags,\n} from '@hooks/reactQuery';\nimport { useSession } from '@hooks/useAuth';\nimport { useEditedContent } from '@intlayer/editor-react';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { WandSparkles } from 'lucide-react';\nimport { type FC, useEffect } from 'react';\nimport { useWatch } from 'react-hook-form';\nimport { useIntlayer } from 'react-intlayer';\nimport { useDictionaryDetailsSchema } from './useDictionaryDetailsSchema';\n\ntype DictionaryDetailsProps = {\n dictionary: Dictionary;\n mode: ('local' | 'remote')[];\n};\n\nexport const DictionaryDetailsForm: FC<DictionaryDetailsProps> = ({\n dictionary,\n mode,\n}) => {\n const { session } = useSession();\n const { project } = session ?? {};\n const { data: projectsData, isLoading: isLoadingProjects } =\n useGetProjects() as any;\n const { data: tagsData } = useGetTags() as any;\n\n const projects = (projectsData?.data ?? []) as any[];\n const allTags = (tagsData?.data ?? []) as any[];\n\n const DictionaryDetailsSchema = useDictionaryDetailsSchema(\n String(project?.id)\n );\n const { form, isSubmitting } = useForm(DictionaryDetailsSchema, {\n defaultValues: {\n ...dictionary,\n location: dictionary.location ?? 'remote',\n },\n });\n const { editedContent, setEditedDictionary } = useEditedContent();\n const {\n titleInput,\n keyInput,\n descriptionInput,\n projectInput,\n tagsSelect,\n locationSelect,\n importModeSelect,\n filePathInput,\n auditButton,\n } = useIntlayer('dictionary-details');\n const { mutate: auditContentDeclaration, isPending: isAuditing } =\n useAuditContentDeclarationMetadata();\n const updatedDictionary =\n editedContent?.[dictionary.localId as LocalDictionaryId];\n\n useEffect(() => {\n form.reset({\n ...dictionary,\n tags: dictionary.tags ?? [],\n location: dictionary.location ?? 'remote',\n });\n }, [dictionary, form?.reset]);\n\n useEffect(() => {\n if (typeof updatedDictionary === 'undefined') {\n form.reset({\n ...dictionary,\n tags: dictionary.tags ?? [],\n location: dictionary.location ?? 'remote',\n });\n }\n }, [updatedDictionary]);\n\n const handleOnAuditFile = () => {\n const dictionaryToAudit = {\n ...dictionary,\n ...updatedDictionary,\n };\n\n auditContentDeclaration(\n {\n fileContent: JSON.stringify(dictionaryToAudit),\n },\n {\n onSuccess: (response) => {\n if (!response?.data) return;\n\n const auditedDictionary = response.data.fileContent;\n\n const merged = {\n ...dictionaryToAudit,\n ...auditedDictionary,\n tags: auditedDictionary.tags ?? dictionaryToAudit.tags ?? [],\n };\n\n setEditedDictionary(merged as Dictionary);\n form.reset(merged);\n },\n }\n );\n };\n\n const watchedLocation = useWatch({\n control: form.control,\n name: 'location',\n });\n const isLocalChecked =\n watchedLocation === 'local' || watchedLocation === 'hybrid';\n\n return (\n <Form\n className=\"flex w-full flex-col gap-8\"\n {...form}\n schema={DictionaryDetailsSchema}\n >\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.EditableFieldInput\n name=\"key\"\n label={keyInput.label}\n placeholder={keyInput.label.value}\n description={keyInput.description}\n disabled={isSubmitting}\n isRequired\n onSave={(value) => {\n form.setValue('key', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n key: value,\n });\n }}\n />\n <Form.EditableFieldInput\n name=\"title\"\n label={titleInput.label}\n placeholder={titleInput.placeholder.value}\n description={titleInput.description}\n disabled={isSubmitting}\n onSave={(value) => {\n form.setValue('title', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n title: value,\n });\n }}\n />\n </div>\n <Form.EditableFieldTextArea\n name=\"description\"\n label={descriptionInput.label}\n placeholder={descriptionInput.placeholder.value}\n description={descriptionInput.description}\n disabled={isSubmitting}\n onSave={(value) => {\n form.setValue('description', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n description: value,\n });\n }}\n />\n <div className=\"grid grid-cols-2 gap-8 px-1 max-md:grid-cols-1\">\n <Form.Field\n control={form.control}\n name=\"location\"\n render={({ field }) => {\n const value = field.value;\n const isLocal = value === 'local' || value === 'hybrid';\n const isRemote = value === 'remote' || value === 'hybrid';\n\n const handleLocalToggle = (isChecked: boolean) => {\n if (!isChecked && !isRemote) return;\n\n const newValue: Dictionary['location'] = isChecked\n ? isRemote\n ? 'hybrid'\n : 'local'\n : 'remote';\n\n field.onChange(newValue);\n\n const newFilePath = isChecked\n ? (form.getValues('filePath') ?? dictionary.filePath)\n : undefined;\n\n if (!isChecked) {\n form.setValue('filePath', undefined);\n }\n\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n location: newValue,\n filePath: newFilePath,\n });\n };\n\n const handleRemoteToggle = (isChecked: boolean) => {\n if (!isChecked && !isLocal) return;\n\n const newValue: Dictionary['location'] = isChecked\n ? isLocal\n ? 'hybrid'\n : 'remote'\n : 'local';\n\n field.onChange(newValue);\n\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n location: newValue,\n });\n };\n\n return (\n <Form.Item className=\"flex flex-col gap-2 px-1\">\n <Form.Label className=\"ml-1\">{locationSelect.label}</Form.Label>\n <div className=\"ml-2 flex items-center gap-4 py-2\">\n <Checkbox\n id=\"location-local\"\n name=\"location-local\"\n label={locationSelect.local.value}\n color=\"text\"\n checked={isLocal}\n disabled={\n !mode.includes('local') && !mode.includes('remote')\n }\n onChange={(e) => handleLocalToggle(e.target.checked)}\n />\n <Checkbox\n id=\"location-remote\"\n name=\"location-remote\"\n label={locationSelect.remote.value}\n color=\"text\"\n checked={isRemote}\n disabled={\n !mode.includes('remote') &&\n dictionary.location !== 'remote' &&\n dictionary.location !== 'hybrid'\n }\n onChange={(e) => handleRemoteToggle(e.target.checked)}\n />\n </div>\n <Form.Description>\n {locationSelect.testDescription}\n </Form.Description>\n <Form.Message />\n </Form.Item>\n );\n }}\n />\n\n <AnimatePresence mode=\"wait\">\n {isLocalChecked && (\n <motion.div\n key=\"filePath-input\"\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n transition={{ duration: 0.3 }}\n className=\"overflow-hidden\"\n >\n <Form.Input\n name=\"filePath\"\n label={filePathInput.label.value}\n placeholder={filePathInput.placeholder.value}\n description={filePathInput.description.value}\n disabled={isSubmitting || !isLocalChecked}\n onChange={(e) => {\n const value = e.target.value;\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n filePath: value,\n });\n }}\n />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.Select\n name=\"importMode\"\n label={importModeSelect.label.value}\n description={importModeSelect.description.value}\n onValueChange={(value) => {\n form.setValue('importMode', value as any, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n importMode: value as any,\n });\n }}\n >\n <Select.Trigger>\n <Select.Value placeholder={importModeSelect.label.value} />\n </Select.Trigger>\n <Select.Content>\n <Select.Item value=\"static\">\n {importModeSelect.static.value}\n </Select.Item>\n <Select.Item value=\"dynamic\">\n {importModeSelect.dynamic.value}\n </Select.Item>\n <Select.Item value=\"live\">\n {importModeSelect.live.value}\n </Select.Item>\n </Select.Content>\n </Form.Select>\n </div>\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.MultiSelect\n name=\"projectIds\"\n label={projectInput.label.value}\n description={projectInput.description}\n onValueChange={(value) => {\n const valueArray = [value].flat();\n form.setValue('projectIds', valueArray, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n projectIds: valueArray,\n });\n }}\n >\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n projects?.find((project: any) => String(project.id) === value)\n ?.name ?? value\n }\n >\n <MultiSelect.Input placeholder={projectInput.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <Loader isLoading={isLoadingProjects}>\n <MultiSelect.List>\n {projects?.map((project: any) => (\n <MultiSelect.Item\n key={String(project.id)}\n value={String(project.id)}\n >\n {project.name}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </Loader>\n </MultiSelect.Content>\n </Form.MultiSelect>\n\n <Form.MultiSelect\n name=\"tags\"\n label={tagsSelect.label.value}\n description={tagsSelect.description}\n onValueChange={(value) => {\n const valueArray = [value].flat();\n form.setValue('tags', valueArray, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n tags: valueArray,\n });\n }}\n >\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n allTags?.find((tag: any) => String(tag.key) === value)?.name ??\n value\n }\n >\n <MultiSelect.Input placeholder={tagsSelect.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <Loader isLoading={isLoadingProjects}>\n <MultiSelect.List>\n {allTags?.map((tag: any) => (\n <MultiSelect.Item\n key={String(tag.key)}\n value={String(tag.key)}\n >\n {tag.name ?? tag.key}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </Loader>\n </MultiSelect.Content>\n </Form.MultiSelect>\n </div>\n\n <div className=\"flex flex-wrap items-center justify-end gap-2 max-md:flex-col\">\n <Form.Button\n type=\"button\"\n size={ButtonSize.ICON_MD}\n label={auditButton.label.value}\n Icon={WandSparkles}\n variant={ButtonVariant.OUTLINE}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n onClick={handleOnAuditFile}\n disabled={isSubmitting || isAuditing}\n isLoading={isAuditing}\n />\n </div>\n </Form>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,yBAAqD,EAChE,YACA,WACI;CACJ,MAAM,EAAE,YAAY,WAAW;CAC/B,MAAM,EAAE,YAAY,WAAW,CAAC;CAChC,MAAM,EAAE,MAAM,cAAc,WAAW,sBACrC,eAAe;CACjB,MAAM,EAAE,MAAM,aAAa,WAAW;CAEtC,MAAM,WAAY,cAAc,QAAQ,CAAC;CACzC,MAAM,UAAW,UAAU,QAAQ,CAAC;CAEpC,MAAM,0BAA0B,2BAC9B,OAAO,SAAS,EAAE,CACpB;CACA,MAAM,EAAE,MAAM,iBAAiBA,UAAQ,yBAAyB,EAC9D,eAAe;EACb,GAAG;EACH,UAAU,WAAW,YAAY;CACnC,EACF,CAAC;CACD,MAAM,EAAE,eAAe,wBAAwB,iBAAiB;CAChE,MAAM,EACJ,YACA,UACA,kBACA,cACA,YACA,gBACA,kBACA,eACA,gBACE,YAAY,oBAAoB;CACpC,MAAM,EAAE,QAAQ,yBAAyB,WAAW,eAClD,mCAAmC;CACrC,MAAM,oBACJ,gBAAgB,WAAW;CAE7B,gBAAgB;EACd,KAAK,MAAM;GACT,GAAG;GACH,MAAM,WAAW,QAAQ,CAAC;GAC1B,UAAU,WAAW,YAAY;EACnC,CAAC;CACH,GAAG,CAAC,YAAY,MAAM,KAAK,CAAC;CAE5B,gBAAgB;EACd,IAAI,OAAO,sBAAsB,aAC/B,KAAK,MAAM;GACT,GAAG;GACH,MAAM,WAAW,QAAQ,CAAC;GAC1B,UAAU,WAAW,YAAY;EACnC,CAAC;CAEL,GAAG,CAAC,iBAAiB,CAAC;CAEtB,MAAM,0BAA0B;EAC9B,MAAM,oBAAoB;GACxB,GAAG;GACH,GAAG;EACL;EAEA,wBACE,EACE,aAAa,KAAK,UAAU,iBAAiB,EAC/C,GACA,EACE,YAAY,aAAa;GACvB,IAAI,CAAC,UAAU,MAAM;GAErB,MAAM,oBAAoB,SAAS,KAAK;GAExC,MAAM,SAAS;IACb,GAAG;IACH,GAAG;IACH,MAAM,kBAAkB,QAAQ,kBAAkB,QAAQ,CAAC;GAC7D;GAEA,oBAAoB,MAAoB;GACxC,KAAK,MAAM,MAAM;EACnB,EACF,CACF;CACF;CAEA,MAAM,kBAAkB,SAAS;EAC/B,SAAS,KAAK;EACd,MAAM;CACR,CAAC;CACD,MAAM,iBACJ,oBAAoB,WAAW,oBAAoB;CAErD,OACE,qBAAC,MAAD;EACE,WAAU;EACV,GAAI;EACJ,QAAQ;YAHV;GAKE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,KAAK,oBAAN;KACE,MAAK;KACL,OAAO,SAAS;KAChB,aAAa,SAAS,MAAM;KAC5B,aAAa,SAAS;KACtB,UAAU;KACV;KACA,SAAS,UAAU;MACjB,KAAK,SAAS,OAAO,OAAO,EAAE,aAAa,KAAK,CAAC;MACjD,oBAAoB;OAClB,GAAG;OACH,GAAI,qBAAqB,CAAC;OAC1B,KAAK;MACP,CAAC;KACH;IACD,IACD,oBAAC,KAAK,oBAAN;KACE,MAAK;KACL,OAAO,WAAW;KAClB,aAAa,WAAW,YAAY;KACpC,aAAa,WAAW;KACxB,UAAU;KACV,SAAS,UAAU;MACjB,KAAK,SAAS,SAAS,OAAO,EAAE,aAAa,KAAK,CAAC;MACnD,oBAAoB;OAClB,GAAG;OACH,GAAI,qBAAqB,CAAC;OAC1B,OAAO;MACT,CAAC;KACH;IACD,EACE;;GACL,oBAAC,KAAK,uBAAN;IACE,MAAK;IACL,OAAO,iBAAiB;IACxB,aAAa,iBAAiB,YAAY;IAC1C,aAAa,iBAAiB;IAC9B,UAAU;IACV,SAAS,UAAU;KACjB,KAAK,SAAS,eAAe,OAAO,EAAE,aAAa,KAAK,CAAC;KACzD,oBAAoB;MAClB,GAAG;MACH,GAAI,qBAAqB,CAAC;MAC1B,aAAa;KACf,CAAC;IACH;GACD;GACD,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,KAAK,OAAN;KACE,SAAS,KAAK;KACd,MAAK;KACL,SAAS,EAAE,YAAY;MACrB,MAAM,QAAQ,MAAM;MACpB,MAAM,UAAU,UAAU,WAAW,UAAU;MAC/C,MAAM,WAAW,UAAU,YAAY,UAAU;MAEjD,MAAM,qBAAqB,cAAuB;OAChD,IAAI,CAAC,aAAa,CAAC,UAAU;OAE7B,MAAM,WAAmC,YACrC,WACE,WACA,UACF;OAEJ,MAAM,SAAS,QAAQ;OAEvB,MAAM,cAAc,YACf,KAAK,UAAU,UAAU,KAAK,WAAW,WAC1C;OAEJ,IAAI,CAAC,WACH,KAAK,SAAS,YAAY,MAAS;OAGrC,oBAAoB;QAClB,GAAG;QACH,GAAI,qBAAqB,CAAC;QAC1B,UAAU;QACV,UAAU;OACZ,CAAC;MACH;MAEA,MAAM,sBAAsB,cAAuB;OACjD,IAAI,CAAC,aAAa,CAAC,SAAS;OAE5B,MAAM,WAAmC,YACrC,UACE,WACA,WACF;OAEJ,MAAM,SAAS,QAAQ;OAEvB,oBAAoB;QAClB,GAAG;QACH,GAAI,qBAAqB,CAAC;QAC1B,UAAU;OACZ,CAAC;MACH;MAEA,OACE,qBAAC,KAAK,MAAN;OAAW,WAAU;iBAArB;QACE,oBAAC,KAAK,OAAN;SAAY,WAAU;mBAAQ,eAAe;QAAkB;QAC/D,qBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,oBAAC,UAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,eAAe,MAAM;UAC5B,OAAM;UACN,SAAS;UACT,UACE,CAAC,KAAK,SAAS,OAAO,KAAK,CAAC,KAAK,SAAS,QAAQ;UAEpD,WAAW,MAAM,kBAAkB,EAAE,OAAO,OAAO;SACpD,IACD,oBAAC,UAAD;UACE,IAAG;UACH,MAAK;UACL,OAAO,eAAe,OAAO;UAC7B,OAAM;UACN,SAAS;UACT,UACE,CAAC,KAAK,SAAS,QAAQ,KACvB,WAAW,aAAa,YACxB,WAAW,aAAa;UAE1B,WAAW,MAAM,mBAAmB,EAAE,OAAO,OAAO;SACrD,EACE;;QACL,oBAAC,KAAK,aAAN,YACG,eAAe,gBACA;QAClB,oBAAC,KAAK,SAAN,CAAe;OACN;;KAEf;IACD,IAED,oBAAC,iBAAD;KAAiB,MAAK;eACnB,kBACC,oBAAC,OAAO,KAAR;MAEE,SAAS;OAAE,SAAS;OAAG,QAAQ;MAAE;MACjC,SAAS;OAAE,SAAS;OAAG,QAAQ;MAAO;MACtC,MAAM;OAAE,SAAS;OAAG,QAAQ;MAAE;MAC9B,YAAY,EAAE,UAAU,GAAI;MAC5B,WAAU;gBAEV,oBAAC,KAAK,OAAN;OACE,MAAK;OACL,OAAO,cAAc,MAAM;OAC3B,aAAa,cAAc,YAAY;OACvC,aAAa,cAAc,YAAY;OACvC,UAAU,gBAAgB,CAAC;OAC3B,WAAW,MAAM;QACf,MAAM,QAAQ,EAAE,OAAO;QACvB,oBAAoB;SAClB,GAAG;SACH,GAAI,qBAAqB,CAAC;SAC1B,UAAU;QACZ,CAAC;OACH;MACD;KACS,GAtBN,gBAsBM;IAEC,EACd;;GACL,oBAAC,OAAD;IAAK,WAAU;cACb,qBAAC,KAAK,QAAN;KACE,MAAK;KACL,OAAO,iBAAiB,MAAM;KAC9B,aAAa,iBAAiB,YAAY;KAC1C,gBAAgB,UAAU;MACxB,KAAK,SAAS,cAAc,OAAc,EAAE,aAAa,KAAK,CAAC;MAC/D,oBAAoB;OAClB,GAAG;OACH,GAAI,qBAAqB,CAAC;OAC1B,YAAY;MACd,CAAC;KACH;eAXF,CAaE,oBAAC,OAAO,SAAR,YACE,oBAAC,OAAO,OAAR,EAAc,aAAa,iBAAiB,MAAM,MAAQ,GAC5C,IAChB,qBAAC,OAAO,SAAR;MACE,oBAAC,OAAO,MAAR;OAAa,OAAM;iBAChB,iBAAiB,OAAO;MACd;MACb,oBAAC,OAAO,MAAR;OAAa,OAAM;iBAChB,iBAAiB,QAAQ;MACf;MACb,oBAAC,OAAO,MAAR;OAAa,OAAM;iBAChB,iBAAiB,KAAK;MACZ;KACC,IACL;;GACV;GACL,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,qBAAC,KAAK,aAAN;KACE,MAAK;KACL,OAAO,aAAa,MAAM;KAC1B,aAAa,aAAa;KAC1B,gBAAgB,UAAU;MACxB,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK;MAChC,KAAK,SAAS,cAAc,YAAY,EAAE,aAAa,KAAK,CAAC;MAC7D,oBAAoB;OAClB,GAAG;OACH,GAAI,qBAAqB,CAAC;OAC1B,YAAY;MACd,CAAC;KACH;eAZF,CAcE,oBAAC,YAAY,SAAb;MACE,gBAAgB,UACd,UAAU,MAAM,YAAiB,OAAO,QAAQ,EAAE,MAAM,KAAK,GACzD,QAAQ;gBAGd,oBAAC,YAAY,OAAb,EAAmB,aAAa,aAAa,YAAY,MAAQ;KAC9C,IACrB,oBAAC,YAAY,SAAb,YACE,oBAAC,QAAD;MAAQ,WAAW;gBACjB,oBAAC,YAAY,MAAb,YACG,UAAU,KAAK,YACd,oBAAC,YAAY,MAAb;OAEE,OAAO,OAAO,QAAQ,EAAE;iBAEvB,QAAQ;MACO,GAJX,OAAO,QAAQ,EAAE,CAIN,CACnB,EACe;KACZ,GACW,EACL;QAElB,qBAAC,KAAK,aAAN;KACE,MAAK;KACL,OAAO,WAAW,MAAM;KACxB,aAAa,WAAW;KACxB,gBAAgB,UAAU;MACxB,MAAM,aAAa,CAAC,KAAK,EAAE,KAAK;MAChC,KAAK,SAAS,QAAQ,YAAY,EAAE,aAAa,KAAK,CAAC;MACvD,oBAAoB;OAClB,GAAG;OACH,GAAI,qBAAqB,CAAC;OAC1B,MAAM;MACR,CAAC;KACH;eAZF,CAcE,oBAAC,YAAY,SAAb;MACE,gBAAgB,UACd,SAAS,MAAM,QAAa,OAAO,IAAI,GAAG,MAAM,KAAK,GAAG,QACxD;gBAGF,oBAAC,YAAY,OAAb,EAAmB,aAAa,WAAW,YAAY,MAAQ;KAC5C,IACrB,oBAAC,YAAY,SAAb,YACE,oBAAC,QAAD;MAAQ,WAAW;gBACjB,oBAAC,YAAY,MAAb,YACG,SAAS,KAAK,QACb,oBAAC,YAAY,MAAb;OAEE,OAAO,OAAO,IAAI,GAAG;iBAEpB,IAAI,QAAQ,IAAI;MACD,GAJX,OAAO,IAAI,GAAG,CAIH,CACnB,EACe;KACZ,GACW,EACL;MACf;;GAEL,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,KAAK,QAAN;KACE,MAAK;KACL;KACA,OAAO,YAAY,MAAM;KACzB,MAAM;KACN;KACA;KACA,WAAU;KACV,SAAS;KACT,UAAU,gBAAgB;KAC1B,WAAW;IACZ;GACE;EACD;;AAEV"}
1
+ {"version":3,"file":"DictionaryDetailsForm.mjs","names":["useForm"],"sources":["../../../../../src/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.tsx"],"sourcesContent":["'use client';\n\nimport {\n useAuditContentDeclarationMetadata,\n useGetProjects,\n useGetTags,\n} from '@api/index';\nimport { useSession } from '@api/useAuth';\nimport { ButtonColor, ButtonSize, ButtonVariant } from '@components/Button';\nimport { Form, useForm } from '@components/Form';\nimport { Checkbox } from '@components/Input';\nimport { Loader } from '@components/Loader';\nimport { MultiSelect, Select } from '@components/Select';\nimport { useEditedContent } from '@intlayer/editor-react';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { WandSparkles } from 'lucide-react';\nimport { type FC, useEffect } from 'react';\nimport { useWatch } from 'react-hook-form';\nimport { useIntlayer } from 'react-intlayer';\nimport { useDictionaryDetailsSchema } from './useDictionaryDetailsSchema';\n\ntype DictionaryDetailsProps = {\n dictionary: Dictionary;\n mode: ('local' | 'remote')[];\n};\n\nexport const DictionaryDetailsForm: FC<DictionaryDetailsProps> = ({\n dictionary,\n mode,\n}) => {\n const { session } = useSession();\n const { project } = session ?? {};\n const { data: projectsData, isLoading: isLoadingProjects } =\n useGetProjects() as any;\n const { data: tagsData } = useGetTags() as any;\n\n const projects = (projectsData?.data ?? []) as any[];\n const allTags = (tagsData?.data ?? []) as any[];\n\n const DictionaryDetailsSchema = useDictionaryDetailsSchema(\n String(project?.id)\n );\n const { form, isSubmitting } = useForm(DictionaryDetailsSchema, {\n defaultValues: {\n ...dictionary,\n location: dictionary.location ?? 'remote',\n },\n });\n const { editedContent, setEditedDictionary } = useEditedContent();\n const {\n titleInput,\n keyInput,\n descriptionInput,\n projectInput,\n tagsSelect,\n locationSelect,\n importModeSelect,\n filePathInput,\n auditButton,\n } = useIntlayer('dictionary-details');\n const { mutate: auditContentDeclaration, isPending: isAuditing } =\n useAuditContentDeclarationMetadata();\n const updatedDictionary =\n editedContent?.[dictionary.localId as LocalDictionaryId];\n\n useEffect(() => {\n form.reset({\n ...dictionary,\n tags: dictionary.tags ?? [],\n location: dictionary.location ?? 'remote',\n });\n }, [dictionary, form?.reset]);\n\n useEffect(() => {\n if (typeof updatedDictionary === 'undefined') {\n form.reset({\n ...dictionary,\n tags: dictionary.tags ?? [],\n location: dictionary.location ?? 'remote',\n });\n }\n }, [updatedDictionary]);\n\n const handleOnAuditFile = () => {\n const dictionaryToAudit = {\n ...dictionary,\n ...updatedDictionary,\n };\n\n auditContentDeclaration(\n {\n fileContent: JSON.stringify(dictionaryToAudit),\n },\n {\n onSuccess: (response) => {\n if (!response?.data) return;\n\n const auditedDictionary = response.data.fileContent;\n\n const merged = {\n ...dictionaryToAudit,\n ...auditedDictionary,\n tags: auditedDictionary.tags ?? dictionaryToAudit.tags ?? [],\n };\n\n setEditedDictionary(merged as Dictionary);\n form.reset(merged);\n },\n }\n );\n };\n\n const watchedLocation = useWatch({\n control: form.control,\n name: 'location',\n });\n const isLocalChecked =\n watchedLocation === 'local' || watchedLocation === 'hybrid';\n\n return (\n <Form\n className=\"flex w-full flex-col gap-8\"\n {...form}\n schema={DictionaryDetailsSchema}\n >\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.EditableFieldInput\n name=\"key\"\n label={keyInput.label}\n placeholder={keyInput.label.value}\n description={keyInput.description}\n disabled={isSubmitting}\n isRequired\n onSave={(value) => {\n form.setValue('key', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n key: value,\n });\n }}\n />\n <Form.EditableFieldInput\n name=\"title\"\n label={titleInput.label}\n placeholder={titleInput.placeholder.value}\n description={titleInput.description}\n disabled={isSubmitting}\n onSave={(value) => {\n form.setValue('title', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n title: value,\n });\n }}\n />\n </div>\n <Form.EditableFieldTextArea\n name=\"description\"\n label={descriptionInput.label}\n placeholder={descriptionInput.placeholder.value}\n description={descriptionInput.description}\n disabled={isSubmitting}\n onSave={(value) => {\n form.setValue('description', value, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n description: value,\n });\n }}\n />\n <div className=\"grid grid-cols-2 gap-8 px-1 max-md:grid-cols-1\">\n <Form.Field\n control={form.control}\n name=\"location\"\n render={({ field }) => {\n const value = field.value;\n const isLocal = value === 'local' || value === 'hybrid';\n const isRemote = value === 'remote' || value === 'hybrid';\n\n const handleLocalToggle = (isChecked: boolean) => {\n if (!isChecked && !isRemote) return;\n\n const newValue: Dictionary['location'] = isChecked\n ? isRemote\n ? 'hybrid'\n : 'local'\n : 'remote';\n\n field.onChange(newValue);\n\n const newFilePath = isChecked\n ? (form.getValues('filePath') ?? dictionary.filePath)\n : undefined;\n\n if (!isChecked) {\n form.setValue('filePath', undefined);\n }\n\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n location: newValue,\n filePath: newFilePath,\n });\n };\n\n const handleRemoteToggle = (isChecked: boolean) => {\n if (!isChecked && !isLocal) return;\n\n const newValue: Dictionary['location'] = isChecked\n ? isLocal\n ? 'hybrid'\n : 'remote'\n : 'local';\n\n field.onChange(newValue);\n\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n location: newValue,\n });\n };\n\n return (\n <Form.Item className=\"flex flex-col gap-2 px-1\">\n <Form.Label className=\"ml-1\">{locationSelect.label}</Form.Label>\n <div className=\"ml-2 flex items-center gap-4 py-2\">\n <Checkbox\n id=\"location-local\"\n name=\"location-local\"\n label={locationSelect.local.value}\n color=\"text\"\n checked={isLocal}\n disabled={\n !mode.includes('local') && !mode.includes('remote')\n }\n onChange={(e) => handleLocalToggle(e.target.checked)}\n />\n <Checkbox\n id=\"location-remote\"\n name=\"location-remote\"\n label={locationSelect.remote.value}\n color=\"text\"\n checked={isRemote}\n disabled={\n !mode.includes('remote') &&\n dictionary.location !== 'remote' &&\n dictionary.location !== 'hybrid'\n }\n onChange={(e) => handleRemoteToggle(e.target.checked)}\n />\n </div>\n <Form.Description>\n {locationSelect.testDescription}\n </Form.Description>\n <Form.Message />\n </Form.Item>\n );\n }}\n />\n\n <AnimatePresence mode=\"wait\">\n {isLocalChecked && (\n <motion.div\n key=\"filePath-input\"\n initial={{ opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: 'auto' }}\n exit={{ opacity: 0, height: 0 }}\n transition={{ duration: 0.3 }}\n className=\"overflow-hidden\"\n >\n <Form.Input\n name=\"filePath\"\n label={filePathInput.label.value}\n placeholder={filePathInput.placeholder.value}\n description={filePathInput.description.value}\n disabled={isSubmitting || !isLocalChecked}\n onChange={(e) => {\n const value = e.target.value;\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n filePath: value,\n });\n }}\n />\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.Select\n name=\"importMode\"\n label={importModeSelect.label.value}\n description={importModeSelect.description.value}\n onValueChange={(value) => {\n form.setValue('importMode', value as any, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n importMode: value as any,\n });\n }}\n >\n <Select.Trigger>\n <Select.Value placeholder={importModeSelect.label.value} />\n </Select.Trigger>\n <Select.Content>\n <Select.Item value=\"static\">\n {importModeSelect.static.value}\n </Select.Item>\n <Select.Item value=\"dynamic\">\n {importModeSelect.dynamic.value}\n </Select.Item>\n <Select.Item value=\"live\">\n {importModeSelect.live.value}\n </Select.Item>\n </Select.Content>\n </Form.Select>\n </div>\n <div className=\"grid grid-cols-2 gap-8 max-md:grid-cols-1\">\n <Form.MultiSelect\n name=\"projectIds\"\n label={projectInput.label.value}\n description={projectInput.description}\n onValueChange={(value) => {\n const valueArray = [value].flat();\n form.setValue('projectIds', valueArray, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n projectIds: valueArray,\n });\n }}\n >\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n projects?.find((project: any) => String(project.id) === value)\n ?.name ?? value\n }\n >\n <MultiSelect.Input placeholder={projectInput.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <Loader isLoading={isLoadingProjects}>\n <MultiSelect.List>\n {projects?.map((project: any) => (\n <MultiSelect.Item\n key={String(project.id)}\n value={String(project.id)}\n >\n {project.name}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </Loader>\n </MultiSelect.Content>\n </Form.MultiSelect>\n\n <Form.MultiSelect\n name=\"tags\"\n label={tagsSelect.label.value}\n description={tagsSelect.description}\n onValueChange={(value) => {\n const valueArray = [value].flat();\n form.setValue('tags', valueArray, { shouldDirty: true });\n setEditedDictionary({\n ...dictionary,\n ...(updatedDictionary ?? {}),\n tags: valueArray,\n });\n }}\n >\n <MultiSelect.Trigger\n getBadgeValue={(value) =>\n allTags?.find((tag: any) => String(tag.key) === value)?.name ??\n value\n }\n >\n <MultiSelect.Input placeholder={tagsSelect.placeholder.value} />\n </MultiSelect.Trigger>\n <MultiSelect.Content>\n <Loader isLoading={isLoadingProjects}>\n <MultiSelect.List>\n {allTags?.map((tag: any) => (\n <MultiSelect.Item\n key={String(tag.key)}\n value={String(tag.key)}\n >\n {tag.name ?? tag.key}\n </MultiSelect.Item>\n ))}\n </MultiSelect.List>\n </Loader>\n </MultiSelect.Content>\n </Form.MultiSelect>\n </div>\n\n <div className=\"flex flex-wrap items-center justify-end gap-2 max-md:flex-col\">\n <Form.Button\n type=\"button\"\n size={ButtonSize.ICON_MD}\n label={auditButton.label.value}\n Icon={WandSparkles}\n variant={ButtonVariant.OUTLINE}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n onClick={handleOnAuditFile}\n disabled={isSubmitting || isAuditing}\n isLoading={isAuditing}\n />\n </div>\n </Form>\n );\n};\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import { cn } from "../../../utils/cn.mjs";
4
- import { useAuth } from "../../../hooks/useAuth/useAuth.mjs";
5
- import { useDeleteDictionary, usePushDictionaries, useWriteDictionary } from "../../../hooks/reactQuery.mjs";
4
+ import { useAuth } from "../../../api/useAuth/useAuth.mjs";
5
+ import { useDeleteDictionary, usePushDictionaries } from "../../../api/hooks/dictionary.mjs";
6
+ import { useWriteDictionary } from "../../../api/hooks/editor.mjs";
6
7
  import { ButtonColor, ButtonVariant } from "../../Button/Button.mjs";
7
8
  import { Form } from "../../Form/Form.mjs";
8
9
  import { Modal, ModalSize } from "../../Modal/Modal.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"SaveForm.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/SaveForm/SaveForm.tsx"],"sourcesContent":["'use client';\n\nimport { ButtonColor, ButtonVariant } from '@components/Button';\nimport { Form } from '@components/Form';\nimport { Modal, ModalSize } from '@components/Modal';\nimport {\n useAuth,\n useDeleteDictionary,\n usePushDictionaries,\n useWriteDictionary,\n} from '@hooks/index';\nimport type { Dictionary as DistantDictionary } from '@intlayer/backend';\nimport {\n useDictionariesRecordActions,\n useEditedContent,\n} from '@intlayer/editor-react';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { cn } from '@utils/cn';\nimport {\n ArrowUpFromLine,\n Download,\n RotateCcw,\n Save,\n Trash,\n} from 'lucide-react';\nimport {\n type DetailedHTMLProps,\n type FC,\n type FormHTMLAttributes,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\ntype DictionaryDetailsProps = {\n dictionary: Dictionary;\n mode: ('local' | 'remote')[];\n onDelete?: () => void;\n onSave?: () => void;\n} & DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>;\n\nexport const SaveForm: FC<DictionaryDetailsProps> = ({\n dictionary,\n mode,\n className,\n onDelete,\n onSave,\n ...props\n}) => {\n const [isFormatAlertModalOpen, setIsFormatAlertModalOpen] = useState(false);\n const { setLocaleDictionary } = useDictionariesRecordActions();\n const { mutate: deleteDictionary, isPending: isDeleting } =\n useDeleteDictionary();\n const { mutate: writeDictionary, isPending: isWriting } =\n useWriteDictionary();\n const { mutate: pushDictionaries, isPending: isPushing } =\n usePushDictionaries();\n const isLoading = isWriting || isPushing;\n\n const { editedContent, restoreEditedContent } = useEditedContent();\n const {\n deleteButton,\n resetButton,\n saveButton,\n publishButton,\n downloadButton,\n confirmation,\n } = useIntlayer('save-dictionary-details');\n const { isAuthenticated } = useAuth();\n\n const editedDictionary = editedContent?.[dictionary.localId!];\n\n const isEdited =\n editedDictionary &&\n JSON.stringify(editedDictionary) !== JSON.stringify(dictionary);\n\n const isDistantDictionary =\n typeof (dictionary as unknown as DistantDictionary)?.id !== 'undefined';\n\n const handleSaveDictionaryConfirmation = async () => {\n if (!editedContent?.[dictionary.localId!]) return;\n\n const updatedDictionary = {\n ...dictionary,\n ...editedContent?.[dictionary.localId!],\n };\n\n writeDictionary(\n {\n dictionary: updatedDictionary,\n },\n {\n onSuccess: () => {\n setLocaleDictionary(editedContent?.[dictionary.localId!]);\n restoreEditedContent(dictionary.localId!);\n setIsFormatAlertModalOpen(false);\n onSave?.();\n },\n }\n );\n };\n\n const handlePushDictionary = () => {\n const updatedDictionary = {\n ...dictionary,\n ...editedContent?.[dictionary.localId!],\n };\n\n pushDictionaries(\n { dictionaries: [updatedDictionary] },\n {\n onSuccess: (res) => {\n if (res) {\n setLocaleDictionary(updatedDictionary);\n restoreEditedContent(dictionary.localId!);\n onSave?.();\n }\n },\n }\n );\n };\n\n const handleDeleteDictionary = () => {\n if (!dictionary.id) return;\n\n deleteDictionary(\n {\n dictionaryId: dictionary.id,\n },\n {\n onSuccess: (res) => {\n if (res) {\n onDelete?.();\n }\n },\n }\n );\n };\n\n return (\n <>\n <Modal\n isOpen={isFormatAlertModalOpen}\n title={confirmation.title.value}\n size={ModalSize.MD}\n onClose={() => setIsFormatAlertModalOpen(false)}\n padding=\"md\"\n >\n <form className=\"size-full\">\n <p className=\"py-4 text-neutral text-sm\">{confirmation.message}</p>\n\n <div className=\"mt-12 flex justify-end gap-2 max-md:flex-col\">\n <Form.Button\n label={confirmation.cancelButton.label.value}\n disabled={!isEdited || isLoading}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n variant={ButtonVariant.OUTLINE}\n onClick={() => setIsFormatAlertModalOpen(false)}\n >\n {confirmation.cancelButton.text}\n </Form.Button>\n <Form.Button\n label={confirmation.confirmButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Save}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handleSaveDictionaryConfirmation}\n >\n {confirmation.confirmButton.text}\n </Form.Button>\n </div>\n </form>\n </Modal>\n <form className={cn('flex justify-end gap-2', className)} {...props}>\n {mode.includes('remote') &&\n isDistantDictionary &&\n onDelete &&\n isAuthenticated && (\n <Form.Button\n label={deleteButton.label.value}\n Icon={Trash}\n color={ButtonColor.ERROR}\n variant={ButtonVariant.OUTLINE}\n className=\"max-md:w-full\"\n isLoading={isDeleting}\n onClick={handleDeleteDictionary}\n >\n {deleteButton.text}\n </Form.Button>\n )}\n {isEdited && (\n <Form.Button\n label={resetButton.label.value}\n disabled={!isEdited}\n Icon={RotateCcw}\n variant={ButtonVariant.OUTLINE}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n onClick={() => restoreEditedContent(dictionary.localId!)}\n >\n {resetButton.text}\n </Form.Button>\n )}\n {mode.includes('local') && (\n <Form.Button\n label={downloadButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Download}\n color={ButtonColor.TEXT}\n variant={\n isAuthenticated ? ButtonVariant.OUTLINE : ButtonVariant.DEFAULT\n }\n className=\"max-md:w-full\"\n isLoading={isWriting}\n onClick={() => setIsFormatAlertModalOpen(true)}\n >\n {downloadButton.text}\n </Form.Button>\n )}\n {mode.includes('remote') && isAuthenticated && !isDistantDictionary && (\n <Form.Button\n label={publishButton.label.value}\n disabled={isLoading}\n Icon={ArrowUpFromLine}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handlePushDictionary}\n >\n {publishButton.text}\n </Form.Button>\n )}\n {mode.includes('remote') &&\n isAuthenticated &&\n isDistantDictionary &&\n isEdited && (\n <Form.Button\n label={saveButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Save}\n color=\"text\"\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handlePushDictionary}\n >\n {saveButton.text}\n </Form.Button>\n )}\n </form>\n </>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"SaveForm.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/SaveForm/SaveForm.tsx"],"sourcesContent":["'use client';\n\nimport {\n useAuth,\n useDeleteDictionary,\n usePushDictionaries,\n useWriteDictionary,\n} from '@api/index';\nimport { ButtonColor, ButtonVariant } from '@components/Button';\nimport { Form } from '@components/Form';\nimport { Modal, ModalSize } from '@components/Modal';\nimport type { Dictionary as DistantDictionary } from '@intlayer/backend';\nimport {\n useDictionariesRecordActions,\n useEditedContent,\n} from '@intlayer/editor-react';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { cn } from '@utils/cn';\nimport {\n ArrowUpFromLine,\n Download,\n RotateCcw,\n Save,\n Trash,\n} from 'lucide-react';\nimport {\n type DetailedHTMLProps,\n type FC,\n type FormHTMLAttributes,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\n\ntype DictionaryDetailsProps = {\n dictionary: Dictionary;\n mode: ('local' | 'remote')[];\n onDelete?: () => void;\n onSave?: () => void;\n} & DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>;\n\nexport const SaveForm: FC<DictionaryDetailsProps> = ({\n dictionary,\n mode,\n className,\n onDelete,\n onSave,\n ...props\n}) => {\n const [isFormatAlertModalOpen, setIsFormatAlertModalOpen] = useState(false);\n const { setLocaleDictionary } = useDictionariesRecordActions();\n const { mutate: deleteDictionary, isPending: isDeleting } =\n useDeleteDictionary();\n const { mutate: writeDictionary, isPending: isWriting } =\n useWriteDictionary();\n const { mutate: pushDictionaries, isPending: isPushing } =\n usePushDictionaries();\n const isLoading = isWriting || isPushing;\n\n const { editedContent, restoreEditedContent } = useEditedContent();\n const {\n deleteButton,\n resetButton,\n saveButton,\n publishButton,\n downloadButton,\n confirmation,\n } = useIntlayer('save-dictionary-details');\n const { isAuthenticated } = useAuth();\n\n const editedDictionary = editedContent?.[dictionary.localId!];\n\n const isEdited =\n editedDictionary &&\n JSON.stringify(editedDictionary) !== JSON.stringify(dictionary);\n\n const isDistantDictionary =\n typeof (dictionary as unknown as DistantDictionary)?.id !== 'undefined';\n\n const handleSaveDictionaryConfirmation = async () => {\n if (!editedContent?.[dictionary.localId!]) return;\n\n const updatedDictionary = {\n ...dictionary,\n ...editedContent?.[dictionary.localId!],\n };\n\n writeDictionary(\n {\n dictionary: updatedDictionary,\n },\n {\n onSuccess: () => {\n setLocaleDictionary(editedContent?.[dictionary.localId!]);\n restoreEditedContent(dictionary.localId!);\n setIsFormatAlertModalOpen(false);\n onSave?.();\n },\n }\n );\n };\n\n const handlePushDictionary = () => {\n const updatedDictionary = {\n ...dictionary,\n ...editedContent?.[dictionary.localId!],\n };\n\n pushDictionaries(\n { dictionaries: [updatedDictionary] },\n {\n onSuccess: (res) => {\n if (res) {\n setLocaleDictionary(updatedDictionary);\n restoreEditedContent(dictionary.localId!);\n onSave?.();\n }\n },\n }\n );\n };\n\n const handleDeleteDictionary = () => {\n if (!dictionary.id) return;\n\n deleteDictionary(\n {\n dictionaryId: dictionary.id,\n },\n {\n onSuccess: (res) => {\n if (res) {\n onDelete?.();\n }\n },\n }\n );\n };\n\n return (\n <>\n <Modal\n isOpen={isFormatAlertModalOpen}\n title={confirmation.title.value}\n size={ModalSize.MD}\n onClose={() => setIsFormatAlertModalOpen(false)}\n padding=\"md\"\n >\n <form className=\"size-full\">\n <p className=\"py-4 text-neutral text-sm\">{confirmation.message}</p>\n\n <div className=\"mt-12 flex justify-end gap-2 max-md:flex-col\">\n <Form.Button\n label={confirmation.cancelButton.label.value}\n disabled={!isEdited || isLoading}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n variant={ButtonVariant.OUTLINE}\n onClick={() => setIsFormatAlertModalOpen(false)}\n >\n {confirmation.cancelButton.text}\n </Form.Button>\n <Form.Button\n label={confirmation.confirmButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Save}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handleSaveDictionaryConfirmation}\n >\n {confirmation.confirmButton.text}\n </Form.Button>\n </div>\n </form>\n </Modal>\n <form className={cn('flex justify-end gap-2', className)} {...props}>\n {mode.includes('remote') &&\n isDistantDictionary &&\n onDelete &&\n isAuthenticated && (\n <Form.Button\n label={deleteButton.label.value}\n Icon={Trash}\n color={ButtonColor.ERROR}\n variant={ButtonVariant.OUTLINE}\n className=\"max-md:w-full\"\n isLoading={isDeleting}\n onClick={handleDeleteDictionary}\n >\n {deleteButton.text}\n </Form.Button>\n )}\n {isEdited && (\n <Form.Button\n label={resetButton.label.value}\n disabled={!isEdited}\n Icon={RotateCcw}\n variant={ButtonVariant.OUTLINE}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n onClick={() => restoreEditedContent(dictionary.localId!)}\n >\n {resetButton.text}\n </Form.Button>\n )}\n {mode.includes('local') && (\n <Form.Button\n label={downloadButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Download}\n color={ButtonColor.TEXT}\n variant={\n isAuthenticated ? ButtonVariant.OUTLINE : ButtonVariant.DEFAULT\n }\n className=\"max-md:w-full\"\n isLoading={isWriting}\n onClick={() => setIsFormatAlertModalOpen(true)}\n >\n {downloadButton.text}\n </Form.Button>\n )}\n {mode.includes('remote') && isAuthenticated && !isDistantDictionary && (\n <Form.Button\n label={publishButton.label.value}\n disabled={isLoading}\n Icon={ArrowUpFromLine}\n color={ButtonColor.TEXT}\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handlePushDictionary}\n >\n {publishButton.text}\n </Form.Button>\n )}\n {mode.includes('remote') &&\n isAuthenticated &&\n isDistantDictionary &&\n isEdited && (\n <Form.Button\n label={saveButton.label.value}\n disabled={!isEdited || isLoading}\n Icon={Save}\n color=\"text\"\n className=\"max-md:w-full\"\n isLoading={isPushing}\n onClick={handlePushDictionary}\n >\n {saveButton.text}\n </Form.Button>\n )}\n </form>\n </>\n );\n};\n"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { cn } from "../../utils/cn.mjs";
4
4
  import { MaxHeightSmoother } from "../MaxHeightSmoother/index.mjs";
5
- import { useEffect, useRef, useState } from "react";
5
+ import { useLayoutEffect, useRef, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
7
  import { useIntlayer } from "react-intlayer";
8
8
 
@@ -66,7 +66,7 @@ const ExpandCollapse = ({ isRollable = true, minHeight = DEFAULT_MIN_HEIGHT, chi
66
66
  const codeContainerRef = useRef(null);
67
67
  const { expandCollapseContent } = useIntlayer("expand-collapse");
68
68
  const isTooBig = codeContainerHeight > minHeight;
69
- useEffect(() => {
69
+ useLayoutEffect(() => {
70
70
  const measure = () => {
71
71
  if (codeContainerRef.current) setCodeContainerHeight(codeContainerRef.current.clientHeight);
72
72
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandCollapse.mjs","names":[],"sources":["../../../../src/components/ExpandCollapse/ExpandCollapse.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { type FC, type ReactNode, useEffect, useRef, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the ExpandCollapse component\n */\nexport type ExpandCollapseProps = {\n /** Whether the component should provide expand/collapse functionality. If false, renders children directly */\n isRollable?: boolean;\n /** Minimum height in pixels before showing the expand/collapse toggle */\n minHeight?: number;\n /** Content that may overflow and trigger the expand/collapse behavior */\n children: ReactNode;\n /** Additional CSS classes for styling customization */\n className?: string;\n};\n\n/** Default minimum height threshold for triggering expand/collapse behavior */\nconst DEFAULT_MIN_HEIGHT = 700;\n\n/**\n * ExpandCollapse Component\n *\n * A smart content container that automatically provides expand/collapse functionality\n * when content exceeds a specified height threshold. Features smooth animations,\n * internationalized toggle text, and intelligent height detection.\n *\n * @example\n * ```tsx\n * <ExpandCollapse minHeight={300}>\n * <div>Very long content that will be collapsed...</div>\n * </ExpandCollapse>\n * ```\n *\n * ## Key Features\n * - **Smart Detection**: Automatically detects when content exceeds height threshold\n * - **Smooth Animations**: Uses CSS transitions for smooth expand/collapse effects\n * - **Internationalization**: Toggle text supports multiple languages via Intlayer\n * - **Customizable Height**: Configurable minimum height threshold\n * - **Performance Optimized**: Only applies collapse behavior when necessary\n * - **Accessibility**: Proper ARIA attributes and keyboard support\n *\n * ## Behavior Logic\n * 1. **Measurement Phase**: Measures actual content height on mount\n * 2. **Comparison**: Compares content height against minHeight threshold\n * 3. **Conditional Rendering**:\n * - If content ≤ minHeight: Renders normally without collapse functionality\n * - If content > minHeight: Enables expand/collapse with toggle button\n * 4. **State Management**: Manages collapsed/expanded state with smooth transitions\n *\n * ## When to Use\n * - Long-form content (articles, documentation, code blocks)\n * - Lists or tables that may grow beyond comfortable viewing height\n * - User-generated content with unpredictable length\n * - FAQ sections or expandable content cards\n * - Code examples or JSON data display\n *\n * ## Accessibility Features\n * - **Keyboard Navigation**: Toggle button is focusable and keyboard accessible\n * - **Screen Reader Support**: Proper ARIA labels and state announcements\n * - **Visual Indicators**: Clear visual cues for collapsed/expanded states\n * - **Smooth Animations**: Respects user preferences for reduced motion\n *\n * ## Internationalization\n * - Supports multiple languages through Intlayer integration\n * - Toggle text automatically adapts to current locale\n * - Includes translations for \"Show all\" and \"Show less\" states\n *\n * @param props - ExpandCollapseProps\n * @returns React functional component\n */\nexport const ExpandCollapse: FC<ExpandCollapseProps> = ({\n isRollable = true,\n minHeight = DEFAULT_MIN_HEIGHT,\n children,\n className,\n}) => {\n const [codeContainerHeight, setCodeContainerHeight] = useState(0);\n const [isCollapsed, setIsCollapsed] = useState(true);\n const codeContainerRef = useRef<HTMLDivElement>(null);\n const { expandCollapseContent } = useIntlayer('expand-collapse');\n\n const isTooBig = codeContainerHeight > minHeight;\n\n useEffect(() => {\n const measure = () => {\n if (codeContainerRef.current) {\n setCodeContainerHeight(codeContainerRef.current.clientHeight);\n }\n };\n\n measure();\n\n window.addEventListener('resize', measure);\n return () => window.removeEventListener('resize', measure);\n }, [children]);\n\n if (!isRollable) {\n return children;\n }\n\n if (!isTooBig) {\n return (\n <div className={cn('grid w-full', className)} ref={codeContainerRef}>\n {children}\n </div>\n );\n }\n\n return (\n <MaxHeightSmoother\n isHidden={isCollapsed}\n minHeight={minHeight}\n className=\"w-full overflow-x-auto overflow-y-hidden\"\n >\n <div className={cn('grid w-full', className)} ref={codeContainerRef}>\n {children}\n </div>\n <button\n className={cn(\n 'absolute right-0 bottom-0 flex w-full cursor-pointer items-center justify-center rounded-t-2xl bg-gradient-to-t from-card/80 to-transparent px-3 py-0.5 text-md text-neutral-700 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur transition-all duration-300 hover:py-1 dark:text-neutral-400',\n isCollapsed ? 'w-full' : 'w-32'\n )}\n type=\"button\"\n onClick={() => setIsCollapsed((prev) => !prev)}\n >\n {expandCollapseContent(isCollapsed)}\n </button>\n </MaxHeightSmoother>\n );\n};\n"],"mappings":";;;;;;;;;;AAsBA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqD3B,MAAa,kBAA2C,EACtD,aAAa,MACb,YAAY,oBACZ,UACA,gBACI;CACJ,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,CAAC;CAChE,MAAM,CAAC,aAAa,kBAAkB,SAAS,IAAI;CACnD,MAAM,mBAAmB,OAAuB,IAAI;CACpD,MAAM,EAAE,0BAA0B,YAAY,iBAAiB;CAE/D,MAAM,WAAW,sBAAsB;CAEvC,gBAAgB;EACd,MAAM,gBAAgB;GACpB,IAAI,iBAAiB,SACnB,uBAAuB,iBAAiB,QAAQ,YAAY;EAEhE;EAEA,QAAQ;EAER,OAAO,iBAAiB,UAAU,OAAO;EACzC,aAAa,OAAO,oBAAoB,UAAU,OAAO;CAC3D,GAAG,CAAC,QAAQ,CAAC;CAEb,IAAI,CAAC,YACH,OAAO;CAGT,IAAI,CAAC,UACH,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,eAAe,SAAS;EAAG,KAAK;EAChD;CACE;CAIT,OACE,qBAAC,mBAAD;EACE,UAAU;EACC;EACX,WAAU;YAHZ,CAKE,oBAAC,OAAD;GAAK,WAAW,GAAG,eAAe,SAAS;GAAG,KAAK;GAChD;EACE,IACL,oBAAC,UAAD;GACE,WAAW,GACT,uSACA,cAAc,WAAW,MAC3B;GACA,MAAK;GACL,eAAe,gBAAgB,SAAS,CAAC,IAAI;aAE5C,sBAAsB,WAAW;EAC5B,EACS;;AAEvB"}
1
+ {"version":3,"file":"ExpandCollapse.mjs","names":[],"sources":["../../../../src/components/ExpandCollapse/ExpandCollapse.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport {\n type FC,\n type ReactNode,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\n\n/**\n * Props for the ExpandCollapse component\n */\nexport type ExpandCollapseProps = {\n /** Whether the component should provide expand/collapse functionality. If false, renders children directly */\n isRollable?: boolean;\n /** Minimum height in pixels before showing the expand/collapse toggle */\n minHeight?: number;\n /** Content that may overflow and trigger the expand/collapse behavior */\n children: ReactNode;\n /** Additional CSS classes for styling customization */\n className?: string;\n};\n\n/** Default minimum height threshold for triggering expand/collapse behavior */\nconst DEFAULT_MIN_HEIGHT = 700;\n\n/**\n * ExpandCollapse Component\n *\n * A smart content container that automatically provides expand/collapse functionality\n * when content exceeds a specified height threshold. Features smooth animations,\n * internationalized toggle text, and intelligent height detection.\n *\n * @example\n * ```tsx\n * <ExpandCollapse minHeight={300}>\n * <div>Very long content that will be collapsed...</div>\n * </ExpandCollapse>\n * ```\n *\n * ## Key Features\n * - **Smart Detection**: Automatically detects when content exceeds height threshold\n * - **Smooth Animations**: Uses CSS transitions for smooth expand/collapse effects\n * - **Internationalization**: Toggle text supports multiple languages via Intlayer\n * - **Customizable Height**: Configurable minimum height threshold\n * - **Performance Optimized**: Only applies collapse behavior when necessary\n * - **Accessibility**: Proper ARIA attributes and keyboard support\n *\n * ## Behavior Logic\n * 1. **Measurement Phase**: Measures actual content height on mount\n * 2. **Comparison**: Compares content height against minHeight threshold\n * 3. **Conditional Rendering**:\n * - If content ≤ minHeight: Renders normally without collapse functionality\n * - If content > minHeight: Enables expand/collapse with toggle button\n * 4. **State Management**: Manages collapsed/expanded state with smooth transitions\n *\n * ## When to Use\n * - Long-form content (articles, documentation, code blocks)\n * - Lists or tables that may grow beyond comfortable viewing height\n * - User-generated content with unpredictable length\n * - FAQ sections or expandable content cards\n * - Code examples or JSON data display\n *\n * ## Accessibility Features\n * - **Keyboard Navigation**: Toggle button is focusable and keyboard accessible\n * - **Screen Reader Support**: Proper ARIA labels and state announcements\n * - **Visual Indicators**: Clear visual cues for collapsed/expanded states\n * - **Smooth Animations**: Respects user preferences for reduced motion\n *\n * ## Internationalization\n * - Supports multiple languages through Intlayer integration\n * - Toggle text automatically adapts to current locale\n * - Includes translations for \"Show all\" and \"Show less\" states\n *\n * @param props - ExpandCollapseProps\n * @returns React functional component\n */\nexport const ExpandCollapse: FC<ExpandCollapseProps> = ({\n isRollable = true,\n minHeight = DEFAULT_MIN_HEIGHT,\n children,\n className,\n}) => {\n const [codeContainerHeight, setCodeContainerHeight] = useState(0);\n const [isCollapsed, setIsCollapsed] = useState(true);\n const codeContainerRef = useRef<HTMLDivElement>(null);\n const { expandCollapseContent } = useIntlayer('expand-collapse');\n\n const isTooBig = codeContainerHeight > minHeight;\n\n useLayoutEffect(() => {\n const measure = () => {\n if (codeContainerRef.current) {\n setCodeContainerHeight(codeContainerRef.current.clientHeight);\n }\n };\n\n measure();\n\n window.addEventListener('resize', measure);\n return () => window.removeEventListener('resize', measure);\n }, [children]);\n\n if (!isRollable) {\n return children;\n }\n\n if (!isTooBig) {\n return (\n <div className={cn('grid w-full', className)} ref={codeContainerRef}>\n {children}\n </div>\n );\n }\n\n return (\n <MaxHeightSmoother\n isHidden={isCollapsed}\n minHeight={minHeight}\n className=\"w-full overflow-x-auto overflow-y-hidden\"\n >\n <div className={cn('grid w-full', className)} ref={codeContainerRef}>\n {children}\n </div>\n <button\n className={cn(\n 'absolute right-0 bottom-0 flex w-full cursor-pointer items-center justify-center rounded-t-2xl bg-gradient-to-t from-card/80 to-transparent px-3 py-0.5 text-md text-neutral-700 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur transition-all duration-300 hover:py-1 dark:text-neutral-400',\n isCollapsed ? 'w-full' : 'w-32'\n )}\n type=\"button\"\n onClick={() => setIsCollapsed((prev) => !prev)}\n >\n {expandCollapseContent(isCollapsed)}\n </button>\n </MaxHeightSmoother>\n );\n};\n"],"mappings":";;;;;;;;;;AA4BA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqD3B,MAAa,kBAA2C,EACtD,aAAa,MACb,YAAY,oBACZ,UACA,gBACI;CACJ,MAAM,CAAC,qBAAqB,0BAA0B,SAAS,CAAC;CAChE,MAAM,CAAC,aAAa,kBAAkB,SAAS,IAAI;CACnD,MAAM,mBAAmB,OAAuB,IAAI;CACpD,MAAM,EAAE,0BAA0B,YAAY,iBAAiB;CAE/D,MAAM,WAAW,sBAAsB;CAEvC,sBAAsB;EACpB,MAAM,gBAAgB;GACpB,IAAI,iBAAiB,SACnB,uBAAuB,iBAAiB,QAAQ,YAAY;EAEhE;EAEA,QAAQ;EAER,OAAO,iBAAiB,UAAU,OAAO;EACzC,aAAa,OAAO,oBAAoB,UAAU,OAAO;CAC3D,GAAG,CAAC,QAAQ,CAAC;CAEb,IAAI,CAAC,YACH,OAAO;CAGT,IAAI,CAAC,UACH,OACE,oBAAC,OAAD;EAAK,WAAW,GAAG,eAAe,SAAS;EAAG,KAAK;EAChD;CACE;CAIT,OACE,qBAAC,mBAAD;EACE,UAAU;EACC;EACX,WAAU;YAHZ,CAKE,oBAAC,OAAD;GAAK,WAAW,GAAG,eAAe,SAAS;GAAG,KAAK;GAChD;EACE,IACL,oBAAC,UAAD;GACE,WAAW,GACT,uSACA,cAAc,WAAW,MAC3B;GACA,MAAK;GACL,eAAe,gBAAgB,SAAS,CAAC,IAAI;aAE5C,sBAAsB,WAAW;EAC5B,EACS;;AAEvB"}
@@ -13,7 +13,7 @@ const FileList = ({ filePaths, ...props }) => /* @__PURE__ */ jsxs(Container, {
13
13
  children: /* @__PURE__ */ jsxs("div", {
14
14
  className: "mx-2 flex items-center justify-start gap-2 p-1",
15
15
  children: [
16
- /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-red-500" }),
16
+ /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-error" }),
17
17
  /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-yellow-500" }),
18
18
  /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-green-500" })
19
19
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"FileList.mjs","names":[],"sources":["../../../../src/components/IDE/FileList.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { Container } from '../Container';\nimport { FileTree } from './FileTree';\n\nexport type FileListProps = {\n filePaths: string[];\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const FileList: FC<FileListProps> = ({ filePaths, ...props }) => (\n <Container\n className=\"flex size-full flex-col justify-start overflow-auto shadow-lg\"\n roundedSize=\"3xl\"\n transparency=\"none\"\n {...props}\n >\n <div className=\"flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-neutral text-xs dark:bg-neutral-950\">\n <div className=\"mx-2 flex items-center justify-start gap-2 p-1\">\n <div className=\"size-3 rounded-full bg-red-500\" />\n <div className=\"size-3 rounded-full bg-yellow-500\" />\n <div className=\"size-3 rounded-full bg-green-500\" />\n </div>\n </div>\n <div className=\"relative flex size-full flex-1 flex-row justify-start shadow-lg\">\n <div className=\"absolute top-0 left-0 size-full\">\n <div className=\"flex size-full\">\n <FileTree filesPaths={filePaths} />\n </div>\n </div>\n </div>\n </Container>\n);\n"],"mappings":";;;;;AAQA,MAAa,YAA+B,EAAE,WAAW,GAAG,YAC1D,qBAAC,WAAD;CACE,WAAU;CACV,aAAY;CACZ,cAAa;CACb,GAAI;WAJN,CAME,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,OAAD,EAAK,WAAU,iCAAkC;IACjD,oBAAC,OAAD,EAAK,WAAU,oCAAqC;IACpD,oBAAC,OAAD,EAAK,WAAU,mCAAoC;GAChD;;CACF,IACL,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD,EAAU,YAAY,UAAY;GAC/B;EACF;CACF,EACI"}
1
+ {"version":3,"file":"FileList.mjs","names":[],"sources":["../../../../src/components/IDE/FileList.tsx"],"sourcesContent":["import type { FC, HTMLAttributes } from 'react';\nimport { Container } from '../Container';\nimport { FileTree } from './FileTree';\n\nexport type FileListProps = {\n filePaths: string[];\n} & HTMLAttributes<HTMLDivElement>;\n\nexport const FileList: FC<FileListProps> = ({ filePaths, ...props }) => (\n <Container\n className=\"flex size-full flex-col justify-start overflow-auto shadow-lg\"\n roundedSize=\"3xl\"\n transparency=\"none\"\n {...props}\n >\n <div className=\"flex w-auto flex-row items-center justify-start gap-1 rounded-t-3xl bg-neutral-200 text-neutral text-xs dark:bg-neutral-950\">\n <div className=\"mx-2 flex items-center justify-start gap-2 p-1\">\n <div className=\"size-3 rounded-full bg-error\" />\n <div className=\"size-3 rounded-full bg-yellow-500\" />\n <div className=\"size-3 rounded-full bg-green-500\" />\n </div>\n </div>\n <div className=\"relative flex size-full flex-1 flex-row justify-start shadow-lg\">\n <div className=\"absolute top-0 left-0 size-full\">\n <div className=\"flex size-full\">\n <FileTree filesPaths={filePaths} />\n </div>\n </div>\n </div>\n </Container>\n);\n"],"mappings":";;;;;AAQA,MAAa,YAA+B,EAAE,WAAW,GAAG,YAC1D,qBAAC,WAAD;CACE,WAAU;CACV,aAAY;CACZ,cAAa;CACb,GAAI;WAJN,CAME,oBAAC,OAAD;EAAK,WAAU;YACb,qBAAC,OAAD;GAAK,WAAU;aAAf;IACE,oBAAC,OAAD,EAAK,WAAU,+BAAgC;IAC/C,oBAAC,OAAD,EAAK,WAAU,oCAAqC;IACpD,oBAAC,OAAD,EAAK,WAAU,mCAAoC;GAChD;;CACF,IACL,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD,EAAU,YAAY,UAAY;GAC/B;EACF;CACF,EACI"}
@@ -41,7 +41,7 @@ const IDE = ({ pages: initialPages, isDarkMode, className, activeTab: defaultAct
41
41
  children: [/* @__PURE__ */ jsxs("div", {
42
42
  className: "mx-2 flex items-center justify-start gap-2 p-1",
43
43
  children: [
44
- /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-red-500" }),
44
+ /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-error" }),
45
45
  /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-yellow-500" }),
46
46
  /* @__PURE__ */ jsx("div", { className: "size-3 rounded-full bg-green-500" })
47
47
  ]