@intlayer/design-system 8.9.5 → 8.9.6-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs +17 -9
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.mjs +20 -0
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.mjs.map +1 -0
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +83 -49
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +4 -4
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +57 -35
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +20 -8
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +22 -52
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs.map +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
- package/dist/esm/components/IDE/CodeFormatSelector.mjs +1 -1
- package/dist/esm/components/IDE/ContentDeclarationFormatSelector.mjs +1 -1
- package/dist/esm/components/IDE/PackageManagerSelector.mjs +1 -1
- package/dist/esm/components/LanguageBackground/index.mjs +4 -4
- package/dist/esm/components/LanguageBackground/index.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +1 -1
- package/dist/esm/components/Modal/Modal.mjs +2 -2
- package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
- package/dist/esm/components/Pagination/Pagination.mjs +1 -1
- package/dist/esm/components/RightDrawer/RightDrawer.mjs +3 -3
- package/dist/esm/components/Tab/Tab.mjs +1 -1
- package/dist/esm/components/Table/SmartTable.mjs +1 -1
- package/dist/esm/components/index.mjs +11 -11
- package/dist/esm/hooks/index.mjs +11 -11
- package/dist/esm/hooks/reactQuery.mjs +17 -1
- package/dist/esm/hooks/reactQuery.mjs.map +1 -1
- package/dist/esm/hooks/useAuth/useOAuth2.mjs +1 -1
- package/dist/esm/hooks/useAuth/useSession.mjs +1 -1
- package/dist/esm/libs/auth.mjs +1 -1
- package/dist/types/components/Badge/index.d.ts +3 -3
- package/dist/types/components/Button/Button.d.ts +5 -5
- package/dist/types/components/CollapsibleTable/CollapsibleTable.d.ts +3 -3
- package/dist/types/components/Command/index.d.ts +2 -2
- package/dist/types/components/Container/index.d.ts +8 -8
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts +11 -0
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/SafeHtmlRenderer.d.ts.map +1 -0
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts +4 -3
- package/dist/types/components/DictionaryFieldEditor/ContentEditorView/TextEditor.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.d.ts.map +1 -1
- package/dist/types/components/DictionaryFieldEditor/StructureView/StructureView.d.ts.map +1 -1
- package/dist/types/components/Input/Checkbox.d.ts +2 -2
- package/dist/types/components/Input/Input.d.ts +1 -1
- package/dist/types/components/Input/OTPInput.d.ts +1 -1
- package/dist/types/components/LanguageBackground/index.d.ts.map +1 -1
- package/dist/types/components/Link/Link.d.ts +3 -3
- package/dist/types/components/Pagination/Pagination.d.ts +2 -2
- package/dist/types/components/SwitchSelector/SwitchSelector.d.ts +1 -1
- package/dist/types/components/SwitchSelector/VerticalSwitchSelector.d.ts +1 -1
- package/dist/types/components/TabSelector/TabSelector.d.ts +1 -1
- package/dist/types/components/Tag/index.d.ts +3 -3
- package/dist/types/components/Toaster/Toast.d.ts +1 -1
- package/dist/types/hooks/index.d.ts +2 -2
- package/dist/types/hooks/reactQuery.d.ts +3 -1
- package/dist/types/hooks/reactQuery.d.ts.map +1 -1
- package/package.json +22 -19
|
@@ -4,17 +4,17 @@ import { Container } from "../Container/index.mjs";
|
|
|
4
4
|
import { Button, ButtonColor, ButtonVariant } from "../Button/Button.mjs";
|
|
5
5
|
import { CopyToClipboard } from "../CopyToClipboard/index.mjs";
|
|
6
6
|
import { LocaleSwitcherContentProvider } from "../LocaleSwitcherContentDropDown/LocaleSwitcherContentContext.mjs";
|
|
7
|
-
import { Tab } from "../Tab/Tab.mjs";
|
|
8
7
|
import { ContentEditor } from "./ContentEditor.mjs";
|
|
8
|
+
import { TabSelector, TabSelectorColor } from "../TabSelector/TabSelector.mjs";
|
|
9
9
|
import { DictionaryDetailsForm } from "./DictionaryDetails/DictionaryDetailsForm.mjs";
|
|
10
10
|
import { JSONEditor } from "./JSONEditor.mjs";
|
|
11
11
|
import { SaveForm } from "./SaveForm/SaveForm.mjs";
|
|
12
12
|
import { StructureEditor } from "./StructureEditor.mjs";
|
|
13
|
-
import { useEffect } from "react";
|
|
13
|
+
import { useEffect, useState } from "react";
|
|
14
14
|
import { ArrowLeft } from "lucide-react";
|
|
15
15
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
16
|
-
import { useConfiguration, useDictionariesRecordActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
17
16
|
import { useIntlayer } from "react-intlayer";
|
|
17
|
+
import { useConfiguration, useDictionariesRecordActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
18
18
|
|
|
19
19
|
//#region src/components/DictionaryFieldEditor/DictionaryFieldEditor.tsx
|
|
20
20
|
const DictionaryFieldEditor = ({ dictionary, onClickDictionaryList, isDarkMode, mode, onDelete, onSave, showReturnButton = true }) => {
|
|
@@ -22,6 +22,7 @@ const DictionaryFieldEditor = ({ dictionary, onClickDictionaryList, isDarkMode,
|
|
|
22
22
|
const { returnToDictionaryList } = useIntlayer("dictionary-field-editor");
|
|
23
23
|
const { focusedContent, setFocusedContent } = useFocusUnmergedDictionary();
|
|
24
24
|
const { setLocaleDictionary } = useDictionariesRecordActions();
|
|
25
|
+
const [activeTab, setActiveTab] = useState("content");
|
|
25
26
|
useEffect(() => {
|
|
26
27
|
setFocusedContent({
|
|
27
28
|
...focusedContent ?? {},
|
|
@@ -44,45 +45,66 @@ const DictionaryFieldEditor = ({ dictionary, onClickDictionaryList, isDarkMode,
|
|
|
44
45
|
label: returnToDictionaryList.label.value,
|
|
45
46
|
children: returnToDictionaryList.text
|
|
46
47
|
}),
|
|
47
|
-
/* @__PURE__ */
|
|
48
|
-
className: "mb-22 min-h-0 flex-1",
|
|
49
|
-
children: /* @__PURE__ */
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
48
|
+
/* @__PURE__ */ jsxs("div", {
|
|
49
|
+
className: "mb-22 flex min-h-0 flex-1 flex-col overflow-hidden",
|
|
50
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
51
|
+
className: "sticky top-0 z-10 flex shrink-0 gap-3 rounded-xl bg-background/20 p-3 pb-4",
|
|
52
|
+
children: /* @__PURE__ */ jsx(TabSelector, {
|
|
53
|
+
selectedChoice: activeTab,
|
|
54
|
+
tabs: [
|
|
55
|
+
...mode.includes("remote") ? [/* @__PURE__ */ jsx("button", {
|
|
56
|
+
className: "cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none",
|
|
57
|
+
"data-active": activeTab === "details",
|
|
58
|
+
onClick: () => setActiveTab("details"),
|
|
59
|
+
type: "button",
|
|
60
|
+
children: "Details"
|
|
61
|
+
}, "details")] : [],
|
|
62
|
+
/* @__PURE__ */ jsx("button", {
|
|
63
|
+
className: "cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none",
|
|
64
|
+
"data-active": activeTab === "structure",
|
|
65
|
+
onClick: () => setActiveTab("structure"),
|
|
66
|
+
type: "button",
|
|
67
|
+
children: "Structure"
|
|
68
|
+
}, "structure"),
|
|
69
|
+
/* @__PURE__ */ jsx("button", {
|
|
70
|
+
className: "cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none",
|
|
71
|
+
"data-active": activeTab === "content",
|
|
72
|
+
onClick: () => setActiveTab("content"),
|
|
73
|
+
type: "button",
|
|
74
|
+
children: "Content"
|
|
75
|
+
}, "content"),
|
|
76
|
+
/* @__PURE__ */ jsx("button", {
|
|
77
|
+
className: "cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none",
|
|
78
|
+
"data-active": activeTab === "json",
|
|
79
|
+
onClick: () => setActiveTab("json"),
|
|
80
|
+
type: "button",
|
|
81
|
+
children: "JSON"
|
|
82
|
+
}, "json")
|
|
83
|
+
],
|
|
84
|
+
hoverable: true,
|
|
85
|
+
color: "text"
|
|
86
|
+
})
|
|
87
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
88
|
+
className: "min-h-0 flex-1 overflow-y-auto p-6",
|
|
89
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
90
|
+
className: "flex w-full min-w-0 flex-col items-stretch gap-6",
|
|
91
|
+
children: [
|
|
92
|
+
mode.includes("remote") && activeTab === "details" && /* @__PURE__ */ jsx(DictionaryDetailsForm, {
|
|
59
93
|
dictionary,
|
|
60
94
|
mode
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
label: "Structure",
|
|
65
|
-
value: "structure",
|
|
66
|
-
children: /* @__PURE__ */ jsx(StructureEditor, { dictionary })
|
|
67
|
-
}),
|
|
68
|
-
/* @__PURE__ */ jsx(Tab.Item, {
|
|
69
|
-
label: "Content",
|
|
70
|
-
value: "content",
|
|
71
|
-
children: /* @__PURE__ */ jsx(ContentEditor, {
|
|
95
|
+
}),
|
|
96
|
+
activeTab === "structure" && /* @__PURE__ */ jsx(StructureEditor, { dictionary }),
|
|
97
|
+
activeTab === "content" && /* @__PURE__ */ jsx(ContentEditor, {
|
|
72
98
|
dictionary,
|
|
73
99
|
isDarkMode
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
/* @__PURE__ */ jsx(Tab.Item, {
|
|
77
|
-
label: "JSON",
|
|
78
|
-
value: "json",
|
|
79
|
-
children: /* @__PURE__ */ jsx(JSONEditor, {
|
|
100
|
+
}),
|
|
101
|
+
activeTab === "json" && /* @__PURE__ */ jsx(JSONEditor, {
|
|
80
102
|
dictionary,
|
|
81
103
|
isDarkMode
|
|
82
104
|
})
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
})
|
|
105
|
+
]
|
|
106
|
+
})
|
|
107
|
+
})]
|
|
86
108
|
}),
|
|
87
109
|
/* @__PURE__ */ jsx("div", {
|
|
88
110
|
className: "absolute bottom-3 z-20 w-full p-2",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DictionaryFieldEditor.mjs","names":[],"sources":["../../../../src/components/DictionaryFieldEditor/DictionaryFieldEditor.tsx"],"sourcesContent":["'use client';\n\nimport { Container } from '@components/Container';\nimport { CopyToClipboard } from '@components/CopyToClipboard';\nimport {\n useConfiguration,\n useDictionariesRecordActions,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { ArrowLeft } from 'lucide-react';\nimport { type FC, useEffect } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonVariant } from '../Button';\nimport { LocaleSwitcherContentProvider } from '../LocaleSwitcherContentDropDown';\nimport {
|
|
1
|
+
{"version":3,"file":"DictionaryFieldEditor.mjs","names":[],"sources":["../../../../src/components/DictionaryFieldEditor/DictionaryFieldEditor.tsx"],"sourcesContent":["'use client';\n\nimport { Container } from '@components/Container';\nimport { CopyToClipboard } from '@components/CopyToClipboard';\nimport {\n useConfiguration,\n useDictionariesRecordActions,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { ArrowLeft } from 'lucide-react';\nimport { type FC, useEffect, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { Button, ButtonColor, ButtonVariant } from '../Button';\nimport { LocaleSwitcherContentProvider } from '../LocaleSwitcherContentDropDown';\nimport { TabSelector, TabSelectorColor } from '../TabSelector';\nimport { ContentEditor } from './ContentEditor';\nimport { DictionaryDetailsForm } from './DictionaryDetails/DictionaryDetailsForm';\nimport { JSONEditor } from './JSONEditor';\nimport { SaveForm } from './SaveForm/SaveForm';\nimport { StructureEditor } from './StructureEditor';\n\ntype DictionaryFieldEditorProps = {\n dictionary: Dictionary;\n onClickDictionaryList?: () => void;\n onDelete?: () => void;\n onSave?: () => void;\n isDarkMode?: boolean;\n mode: ('local' | 'remote')[];\n showReturnButton?: boolean;\n};\n\nexport const DictionaryFieldEditor: FC<DictionaryFieldEditorProps> = ({\n dictionary,\n onClickDictionaryList,\n isDarkMode,\n mode,\n onDelete,\n onSave,\n showReturnButton = true,\n}) => {\n const config = useConfiguration();\n const { returnToDictionaryList } = useIntlayer('dictionary-field-editor');\n const { focusedContent, setFocusedContent } = useFocusUnmergedDictionary();\n const { setLocaleDictionary } = useDictionariesRecordActions();\n const [activeTab, setActiveTab] = useState<string>('content');\n\n useEffect(() => {\n setFocusedContent({\n ...(focusedContent ?? {}),\n dictionaryKey: dictionary.key,\n dictionaryLocalId: dictionary.localId,\n });\n setLocaleDictionary(dictionary);\n }, []);\n\n return (\n <LocaleSwitcherContentProvider\n availableLocales={config?.internationalization?.locales ?? []}\n >\n <div className=\"relative flex h-full min-h-0 w-full flex-1 flex-col md:overflow-hidden\">\n {showReturnButton && (\n <Button\n onClick={onClickDictionaryList}\n variant={ButtonVariant.HOVERABLE}\n className=\"z-10 mr-auto mb-6 ml-5 shrink-0\"\n color={ButtonColor.TEXT}\n Icon={ArrowLeft}\n label={returnToDictionaryList.label.value}\n >\n {returnToDictionaryList.text}\n </Button>\n )}\n\n <div className=\"mb-22 flex min-h-0 flex-1 flex-col overflow-hidden\">\n {/* Tab headers */}\n <div className=\"sticky top-0 z-10 flex shrink-0 gap-3 rounded-xl bg-background/20 p-3 pb-4\">\n <TabSelector\n selectedChoice={activeTab}\n tabs={[\n ...(mode.includes('remote')\n ? [\n <button\n key=\"details\"\n className=\"cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none\"\n data-active={activeTab === 'details'}\n onClick={() => setActiveTab('details')}\n type=\"button\"\n >\n Details\n </button>,\n ]\n : []),\n <button\n key=\"structure\"\n className=\"cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none\"\n data-active={activeTab === 'structure'}\n onClick={() => setActiveTab('structure')}\n type=\"button\"\n >\n Structure\n </button>,\n <button\n key=\"content\"\n className=\"cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none\"\n data-active={activeTab === 'content'}\n onClick={() => setActiveTab('content')}\n type=\"button\"\n >\n Content\n </button>,\n <button\n key=\"json\"\n className=\"cursor-pointer whitespace-nowrap rounded-md px-4 py-1 font-medium text-sm transition-colors focus:outline-none\"\n data-active={activeTab === 'json'}\n onClick={() => setActiveTab('json')}\n type=\"button\"\n >\n JSON\n </button>,\n ]}\n hoverable\n color={TabSelectorColor.TEXT}\n />\n </div>\n {/* Tab content — only active panel is mounted */}\n <div className=\"min-h-0 flex-1 overflow-y-auto p-6\">\n <div className=\"flex w-full min-w-0 flex-col items-stretch gap-6\">\n {mode.includes('remote') && activeTab === 'details' && (\n <DictionaryDetailsForm dictionary={dictionary} mode={mode} />\n )}\n {activeTab === 'structure' && (\n <StructureEditor dictionary={dictionary} />\n )}\n {activeTab === 'content' && (\n <ContentEditor\n dictionary={dictionary}\n isDarkMode={isDarkMode}\n />\n )}\n {activeTab === 'json' && (\n <JSONEditor dictionary={dictionary} isDarkMode={isDarkMode} />\n )}\n </div>\n </div>\n </div>\n\n <div className=\"absolute bottom-3 z-20 w-full p-2\">\n <Container\n color=\"card\"\n roundedSize=\"2xl\"\n padding=\"sm\"\n className=\"w-full shrink-0 flex-row flex-wrap items-center justify-end gap-10 bg-background/20 md:bottom-0\"\n >\n <CopyToClipboard\n text={dictionary.id!}\n className=\"text-nowrap text-neutral text-sm\"\n size={9}\n >\n {dictionary.id}\n </CopyToClipboard>\n <SaveForm\n dictionary={dictionary}\n mode={mode}\n onDelete={() => {\n setFocusedContent(null);\n onDelete?.();\n }}\n onSave={onSave}\n />\n </Container>\n </div>\n </div>\n </LocaleSwitcherContentProvider>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgCA,MAAa,yBAAyD,EACpE,YACA,uBACA,YACA,MACA,UACA,QACA,mBAAmB,WACf;CACJ,MAAM,SAAS,kBAAkB;CACjC,MAAM,EAAE,2BAA2B,YAAY,0BAA0B;CACzE,MAAM,EAAE,gBAAgB,sBAAsB,4BAA4B;CAC1E,MAAM,EAAE,wBAAwB,8BAA8B;CAC9D,MAAM,CAAC,WAAW,gBAAgB,SAAiB,UAAU;CAE7D,gBAAgB;EACd,kBAAkB;GAChB,GAAI,kBAAkB,EAAE;GACxB,eAAe,WAAW;GAC1B,mBAAmB,WAAW;GAC/B,CAAC;EACF,oBAAoB,WAAW;IAC9B,EAAE,CAAC;CAEN,OACE,oBAAC,+BAAD;EACE,kBAAkB,QAAQ,sBAAsB,WAAW,EAAE;YAE7D,qBAAC,OAAD;GAAK,WAAU;aAAf;IACG,oBACC,oBAAC,QAAD;KACE,SAAS;KACT;KACA,WAAU;KACV;KACA,MAAM;KACN,OAAO,uBAAuB,MAAM;eAEnC,uBAAuB;KACjB;IAGX,qBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,aAAD;OACE,gBAAgB;OAChB,MAAM;QACJ,GAAI,KAAK,SAAS,SAAS,GACvB,CACE,oBAAC,UAAD;SAEE,WAAU;SACV,eAAa,cAAc;SAC3B,eAAe,aAAa,UAAU;SACtC,MAAK;mBACN;SAEQ,EAPH,UAOG,CACV,GACD,EAAE;QACN,oBAAC,UAAD;SAEE,WAAU;SACV,eAAa,cAAc;SAC3B,eAAe,aAAa,YAAY;SACxC,MAAK;mBACN;SAEQ,EAPH,YAOG;QACT,oBAAC,UAAD;SAEE,WAAU;SACV,eAAa,cAAc;SAC3B,eAAe,aAAa,UAAU;SACtC,MAAK;mBACN;SAEQ,EAPH,UAOG;QACT,oBAAC,UAAD;SAEE,WAAU;SACV,eAAa,cAAc;SAC3B,eAAe,aAAa,OAAO;SACnC,MAAK;mBACN;SAEQ,EAPH,OAOG;QACV;OACD;OACA;OACA;MACE,GAEN,oBAAC,OAAD;MAAK,WAAU;gBACb,qBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,KAAK,SAAS,SAAS,IAAI,cAAc,aACxC,oBAAC,uBAAD;SAAmC;SAAkB;SAAQ;QAE9D,cAAc,eACb,oBAAC,iBAAD,EAA6B,YAAc;QAE5C,cAAc,aACb,oBAAC,eAAD;SACc;SACA;SACZ;QAEH,cAAc,UACb,oBAAC,YAAD;SAAwB;SAAwB;SAAc;QAE5D;;MACF,EACF;;IAEN,oBAAC,OAAD;KAAK,WAAU;eACb,qBAAC,WAAD;MACE,OAAM;MACN,aAAY;MACZ,SAAQ;MACR,WAAU;gBAJZ,CAME,oBAAC,iBAAD;OACE,MAAM,WAAW;OACjB,WAAU;OACV,MAAM;iBAEL,WAAW;OACI,GAClB,oBAAC,UAAD;OACc;OACN;OACN,gBAAgB;QACd,kBAAkB,KAAK;QACvB,YAAY;;OAEN;OACR,EACQ;;KACR;IACF;;EACwB"}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Button, ButtonColor, ButtonTextAlign, ButtonVariant } from "../../Button/Button.mjs";
|
|
2
2
|
import { Accordion } from "../../Accordion/Accordion.mjs";
|
|
3
3
|
import { getIsEditableSection } from "../getIsEditableSection.mjs";
|
|
4
|
+
import { useState } from "react";
|
|
4
5
|
import { ChevronRight, Plus } from "lucide-react";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { internationalization } from "@intlayer/config/built";
|
|
7
|
-
import { useEditedContentActions, useEditorLocale, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { useIntlayer } from "react-intlayer";
|
|
8
|
+
import { useEditedContentActions, useEditorLocale, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
9
9
|
import { getContentNodeByKeyPath, getEmptyNode, getNodeType } from "@intlayer/core/dictionaryManipulator";
|
|
10
10
|
import * as NodeTypes from "@intlayer/types/nodeType";
|
|
11
11
|
import { isSameKeyPath } from "@intlayer/core/utils";
|
|
12
12
|
import { camelCaseToSentence } from "@intlayer/config/client";
|
|
13
|
+
import { internationalization } from "@intlayer/config/built";
|
|
13
14
|
|
|
14
15
|
//#region src/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.tsx
|
|
15
16
|
const traceKeys = [
|
|
@@ -17,6 +18,17 @@ const traceKeys = [
|
|
|
17
18
|
"id",
|
|
18
19
|
"nodeType"
|
|
19
20
|
];
|
|
21
|
+
const GatedAccordion = ({ children, onToggle, ...props }) => {
|
|
22
|
+
const [hasOpened, setHasOpened] = useState(false);
|
|
23
|
+
return /* @__PURE__ */ jsx(Accordion, {
|
|
24
|
+
...props,
|
|
25
|
+
onToggle: (isOpen) => {
|
|
26
|
+
if (isOpen && !hasOpened) setHasOpened(true);
|
|
27
|
+
onToggle?.(isOpen);
|
|
28
|
+
},
|
|
29
|
+
children: hasOpened ? children : null
|
|
30
|
+
});
|
|
31
|
+
};
|
|
20
32
|
const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
21
33
|
const { locales } = internationalization;
|
|
22
34
|
const section = getContentNodeByKeyPath(sectionProp, keyPath, useEditorLocale());
|
|
@@ -26,7 +38,7 @@ const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
|
26
38
|
const nodeType = getNodeType(section);
|
|
27
39
|
const getIsSelected = (keyPath) => (focusedContent?.keyPath?.length ?? 0) > 0 && isSameKeyPath(keyPath, focusedContent?.keyPath ?? []);
|
|
28
40
|
const isEditableSubSection = getIsEditableSection(section);
|
|
29
|
-
if (!section) return /* @__PURE__ */ jsx(Fragment, {});
|
|
41
|
+
if (!section) return /* @__PURE__ */ jsx(Fragment$1, {});
|
|
30
42
|
if (isEditableSubSection) return /* @__PURE__ */ jsx(Button, {
|
|
31
43
|
label: goToField.label.value,
|
|
32
44
|
variant: "hoverable",
|
|
@@ -37,7 +49,7 @@ const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
|
37
49
|
children: camelCaseToSentence(keyPath[keyPath.length - 1].key)
|
|
38
50
|
});
|
|
39
51
|
if (typeof section === "object") {
|
|
40
|
-
if (nodeType === NodeTypes.REACT_NODE) return /* @__PURE__ */ jsx(Fragment, { children: "React Node" });
|
|
52
|
+
if (nodeType === NodeTypes.REACT_NODE) return /* @__PURE__ */ jsx(Fragment$1, { children: "React Node" });
|
|
41
53
|
if (nodeType === NodeTypes.TRANSLATION) return /* @__PURE__ */ jsx("div", {
|
|
42
54
|
className: "flex flex-col justify-between gap-2",
|
|
43
55
|
children: locales.map((translationKey) => {
|
|
@@ -81,7 +93,7 @@ const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
|
81
93
|
isActive: getIsSelected(childKeyPath),
|
|
82
94
|
children: ["Item ", index]
|
|
83
95
|
}, JSON.stringify(childKeyPath));
|
|
84
|
-
return /* @__PURE__ */ jsx(
|
|
96
|
+
return /* @__PURE__ */ jsx(GatedAccordion, {
|
|
85
97
|
label: `${goToField.label.value} ${index}`,
|
|
86
98
|
header: `Item ${index}`,
|
|
87
99
|
isActive: getIsSelected(childKeyPath),
|
|
@@ -139,7 +151,7 @@ const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
|
139
151
|
IconRight: ChevronRight,
|
|
140
152
|
children: camelCaseToSentence(key)
|
|
141
153
|
}, key);
|
|
142
|
-
return /* @__PURE__ */ jsx(
|
|
154
|
+
return /* @__PURE__ */ jsx(GatedAccordion, {
|
|
143
155
|
label: `${goToField.label.value} ${key}`,
|
|
144
156
|
isActive: getIsSelected(childKeyPath),
|
|
145
157
|
onClick: () => setFocusedContentKeyPath(childKeyPath),
|
|
@@ -159,7 +171,7 @@ const NavigationViewNode = ({ section: sectionProp, keyPath, dictionary }) => {
|
|
|
159
171
|
})
|
|
160
172
|
});
|
|
161
173
|
}
|
|
162
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
174
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
163
175
|
"Error loading section --",
|
|
164
176
|
nodeType,
|
|
165
177
|
"--",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavigationViewNode.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.tsx"],"sourcesContent":["import { Accordion } from '@components/Accordion';\nimport {\n Button,\n ButtonColor,\n ButtonTextAlign,\n ButtonVariant,\n} from '@components/Button';\nimport { internationalization } from '@intlayer/config/built';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getContentNodeByKeyPath,\n getEmptyNode,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { isSameKeyPath } from '@intlayer/core/utils';\nimport {\n useEditedContentActions,\n useEditorLocale,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { LocalDictionaryId } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport type { ContentNode, Dictionary } from 'intlayer';\nimport { ChevronRight, Plus } from 'lucide-react';\nimport type { FC } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { getIsEditableSection } from '../getIsEditableSection';\n\nexport const traceKeys: string[] = ['filePath', 'id', 'nodeType'];\n\nexport type NodeWrapperProps = {\n keyPath: KeyPath[];\n section: ContentNode;\n dictionary: Dictionary;\n};\n\nexport const NavigationViewNode: FC<NodeWrapperProps> = ({\n section: sectionProp,\n keyPath,\n dictionary,\n}) => {\n const { locales } = internationalization;\n\n const currentLocale = useEditorLocale();\n const section = getContentNodeByKeyPath(sectionProp, keyPath, currentLocale);\n const { addEditedContent } = useEditedContentActions();\n const { setFocusedContentKeyPath, focusedContent } =\n useFocusUnmergedDictionary();\n const { addNewElement, goToField } = useIntlayer('navigation-view');\n const nodeType = getNodeType(section);\n const getIsSelected = (keyPath: KeyPath[]) =>\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(keyPath, focusedContent?.keyPath ?? []);\n const isEditableSubSection = getIsEditableSection(section);\n\n if (!section) return <></>;\n\n if (isEditableSubSection) {\n return (\n <Button\n label={goToField.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(keyPath)}\n IconRight={ChevronRight}\n >\n {camelCaseToSentence(keyPath[keyPath.length - 1].key as string)}\n </Button>\n );\n }\n\n if (typeof section === 'object') {\n if (nodeType === NodeTypes.REACT_NODE) {\n return <>React Node</>;\n }\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {locales.map((translationKey) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.TRANSLATION, key: translationKey },\n ];\n\n return (\n <NavigationViewNode\n key={translationKey}\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n })}\n </div>\n );\n }\n\n if (\n nodeType === NodeTypes.ENUMERATION ||\n nodeType === NodeTypes.PLURAL ||\n nodeType === NodeTypes.CONDITION\n ) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {Object.keys(\n (section as any)[nodeType as unknown as keyof typeof section]\n ).map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: nodeType, key },\n ];\n\n return (\n <NavigationViewNode\n key={key}\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n })}\n </div>\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {(section as unknown as ContentNode[]).map((subSection, index) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.ARRAY, key: index },\n ];\n\n const isEditableSubSection = getIsEditableSection(subSection);\n\n if (isEditableSubSection) {\n return (\n <Button\n key={JSON.stringify(childKeyPath)}\n label={`${goToField.label.value} ${index}`}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n IconRight={ChevronRight}\n isActive={getIsSelected(childKeyPath)}\n >\n Item {index}\n </Button>\n );\n }\n\n return (\n <Accordion\n key={JSON.stringify(childKeyPath)}\n label={`${goToField.label.value} ${index}`}\n header={`Item ${index}`}\n isActive={getIsSelected(childKeyPath)}\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n >\n <div className=\"mt-2 flex w-full max-w-full\">\n <div className=\"flex-1 pl-10\">\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n </div>\n </div>\n </Accordion>\n );\n })}\n\n <Button\n label={addNewElement.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: (section as unknown as ContentNode[]).length,\n },\n ];\n const sectionArray = section as unknown as ContentNode[];\n const emptySectionEl =\n getEmptyNode(\n sectionArray[\n (sectionArray.length - 1) as keyof typeof sectionArray\n ] as ContentNode\n ) ?? '';\n addEditedContent(\n dictionary.localId as LocalDictionaryId,\n emptySectionEl,\n newKeyPath,\n false\n );\n setFocusedContentKeyPath(newKeyPath);\n }}\n Icon={Plus}\n >\n {addNewElement.text}\n </Button>\n </div>\n );\n }\n\n if (typeof section.nodeType === 'string') {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: section.nodeType } as KeyPath,\n ];\n\n return (\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n }\n\n const sectionArray = Object.keys(section);\n return (\n <div className=\"flex w-full max-w-full flex-col justify-between gap-2\">\n {sectionArray.map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key },\n ];\n\n const subSection = getContentNodeByKeyPath(sectionProp, childKeyPath);\n const isEditableSubSection = getIsEditableSection(subSection);\n\n if (isEditableSubSection) {\n return (\n <Button\n label={`${goToField.label.value} ${key}`}\n key={key}\n isActive={getIsSelected(childKeyPath)}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n IconRight={ChevronRight}\n >\n {camelCaseToSentence(key)}\n </Button>\n );\n }\n\n return (\n <Accordion\n key={key}\n label={`${goToField.label.value} ${key}`}\n isActive={getIsSelected(childKeyPath)}\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n header={camelCaseToSentence(key)}\n >\n <div className=\"mt-2 flex w-full max-w-full\">\n <div className=\"flex-1 pl-10\">\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n </div>\n </div>\n </Accordion>\n );\n })}\n </div>\n );\n }\n\n return (\n <>\n Error loading section --\n {nodeType}\n --\n {JSON.stringify(section)}\n --\n {JSON.stringify(keyPath)}\n </>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NavigationViewNode.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.tsx"],"sourcesContent":["import { Accordion, type AccordionProps } from '@components/Accordion';\nimport {\n Button,\n ButtonColor,\n ButtonTextAlign,\n ButtonVariant,\n} from '@components/Button';\nimport { internationalization } from '@intlayer/config/built';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getContentNodeByKeyPath,\n getEmptyNode,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { isSameKeyPath } from '@intlayer/core/utils';\nimport {\n useEditedContentActions,\n useEditorLocale,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { LocalDictionaryId } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport type { ContentNode, Dictionary } from 'intlayer';\nimport { ChevronRight, Plus } from 'lucide-react';\nimport { type FC, type ReactNode, useState } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { getIsEditableSection } from '../getIsEditableSection';\n\nexport const traceKeys: string[] = ['filePath', 'id', 'nodeType'];\n\ntype GatedAccordionProps = AccordionProps & { children: ReactNode };\n\n// Renders children only after the accordion is first opened (mount-once pattern).\n// Prevents the entire recursive subtree from mounting on initial render.\nconst GatedAccordion: FC<GatedAccordionProps> = ({\n children,\n onToggle,\n ...props\n}) => {\n const [hasOpened, setHasOpened] = useState(false);\n return (\n <Accordion\n {...props}\n onToggle={(isOpen) => {\n if (isOpen && !hasOpened) setHasOpened(true);\n onToggle?.(isOpen);\n }}\n >\n {hasOpened ? children : null}\n </Accordion>\n );\n};\n\nexport type NodeWrapperProps = {\n keyPath: KeyPath[];\n section: ContentNode;\n dictionary: Dictionary;\n};\n\nexport const NavigationViewNode: FC<NodeWrapperProps> = ({\n section: sectionProp,\n keyPath,\n dictionary,\n}) => {\n const { locales } = internationalization;\n\n const currentLocale = useEditorLocale();\n const section = getContentNodeByKeyPath(sectionProp, keyPath, currentLocale);\n const { addEditedContent } = useEditedContentActions();\n const { setFocusedContentKeyPath, focusedContent } =\n useFocusUnmergedDictionary();\n const { addNewElement, goToField } = useIntlayer('navigation-view');\n const nodeType = getNodeType(section);\n const getIsSelected = (keyPath: KeyPath[]) =>\n (focusedContent?.keyPath?.length ?? 0) > 0 &&\n isSameKeyPath(keyPath, focusedContent?.keyPath ?? []);\n const isEditableSubSection = getIsEditableSection(section);\n\n if (!section) return <></>;\n\n if (isEditableSubSection) {\n return (\n <Button\n label={goToField.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(keyPath)}\n IconRight={ChevronRight}\n >\n {camelCaseToSentence(keyPath[keyPath.length - 1].key as string)}\n </Button>\n );\n }\n\n if (typeof section === 'object') {\n if (nodeType === NodeTypes.REACT_NODE) {\n return <>React Node</>;\n }\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {locales.map((translationKey) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.TRANSLATION, key: translationKey },\n ];\n\n return (\n <NavigationViewNode\n key={translationKey}\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n })}\n </div>\n );\n }\n\n if (\n nodeType === NodeTypes.ENUMERATION ||\n nodeType === NodeTypes.PLURAL ||\n nodeType === NodeTypes.CONDITION\n ) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {Object.keys(\n (section as any)[nodeType as unknown as keyof typeof section]\n ).map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: nodeType, key },\n ];\n\n return (\n <NavigationViewNode\n key={key}\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n })}\n </div>\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n return (\n <div className=\"flex flex-col justify-between gap-2\">\n {(section as unknown as ContentNode[]).map((subSection, index) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.ARRAY, key: index },\n ];\n\n const isEditableSubSection = getIsEditableSection(subSection);\n\n if (isEditableSubSection) {\n return (\n <Button\n key={JSON.stringify(childKeyPath)}\n label={`${goToField.label.value} ${index}`}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n IconRight={ChevronRight}\n isActive={getIsSelected(childKeyPath)}\n >\n Item {index}\n </Button>\n );\n }\n\n return (\n <GatedAccordion\n key={JSON.stringify(childKeyPath)}\n label={`${goToField.label.value} ${index}`}\n header={`Item ${index}`}\n isActive={getIsSelected(childKeyPath)}\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n >\n <div className=\"mt-2 flex w-full max-w-full\">\n <div className=\"flex-1 pl-10\">\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n </div>\n </div>\n </GatedAccordion>\n );\n })}\n\n <Button\n label={addNewElement.label.value}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.NEUTRAL}\n textAlign={ButtonTextAlign.LEFT}\n onClick={() => {\n const newKeyPath: KeyPath[] = [\n ...keyPath,\n {\n type: NodeTypes.ARRAY,\n key: (section as unknown as ContentNode[]).length,\n },\n ];\n const sectionArray = section as unknown as ContentNode[];\n const emptySectionEl =\n getEmptyNode(\n sectionArray[\n (sectionArray.length - 1) as keyof typeof sectionArray\n ] as ContentNode\n ) ?? '';\n addEditedContent(\n dictionary.localId as LocalDictionaryId,\n emptySectionEl,\n newKeyPath,\n false\n );\n setFocusedContentKeyPath(newKeyPath);\n }}\n Icon={Plus}\n >\n {addNewElement.text}\n </Button>\n </div>\n );\n }\n\n if (typeof section.nodeType === 'string') {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: section.nodeType } as KeyPath,\n ];\n\n return (\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n );\n }\n\n const sectionArray = Object.keys(section);\n return (\n <div className=\"flex w-full max-w-full flex-col justify-between gap-2\">\n {sectionArray.map((key) => {\n const childKeyPath: KeyPath[] = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key },\n ];\n\n const subSection = getContentNodeByKeyPath(sectionProp, childKeyPath);\n const isEditableSubSection = getIsEditableSection(subSection);\n\n if (isEditableSubSection) {\n return (\n <Button\n label={`${goToField.label.value} ${key}`}\n key={key}\n isActive={getIsSelected(childKeyPath)}\n variant={ButtonVariant.HOVERABLE}\n color={ButtonColor.TEXT}\n className=\"w-full\"\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n IconRight={ChevronRight}\n >\n {camelCaseToSentence(key)}\n </Button>\n );\n }\n\n return (\n <GatedAccordion\n key={key}\n label={`${goToField.label.value} ${key}`}\n isActive={getIsSelected(childKeyPath)}\n onClick={() => setFocusedContentKeyPath(childKeyPath)}\n header={camelCaseToSentence(key)}\n >\n <div className=\"mt-2 flex w-full max-w-full\">\n <div className=\"flex-1 pl-10\">\n <NavigationViewNode\n keyPath={childKeyPath}\n section={sectionProp}\n dictionary={dictionary}\n />\n </div>\n </div>\n </GatedAccordion>\n );\n })}\n </div>\n );\n }\n\n return (\n <>\n Error loading section --\n {nodeType}\n --\n {JSON.stringify(section)}\n --\n {JSON.stringify(keyPath)}\n </>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { cn } from "../../../utils/cn.mjs";
|
|
4
|
+
import { ButtonColor, ButtonVariant } from "../../Button/Button.mjs";
|
|
4
5
|
import { useAuth } from "../../../hooks/useAuth/useAuth.mjs";
|
|
5
6
|
import { useDeleteDictionary, usePushDictionaries, useWriteDictionary } from "../../../hooks/reactQuery.mjs";
|
|
6
|
-
import { ButtonColor, ButtonVariant } from "../../Button/Button.mjs";
|
|
7
|
-
import { Modal, ModalSize } from "../../Modal/Modal.mjs";
|
|
8
7
|
import { Form } from "../../Form/Form.mjs";
|
|
8
|
+
import { Modal, ModalSize } from "../../Modal/Modal.mjs";
|
|
9
9
|
import { useState } from "react";
|
|
10
10
|
import { ArrowUpFromLine, Download, RotateCcw, Save, Trash } from "lucide-react";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
import { useDictionariesRecordActions, useEditedContent } from "@intlayer/editor-react";
|
|
13
12
|
import { useIntlayer } from "react-intlayer";
|
|
13
|
+
import { useDictionariesRecordActions, useEditedContent } from "@intlayer/editor-react";
|
|
14
14
|
|
|
15
15
|
//#region src/components/DictionaryFieldEditor/SaveForm/SaveForm.tsx
|
|
16
16
|
const SaveForm = ({ dictionary, mode, className, onDelete, onSave, ...props }) => {
|
|
@@ -5,22 +5,20 @@ import { Button, ButtonColor, ButtonSize, ButtonVariant } from "../../Button/But
|
|
|
5
5
|
import { InputVariant } from "../../Input/Input.mjs";
|
|
6
6
|
import { EditableFieldInput } from "../../EditableField/EditableFieldInput.mjs";
|
|
7
7
|
import { NodeTypeSelector } from "../NodeTypeSelector.mjs";
|
|
8
|
-
import { memo, useMemo, useRef } from "react";
|
|
9
8
|
import { Plus, Trash } from "lucide-react";
|
|
10
|
-
import { Fragment
|
|
11
|
-
import { useConfiguration, useEditedContentActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
10
|
import { useIntlayer } from "react-intlayer";
|
|
11
|
+
import { useConfiguration, useEditedContentActions, useFocusUnmergedDictionary } from "@intlayer/editor-react";
|
|
13
12
|
import { getDefaultNode, getNodeChildren, getNodeType } from "@intlayer/core/dictionaryManipulator";
|
|
14
13
|
import * as NodeTypes from "@intlayer/types/nodeType";
|
|
15
14
|
import { isSameKeyPath } from "@intlayer/core/utils";
|
|
16
15
|
import { camelCaseToSentence } from "@intlayer/config/client";
|
|
17
|
-
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
18
16
|
|
|
19
17
|
//#region src/components/DictionaryFieldEditor/StructureView/StructureView.tsx
|
|
20
18
|
const NodeTypeView = ({ section, dictionaryLocalId, keyPath, onNodeTypeChange: onNodeTypeChangeProp }) => {
|
|
21
19
|
const locales = useConfiguration()?.internationalization?.locales ?? [];
|
|
22
|
-
const nodeType =
|
|
23
|
-
const children =
|
|
20
|
+
const nodeType = getNodeType(section);
|
|
21
|
+
const children = getNodeChildren(section);
|
|
24
22
|
const onNodeTypeChange = (content) => {
|
|
25
23
|
onNodeTypeChangeProp(getDefaultNode(nodeType, locales, content));
|
|
26
24
|
};
|
|
@@ -61,7 +59,7 @@ const NodeTypeView = ({ section, dictionaryLocalId, keyPath, onNodeTypeChange: o
|
|
|
61
59
|
})]
|
|
62
60
|
});
|
|
63
61
|
}
|
|
64
|
-
if (nodeType === NodeTypes.OBJECT) return /* @__PURE__ */ jsxs(Fragment
|
|
62
|
+
if (nodeType === NodeTypes.OBJECT) return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(NodeTypeSelector, {
|
|
65
63
|
section,
|
|
66
64
|
onValueChange: (nodeType) => onNodeTypeChangeProp(getDefaultNode(nodeType, locales))
|
|
67
65
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -77,7 +75,7 @@ const NodeTypeView = ({ section, dictionaryLocalId, keyPath, onNodeTypeChange: o
|
|
|
77
75
|
onValueChange: (nodeType) => onNodeTypeChangeProp(getDefaultNode(nodeType, locales))
|
|
78
76
|
});
|
|
79
77
|
};
|
|
80
|
-
const NodeView =
|
|
78
|
+
const NodeView = ({ sectionKey, section, keyPath, dictionaryLocalId }) => {
|
|
81
79
|
const { focusedContent, setFocusedContentKeyPath } = useFocusUnmergedDictionary();
|
|
82
80
|
const { renameEditedContent, addEditedContent } = useEditedContentActions();
|
|
83
81
|
const { titleInput, deleteButton } = useIntlayer("structure-view");
|
|
@@ -142,63 +140,35 @@ const NodeView = memo(({ sectionKey, section, keyPath, dictionaryLocalId }) => {
|
|
|
142
140
|
})]
|
|
143
141
|
})
|
|
144
142
|
});
|
|
145
|
-
}
|
|
143
|
+
};
|
|
146
144
|
const ObjectView = ({ section, keyPath, dictionaryLocalId }) => {
|
|
147
145
|
const { addNodeButton } = useIntlayer("structure-view");
|
|
148
146
|
const { setFocusedContentKeyPath } = useFocusUnmergedDictionary();
|
|
149
147
|
const { addEditedContent } = useEditedContentActions();
|
|
150
|
-
const keys = useMemo(() => section && typeof section === "object" ? Object.keys(section) : [], [section]);
|
|
151
|
-
const parentRef = useRef(null);
|
|
152
|
-
const rowVirtualizer = useVirtualizer({
|
|
153
|
-
count: keys.length,
|
|
154
|
-
getScrollElement: () => parentRef.current,
|
|
155
|
-
estimateSize: () => 140,
|
|
156
|
-
overscan: 5
|
|
157
|
-
});
|
|
158
148
|
if (!section || typeof section !== "object") return /* @__PURE__ */ jsx("div", { children: "Not an object" });
|
|
159
149
|
return /* @__PURE__ */ jsxs("div", {
|
|
160
|
-
className: "flex flex-col gap-2",
|
|
161
|
-
children: [/* @__PURE__ */ jsx("
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"data-index": virtualRow.index,
|
|
174
|
-
ref: rowVirtualizer.measureElement,
|
|
175
|
-
style: {
|
|
176
|
-
position: "absolute",
|
|
177
|
-
top: 0,
|
|
178
|
-
left: 0,
|
|
179
|
-
width: "100%",
|
|
180
|
-
transform: `translateY(${virtualRow.start}px)`
|
|
181
|
-
},
|
|
182
|
-
className: "pb-4",
|
|
183
|
-
children: /* @__PURE__ */ jsx(NodeView, {
|
|
184
|
-
sectionKey: key,
|
|
185
|
-
section: section?.[key],
|
|
186
|
-
keyPath: [...keyPath, {
|
|
187
|
-
type: NodeTypes.OBJECT,
|
|
188
|
-
key
|
|
189
|
-
}],
|
|
190
|
-
dictionaryLocalId
|
|
191
|
-
})
|
|
192
|
-
}, virtualRow.key);
|
|
150
|
+
className: "flex flex-col gap-2 overflow-y-auto",
|
|
151
|
+
children: [/* @__PURE__ */ jsx("ul", {
|
|
152
|
+
className: "mr-auto flex flex-col gap-4",
|
|
153
|
+
children: Object.keys(section).map((key) => /* @__PURE__ */ jsx("li", {
|
|
154
|
+
className: "flex w-full",
|
|
155
|
+
children: /* @__PURE__ */ jsx(NodeView, {
|
|
156
|
+
sectionKey: key,
|
|
157
|
+
section: section?.[key],
|
|
158
|
+
keyPath: [...keyPath, {
|
|
159
|
+
type: NodeTypes.OBJECT,
|
|
160
|
+
key
|
|
161
|
+
}],
|
|
162
|
+
dictionaryLocalId
|
|
193
163
|
})
|
|
194
|
-
})
|
|
164
|
+
}, `${JSON.stringify(keyPath)}-object-${key}`))
|
|
195
165
|
}), /* @__PURE__ */ jsx(Button, {
|
|
196
166
|
label: addNodeButton.label.value,
|
|
197
167
|
variant: "hoverable",
|
|
198
168
|
size: "md",
|
|
199
169
|
color: "text",
|
|
200
170
|
Icon: Plus,
|
|
201
|
-
className: "
|
|
171
|
+
className: "flex-1",
|
|
202
172
|
onClick: () => {
|
|
203
173
|
const newKey = "newKey";
|
|
204
174
|
const newKeyPath = [...keyPath, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StructureView.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/StructureView/StructureView.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { Container } from '@components/Container';\nimport { EditableFieldInput } from '@components/EditableField';\nimport { InputVariant } from '@components/Input';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getDefaultNode,\n getNodeChildren,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { isSameKeyPath } from '@intlayer/core/utils';\nimport {\n useConfiguration,\n useEditedContentActions,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { LocalDictionaryId, TypedNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { useVirtualizer } from '@tanstack/react-virtual';\nimport type { ContentNode } from 'intlayer';\nimport { Plus, Trash } from 'lucide-react';\nimport { type FC, memo, useMemo, useRef } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { NodeTypeSelector } from '../NodeTypeSelector';\n\ntype NodeTypeViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n onNodeTypeChange: (content?: ContentNode) => void;\n};\n\nconst NodeTypeView: FC<NodeTypeViewProps> = ({\n section,\n dictionaryLocalId,\n keyPath,\n onNodeTypeChange: onNodeTypeChangeProp,\n}) => {\n const locales = useConfiguration()?.internationalization?.locales ?? [];\n\n // Memoize node type and children calculations\n const nodeType = useMemo(() => getNodeType(section), [section]);\n const children = useMemo(() => getNodeChildren(section), [section]);\n\n const onNodeTypeChange = (content?: ContentNode) => {\n const transformedContent = getDefaultNode(\n nodeType,\n locales,\n content\n ) as ContentNode;\n\n onNodeTypeChangeProp(transformedContent);\n };\n\n if (\n nodeType === NodeTypes.TRANSLATION ||\n nodeType === NodeTypes.CONDITION ||\n nodeType === NodeTypes.GENDER ||\n nodeType === NodeTypes.ENUMERATION ||\n nodeType === NodeTypes.PLURAL\n ) {\n const firstKey = Object.keys(\n (section as unknown as TypedNode)[nodeType as keyof typeof section]\n )[0];\n const childrenKeyPath = [\n ...keyPath,\n { type: nodeType, key: firstKey },\n ] as KeyPath[];\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n\n <NodeTypeView\n section={children}\n keyPath={childrenKeyPath}\n dictionaryLocalId={dictionaryLocalId}\n onNodeTypeChange={onNodeTypeChange}\n />\n </div>\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n const childrenKeyPath = [...keyPath, { type: nodeType, key: 0 } as KeyPath];\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n\n <NodeTypeView\n section={children}\n keyPath={childrenKeyPath}\n dictionaryLocalId={dictionaryLocalId}\n onNodeTypeChange={onNodeTypeChange}\n />\n </div>\n );\n }\n\n if (nodeType === NodeTypes.OBJECT) {\n return (\n <>\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n <div className=\"mt-6 ml-10\">\n <StructureView\n keyPath={keyPath}\n section={section}\n dictionaryLocalId={dictionaryLocalId}\n />\n </div>\n </>\n );\n }\n\n return (\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(getDefaultNode(nodeType, locales) as ContentNode)\n }\n />\n );\n};\n\ntype NodeWrapperProps = {\n sectionKey?: string;\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const NodeView: FC<NodeWrapperProps> = memo(\n ({ sectionKey, section, keyPath, dictionaryLocalId }) => {\n const { focusedContent, setFocusedContentKeyPath } =\n useFocusUnmergedDictionary();\n const { renameEditedContent, addEditedContent } = useEditedContentActions();\n\n const { titleInput, deleteButton } = useIntlayer('structure-view');\n\n const handleRenameNodeKey = (keyName: string) => {\n renameEditedContent(dictionaryLocalId, keyName, keyPath);\n const prevKeyPath: KeyPath[] = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n const newKeyPath: KeyPath[] = [\n ...prevKeyPath,\n { ...lastKeyPath, key: keyName } as KeyPath,\n ];\n setFocusedContentKeyPath(newKeyPath);\n };\n\n return (\n <Container\n transparency=\"xl\"\n roundedSize=\"xl\"\n className=\"w-full min-w-80 gap-2 overflow-auto px-5 py-2\"\n border\n borderColor=\"text\"\n background=\"none\"\n aria-selected={isSameKeyPath(keyPath, focusedContent?.keyPath ?? [])}\n onClick={() => setFocusedContentKeyPath(keyPath)}\n >\n <div className=\"flex w-full flex-col items-start justify-between gap-3\">\n {typeof sectionKey === 'string' && (\n <div className=\"w-full\">\n <div className=\"flex w-full items-center justify-between gap-10\">\n <EditableFieldInput\n name=\"key\"\n aria-label=\"Key\"\n placeholder={titleInput.placeholder.value}\n defaultValue={sectionKey}\n onSave={(value) => handleRenameNodeKey(value)}\n variant={InputVariant.INVISIBLE}\n />\n <Button\n label={deleteButton.label.value}\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"translate-x-2\"\n Icon={Trash}\n onClick={() => {\n addEditedContent(dictionaryLocalId, undefined, keyPath);\n\n const parentKeyPath: KeyPath[] = keyPath.slice(0, -1);\n setFocusedContentKeyPath(parentKeyPath);\n }}\n />\n </div>\n\n <span className=\"ml-3 text-neutral text-sm\">\n ( {camelCaseToSentence(sectionKey)} )\n </span>\n </div>\n )}\n <NodeTypeView\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n section={section}\n onNodeTypeChange={(content) => {\n addEditedContent(dictionaryLocalId, content, keyPath);\n }}\n />\n </div>\n </Container>\n );\n }\n);\n\ntype ObjectViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const ObjectView: FC<ObjectViewProps> = ({\n section,\n keyPath,\n dictionaryLocalId,\n}) => {\n const { addNodeButton } = useIntlayer('structure-view');\n const { setFocusedContentKeyPath } = useFocusUnmergedDictionary();\n const { addEditedContent } = useEditedContentActions();\n\n // 1. Memoize keys to avoid unnecessary virtualizer resets\n const keys = useMemo(\n () => (section && typeof section === 'object' ? Object.keys(section) : []),\n [section]\n );\n\n // 2. Setup virtualization for large objects\n const parentRef = useRef<HTMLDivElement>(null);\n\n const rowVirtualizer = useVirtualizer({\n count: keys.length,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 140, // Estimated height for a NodeView\n overscan: 5,\n });\n\n if (!section || typeof section !== 'object') {\n return <div>Not an object</div>;\n }\n\n return (\n <div className=\"flex flex-col gap-2\">\n <div\n ref={parentRef}\n className=\"flex max-h-[800px] flex-col gap-4 overflow-y-auto pr-2\"\n >\n <div\n style={{\n height: `${rowVirtualizer.getTotalSize()}px`,\n width: '100%',\n position: 'relative',\n }}\n >\n {rowVirtualizer.getVirtualItems().map((virtualRow) => {\n const key = keys[virtualRow.index];\n return (\n <div\n key={virtualRow.key}\n data-index={virtualRow.index}\n ref={rowVirtualizer.measureElement}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }}\n className=\"pb-4\"\n >\n <NodeView\n sectionKey={key}\n section={section?.[key as keyof typeof section]}\n keyPath={[\n ...keyPath,\n { type: NodeTypes.OBJECT, key } as KeyPath,\n ]}\n dictionaryLocalId={dictionaryLocalId}\n />\n </div>\n );\n })}\n </div>\n </div>\n\n <Button\n label={addNodeButton.label.value}\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.MD}\n color={ButtonColor.TEXT}\n Icon={Plus}\n className=\"mt-2 flex-1\"\n onClick={() => {\n const newKey = 'newKey';\n const newKeyPath = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key: newKey },\n ] as KeyPath[];\n addEditedContent(dictionaryLocalId, '', newKeyPath);\n setFocusedContentKeyPath(newKeyPath);\n }}\n >\n {addNodeButton.text}\n </Button>\n </div>\n );\n};\n\ntype StructureViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const StructureView: FC<StructureViewProps> = ({\n section,\n keyPath,\n dictionaryLocalId,\n}) => {\n if (\n !section ||\n typeof section !== 'object' ||\n typeof section.nodeType === 'string'\n ) {\n return (\n <NodeView\n sectionKey={'content'}\n section={section}\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n />\n );\n }\n\n return (\n <ObjectView\n section={section}\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n />\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StructureView.mjs","names":[],"sources":["../../../../../src/components/DictionaryFieldEditor/StructureView/StructureView.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n ButtonColor,\n ButtonSize,\n ButtonVariant,\n} from '@components/Button';\nimport { Container } from '@components/Container';\nimport { EditableFieldInput } from '@components/EditableField';\nimport { InputVariant } from '@components/Input';\nimport { camelCaseToSentence } from '@intlayer/config/client';\nimport {\n getDefaultNode,\n getNodeChildren,\n getNodeType,\n} from '@intlayer/core/dictionaryManipulator';\nimport { isSameKeyPath } from '@intlayer/core/utils';\nimport {\n useConfiguration,\n useEditedContentActions,\n useFocusUnmergedDictionary,\n} from '@intlayer/editor-react';\nimport type { LocalDictionaryId, TypedNode } from '@intlayer/types/dictionary';\nimport type { KeyPath } from '@intlayer/types/keyPath';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport type { ContentNode } from 'intlayer';\nimport { Plus, Trash } from 'lucide-react';\nimport type { FC } from 'react';\nimport { useIntlayer } from 'react-intlayer';\nimport { NodeTypeSelector } from '../NodeTypeSelector';\n\ntype NodeTypeViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n onNodeTypeChange: (content?: ContentNode) => void;\n};\n\nconst NodeTypeView: FC<NodeTypeViewProps> = ({\n section,\n dictionaryLocalId,\n keyPath,\n onNodeTypeChange: onNodeTypeChangeProp,\n}) => {\n const locales = useConfiguration()?.internationalization?.locales ?? [];\n const nodeType = getNodeType(section);\n const children = getNodeChildren(section);\n\n const onNodeTypeChange = (content?: ContentNode) => {\n const transformedContent = getDefaultNode(\n nodeType,\n locales,\n content\n ) as ContentNode;\n\n onNodeTypeChangeProp(transformedContent);\n };\n\n if (\n nodeType === NodeTypes.TRANSLATION ||\n nodeType === NodeTypes.CONDITION ||\n nodeType === NodeTypes.GENDER ||\n nodeType === NodeTypes.ENUMERATION ||\n nodeType === NodeTypes.PLURAL\n ) {\n const firstKey = Object.keys(\n (section as unknown as TypedNode)[nodeType as keyof typeof section]\n )[0];\n const childrenKeyPath = [\n ...keyPath,\n { type: nodeType, key: firstKey },\n ] as KeyPath[];\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n\n <NodeTypeView\n section={children}\n keyPath={childrenKeyPath}\n dictionaryLocalId={dictionaryLocalId}\n onNodeTypeChange={onNodeTypeChange}\n />\n </div>\n );\n }\n\n if (nodeType === NodeTypes.ARRAY) {\n const childrenKeyPath = [...keyPath, { type: nodeType, key: 0 } as KeyPath];\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n\n <NodeTypeView\n section={children}\n keyPath={childrenKeyPath}\n dictionaryLocalId={dictionaryLocalId}\n onNodeTypeChange={onNodeTypeChange}\n />\n </div>\n );\n }\n\n if (nodeType === NodeTypes.OBJECT) {\n return (\n <>\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(\n getDefaultNode(nodeType, locales) as ContentNode\n )\n }\n />\n <div className=\"mt-6 ml-10\">\n <StructureView\n keyPath={keyPath}\n section={section}\n dictionaryLocalId={dictionaryLocalId}\n />\n </div>\n </>\n );\n }\n\n return (\n <NodeTypeSelector\n section={section}\n onValueChange={(nodeType) =>\n onNodeTypeChangeProp(getDefaultNode(nodeType, locales) as ContentNode)\n }\n />\n );\n};\n\ntype NodeWrapperProps = {\n sectionKey?: string;\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const NodeView: FC<NodeWrapperProps> = ({\n sectionKey,\n section,\n keyPath,\n dictionaryLocalId,\n}) => {\n const { focusedContent, setFocusedContentKeyPath } =\n useFocusUnmergedDictionary();\n const { renameEditedContent, addEditedContent } = useEditedContentActions();\n\n const { titleInput, deleteButton } = useIntlayer('structure-view');\n\n const handleRenameNodeKey = (keyName: string) => {\n renameEditedContent(dictionaryLocalId, keyName, keyPath);\n const prevKeyPath: KeyPath[] = keyPath.slice(0, -1);\n const lastKeyPath: KeyPath = keyPath[keyPath.length - 1];\n const newKeyPath: KeyPath[] = [\n ...prevKeyPath,\n { ...lastKeyPath, key: keyName } as KeyPath,\n ];\n setFocusedContentKeyPath(newKeyPath);\n };\n\n return (\n <Container\n transparency=\"xl\"\n roundedSize=\"xl\"\n className=\"w-full min-w-80 gap-2 overflow-auto px-5 py-2\"\n border\n borderColor=\"text\"\n background=\"none\"\n aria-selected={isSameKeyPath(keyPath, focusedContent?.keyPath ?? [])}\n onClick={() => setFocusedContentKeyPath(keyPath)}\n >\n <div className=\"flex w-full flex-col items-start justify-between gap-3\">\n {typeof sectionKey === 'string' && (\n <div className=\"w-full\">\n <div className=\"flex w-full items-center justify-between gap-10\">\n <EditableFieldInput\n name=\"key\"\n aria-label=\"Key\"\n placeholder={titleInput.placeholder.value}\n defaultValue={sectionKey}\n onSave={(value) => handleRenameNodeKey(value)}\n variant={InputVariant.INVISIBLE}\n />\n <Button\n label={deleteButton.label.value}\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.ICON_SM}\n color={ButtonColor.TEXT}\n className=\"translate-x-2\"\n Icon={Trash}\n onClick={() => {\n addEditedContent(dictionaryLocalId, undefined, keyPath);\n\n const parentKeyPath: KeyPath[] = keyPath.slice(0, -1);\n setFocusedContentKeyPath(parentKeyPath);\n }}\n />\n </div>\n\n <span className=\"ml-3 text-neutral text-sm\">\n ( {camelCaseToSentence(sectionKey)} )\n </span>\n </div>\n )}\n <NodeTypeView\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n section={section}\n onNodeTypeChange={(content) => {\n addEditedContent(dictionaryLocalId, content, keyPath);\n }}\n />\n </div>\n </Container>\n );\n};\n\ntype ObjectViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const ObjectView: FC<ObjectViewProps> = ({\n section,\n keyPath,\n dictionaryLocalId,\n}) => {\n const { addNodeButton } = useIntlayer('structure-view');\n const { setFocusedContentKeyPath } = useFocusUnmergedDictionary();\n const { addEditedContent } = useEditedContentActions();\n\n if (!section || typeof section !== 'object') {\n return <div>Not an object</div>;\n }\n\n return (\n <div className=\"flex flex-col gap-2 overflow-y-auto\">\n <ul className=\"mr-auto flex flex-col gap-4\">\n {Object.keys(section).map((key) => (\n <li\n key={`${JSON.stringify(keyPath)}-object-${key}`}\n className=\"flex w-full\"\n >\n <NodeView\n sectionKey={key}\n section={section?.[key as keyof typeof section]}\n keyPath={[...keyPath, { type: NodeTypes.OBJECT, key }]}\n dictionaryLocalId={dictionaryLocalId}\n />\n </li>\n ))}\n </ul>\n <Button\n label={addNodeButton.label.value}\n variant={ButtonVariant.HOVERABLE}\n size={ButtonSize.MD}\n color={ButtonColor.TEXT}\n Icon={Plus}\n className=\"flex-1\"\n onClick={() => {\n const newKey = 'newKey';\n const newKeyPath = [\n ...keyPath,\n { type: NodeTypes.OBJECT, key: newKey },\n ] as KeyPath[];\n addEditedContent(dictionaryLocalId, '', newKeyPath);\n setFocusedContentKeyPath(newKeyPath);\n }}\n >\n {addNodeButton.text}\n </Button>\n </div>\n );\n};\n\ntype StructureViewProps = {\n dictionaryLocalId: LocalDictionaryId;\n keyPath: KeyPath[];\n section: ContentNode;\n};\n\nexport const StructureView: FC<StructureViewProps> = ({\n section,\n keyPath,\n dictionaryLocalId,\n}) => {\n if (\n !section ||\n typeof section !== 'object' ||\n typeof section.nodeType === 'string'\n ) {\n return (\n <NodeView\n sectionKey={'content'}\n section={section}\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n />\n );\n }\n\n return (\n <ObjectView\n section={section}\n keyPath={keyPath}\n dictionaryLocalId={dictionaryLocalId}\n />\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useItemSelector } from "../../../hooks/useItemSelector.mjs";
|
|
4
3
|
import { InputIndicator, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot } from "../../Input/OTPInput.mjs";
|
|
4
|
+
import { useItemSelector } from "../../../hooks/useItemSelector.mjs";
|
|
5
5
|
import { useFormField } from "../FormField.mjs";
|
|
6
6
|
import { FormItemLayout } from "../layout/FormItemLayout.mjs";
|
|
7
7
|
import { Form } from "../Form.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useCodeContext } from "./CodeContext.mjs";
|
|
4
3
|
import { Select } from "../Select/Select.mjs";
|
|
4
|
+
import { useCodeContext } from "./CodeContext.mjs";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { useIntlayer } from "react-intlayer";
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useCodeContext } from "./CodeContext.mjs";
|
|
4
3
|
import { Select } from "../Select/Select.mjs";
|
|
4
|
+
import { useCodeContext } from "./CodeContext.mjs";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { useIntlayer } from "react-intlayer";
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { useCodeContext } from "./CodeContext.mjs";
|
|
4
3
|
import { Select } from "../Select/Select.mjs";
|
|
4
|
+
import { useCodeContext } from "./CodeContext.mjs";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { useIntlayer } from "react-intlayer";
|
|
7
7
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { cn } from "../../utils/cn.mjs";
|
|
4
4
|
import { Container } from "../Container/index.mjs";
|
|
5
5
|
import { Flag } from "../Flags/Flag.mjs";
|
|
6
|
-
import { useEffect, useState } from "react";
|
|
6
|
+
import { Suspense, useEffect, useState } from "react";
|
|
7
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { ALL_LOCALES, getHTMLTextDir, getLocaleName } from "intlayer";
|
|
9
9
|
|
|
@@ -56,9 +56,9 @@ const LanguageSection = ({ className, ...props }) => {
|
|
|
56
56
|
return /* @__PURE__ */ jsx("section", {
|
|
57
57
|
className: cn("mask-[linear-gradient(to_right,transparent_0,black_128px,black_calc(100%-128px),transparent_100%)] my-10 w-full overflow-hidden", className),
|
|
58
58
|
...props,
|
|
59
|
-
children: /* @__PURE__ */
|
|
59
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
60
60
|
className: "relative flex w-full flex-col gap-5 py-3",
|
|
61
|
-
children: [
|
|
61
|
+
children: /* @__PURE__ */ jsxs(Suspense, { children: [
|
|
62
62
|
/* @__PURE__ */ jsx(LocalCardList, {
|
|
63
63
|
localeList: firstPart,
|
|
64
64
|
className: "horizontal-loop-1"
|
|
@@ -75,7 +75,7 @@ const LanguageSection = ({ className, ...props }) => {
|
|
|
75
75
|
localeList: fourthPart,
|
|
76
76
|
className: "horizontal-loop-2"
|
|
77
77
|
})
|
|
78
|
-
]
|
|
78
|
+
] })
|
|
79
79
|
})
|
|
80
80
|
});
|
|
81
81
|
};
|