@form-engine-ts/mui 5.0.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +135 -63
- package/dist/index.d.cts +26 -5
- package/dist/index.d.ts +26 -5
- package/dist/index.js +141 -65
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1546,10 +1546,16 @@ function normalizeLocaleOptions(options, getLocaleLabel) {
|
|
|
1546
1546
|
const seen = /* @__PURE__ */ new Set();
|
|
1547
1547
|
const normalized = [];
|
|
1548
1548
|
for (const item of options) {
|
|
1549
|
-
const value = typeof item === "string" ? item : item.value;
|
|
1549
|
+
const value = typeof item === "string" ? item : "value" in item ? item.value : item.locale;
|
|
1550
1550
|
if (value.length === 0 || seen.has(value)) continue;
|
|
1551
1551
|
seen.add(value);
|
|
1552
|
-
normalized.push({
|
|
1552
|
+
normalized.push({
|
|
1553
|
+
value,
|
|
1554
|
+
label: typeof item === "string" ? getLocaleLabel?.(value) ?? value : item.label,
|
|
1555
|
+
...typeof item === "string" || item.translatable === void 0 ? {} : { translatable: item.translatable },
|
|
1556
|
+
...typeof item === "string" || item.removable === void 0 ? {} : { removable: item.removable },
|
|
1557
|
+
...typeof item === "string" || item.metadata === void 0 ? {} : { metadata: item.metadata }
|
|
1558
|
+
});
|
|
1553
1559
|
}
|
|
1554
1560
|
return normalized;
|
|
1555
1561
|
}
|
|
@@ -1592,6 +1598,8 @@ function createMuiLocalizationSlot(options) {
|
|
|
1592
1598
|
const hasLocaleSelector = filteredAvailableLocales !== void 0;
|
|
1593
1599
|
const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
|
|
1594
1600
|
const normalizedLocale = newLocale.trim();
|
|
1601
|
+
const currentLocaleOption = availableLocaleOptions?.find((locale) => locale.value === currentLocale);
|
|
1602
|
+
const currentLocaleTranslatable = currentLocaleOption?.translatable !== false;
|
|
1595
1603
|
const selectedLocaleAvailable = !hasLocaleSelector || filteredAvailableLocales.some((locale) => locale.value === normalizedLocale);
|
|
1596
1604
|
const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
|
|
1597
1605
|
const canAddLocale = !readOnly && normalizedLocale.length > 0 && selectedLocaleAvailable && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
@@ -1757,7 +1765,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1757
1765
|
{
|
|
1758
1766
|
variant: "secondary",
|
|
1759
1767
|
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1760
|
-
disabled: readOnly || !editingLocaleConfigured || isTranslating,
|
|
1768
|
+
disabled: readOnly || !editingLocaleConfigured || isTranslating || !currentLocaleTranslatable,
|
|
1761
1769
|
onClick: onAutoTranslate,
|
|
1762
1770
|
children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
|
|
1763
1771
|
}
|
|
@@ -1895,6 +1903,7 @@ function MuiFormBuilder({
|
|
|
1895
1903
|
muiSlotProps,
|
|
1896
1904
|
components: customComponents,
|
|
1897
1905
|
slots: customSlots,
|
|
1906
|
+
i18n,
|
|
1898
1907
|
sectionOrder,
|
|
1899
1908
|
...props
|
|
1900
1909
|
}) {
|
|
@@ -1906,7 +1915,14 @@ function MuiFormBuilder({
|
|
|
1906
1915
|
}),
|
|
1907
1916
|
[layoutOptions, localizationOptions, muiOptions, muiSlotProps]
|
|
1908
1917
|
);
|
|
1909
|
-
const
|
|
1918
|
+
const resolvedMuiOptions = (0, import_react5.useMemo)(
|
|
1919
|
+
() => mergeMuiAdapterOptions(contextOptions, {
|
|
1920
|
+
...i18n?.getLocaleLabel === void 0 ? {} : { getLocaleLabel: i18n.getLocaleLabel },
|
|
1921
|
+
...i18n?.getActionLabel === void 0 ? {} : { getActionLabel: i18n.getActionLabel }
|
|
1922
|
+
}),
|
|
1923
|
+
[contextOptions, i18n?.getActionLabel, i18n?.getLocaleLabel]
|
|
1924
|
+
);
|
|
1925
|
+
const contextValue = (0, import_react5.useMemo)(() => ({ options: resolvedMuiOptions }), [resolvedMuiOptions]);
|
|
1910
1926
|
const components = (0, import_react5.useMemo)(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
|
|
1911
1927
|
const slots = (0, import_react5.useMemo)(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
|
|
1912
1928
|
const placement = contextOptions.localizationOptions?.placement;
|
|
@@ -1927,7 +1943,7 @@ function MuiFormBuilder({
|
|
|
1927
1943
|
);
|
|
1928
1944
|
return order;
|
|
1929
1945
|
})();
|
|
1930
|
-
|
|
1946
|
+
const content = /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1931
1947
|
import_react4.FormBuilder,
|
|
1932
1948
|
{
|
|
1933
1949
|
...props,
|
|
@@ -1938,6 +1954,17 @@ function MuiFormBuilder({
|
|
|
1938
1954
|
...submissionSettingsOptions === void 0 ? {} : { submissionSettingsOptions }
|
|
1939
1955
|
}
|
|
1940
1956
|
) });
|
|
1957
|
+
if (i18n === void 0) return content;
|
|
1958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1959
|
+
import_react4.FormEngineI18nProvider,
|
|
1960
|
+
{
|
|
1961
|
+
...i18n.locale === void 0 ? {} : { locale: i18n.locale },
|
|
1962
|
+
...i18n.fallbackLocale === void 0 ? {} : { fallbackLocale: i18n.fallbackLocale },
|
|
1963
|
+
...i18n.messages === void 0 ? {} : { messages: i18n.messages },
|
|
1964
|
+
...i18n.translator === void 0 ? {} : { translator: i18n.translator },
|
|
1965
|
+
children: content
|
|
1966
|
+
}
|
|
1967
|
+
);
|
|
1941
1968
|
}
|
|
1942
1969
|
|
|
1943
1970
|
// src/workspace/TranslationWorkspace.tsx
|
|
@@ -1945,28 +1972,31 @@ var import_react6 = require("@form-engine-ts/react");
|
|
|
1945
1972
|
var import_material16 = require("@mui/material");
|
|
1946
1973
|
var import_react7 = require("react");
|
|
1947
1974
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1948
|
-
var
|
|
1949
|
-
missing: "
|
|
1950
|
-
translated: "
|
|
1951
|
-
stale: "
|
|
1952
|
-
manual: "
|
|
1953
|
-
"manual-stale": "
|
|
1975
|
+
var statusKey = {
|
|
1976
|
+
missing: "workspace.status.missing",
|
|
1977
|
+
translated: "workspace.status.translated",
|
|
1978
|
+
stale: "workspace.status.stale",
|
|
1979
|
+
manual: "workspace.status.manual",
|
|
1980
|
+
"manual-stale": "workspace.status.manualStale"
|
|
1954
1981
|
};
|
|
1955
1982
|
function SlotCard({
|
|
1956
1983
|
slot,
|
|
1957
1984
|
readOnly,
|
|
1958
1985
|
onChange,
|
|
1959
|
-
onTranslate
|
|
1986
|
+
onTranslate,
|
|
1987
|
+
translate,
|
|
1988
|
+
renderStatusBadge
|
|
1960
1989
|
}) {
|
|
1990
|
+
const status = slot.status ?? "missing";
|
|
1961
1991
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Card, { variant: "outlined", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.CardContent, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { spacing: 1.5, children: [
|
|
1962
1992
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [
|
|
1963
1993
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "subtitle2", children: slot.path }),
|
|
1964
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Chip, { size: "small", label:
|
|
1994
|
+
renderStatusBadge?.({ status }) ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Chip, { size: "small", label: translate(statusKey[status]) })
|
|
1965
1995
|
] }),
|
|
1966
1996
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1967
1997
|
import_material16.TextField,
|
|
1968
1998
|
{
|
|
1969
|
-
label: "
|
|
1999
|
+
label: translate("workspace.slot.sourceText"),
|
|
1970
2000
|
value: slot.sourceText,
|
|
1971
2001
|
multiline: true,
|
|
1972
2002
|
fullWidth: true,
|
|
@@ -1976,7 +2006,7 @@ function SlotCard({
|
|
|
1976
2006
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1977
2007
|
import_material16.TextField,
|
|
1978
2008
|
{
|
|
1979
|
-
label: "
|
|
2009
|
+
label: translate("workspace.slot.translatedText"),
|
|
1980
2010
|
value: slot.existingText ?? "",
|
|
1981
2011
|
multiline: true,
|
|
1982
2012
|
fullWidth: true,
|
|
@@ -1984,28 +2014,28 @@ function SlotCard({
|
|
|
1984
2014
|
onChange: (event) => onChange(event.target.value)
|
|
1985
2015
|
}
|
|
1986
2016
|
),
|
|
1987
|
-
slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "warning.main", variant: "body2", children: "
|
|
1988
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Button, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: "
|
|
2017
|
+
slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "warning.main", variant: "body2", children: translate("workspace.status.stale") }) : null,
|
|
2018
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Button, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: translate("workspace.slot.translateSingle") })
|
|
1989
2019
|
] }) }) });
|
|
1990
2020
|
}
|
|
1991
|
-
function workspaceErrorMessage(error) {
|
|
2021
|
+
function workspaceErrorMessage(error, translate) {
|
|
1992
2022
|
switch (error.type) {
|
|
1993
2023
|
case "locale_not_allowed":
|
|
1994
|
-
return
|
|
2024
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1995
2025
|
case "locale_already_exists":
|
|
1996
|
-
return
|
|
2026
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1997
2027
|
case "invalid_locale_format":
|
|
1998
|
-
return
|
|
2028
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1999
2029
|
case "max_locales_exceeded":
|
|
2000
|
-
return
|
|
2030
|
+
return translate("workspace.errors.maxLocalesExceeded", { max: error.max });
|
|
2001
2031
|
case "read_only_mode":
|
|
2002
|
-
return "
|
|
2032
|
+
return translate("workspace.errors.readOnly");
|
|
2003
2033
|
case "adapter_not_configured":
|
|
2004
|
-
return "
|
|
2034
|
+
return translate("workspace.errors.adapterNotConfigured");
|
|
2005
2035
|
case "target_locale_missing":
|
|
2006
|
-
return "
|
|
2036
|
+
return translate("workspace.empty.noTargetLocales");
|
|
2007
2037
|
case "translation_failed":
|
|
2008
|
-
return
|
|
2038
|
+
return translate("workspace.errors.translationFailed");
|
|
2009
2039
|
case "custom_validation_failed":
|
|
2010
2040
|
return error.message;
|
|
2011
2041
|
}
|
|
@@ -2016,81 +2046,123 @@ function TranslationWorkspace({
|
|
|
2016
2046
|
sourceLocale,
|
|
2017
2047
|
targetLocale,
|
|
2018
2048
|
translationAdapter,
|
|
2019
|
-
readOnly = false
|
|
2049
|
+
readOnly = false,
|
|
2050
|
+
availableLocales,
|
|
2051
|
+
onLocaleAdded,
|
|
2052
|
+
onLocaleRemoved,
|
|
2053
|
+
onLocaleChange,
|
|
2054
|
+
beforeRemoveLocale,
|
|
2055
|
+
slots: workspaceSlots
|
|
2020
2056
|
}) {
|
|
2057
|
+
const { translator } = (0, import_react6.useFormEngineI18n)();
|
|
2058
|
+
const translate = (key, params = {}) => translator(key, params);
|
|
2021
2059
|
const workspace = (0, import_react6.useTranslationWorkspace)({
|
|
2022
2060
|
schema,
|
|
2023
2061
|
...onChange === void 0 ? {} : { onChange },
|
|
2024
2062
|
...sourceLocale === void 0 ? {} : { sourceLocale },
|
|
2025
2063
|
...targetLocale === void 0 ? {} : { targetLocale },
|
|
2026
2064
|
...translationAdapter === void 0 ? {} : { translationAdapter },
|
|
2027
|
-
readOnly
|
|
2065
|
+
readOnly,
|
|
2066
|
+
...availableLocales === void 0 ? {} : { availableLocales },
|
|
2067
|
+
...onLocaleAdded === void 0 ? {} : { onLocaleAdded },
|
|
2068
|
+
...onLocaleRemoved === void 0 ? {} : { onLocaleRemoved },
|
|
2069
|
+
...onLocaleChange === void 0 ? {} : { onLocaleChange },
|
|
2070
|
+
...beforeRemoveLocale === void 0 ? {} : { beforeRemoveLocale }
|
|
2028
2071
|
});
|
|
2029
2072
|
const [newLocale, setNewLocale] = (0, import_react7.useState)("");
|
|
2073
|
+
const headerProps = {
|
|
2074
|
+
schema,
|
|
2075
|
+
sourceLocale: workspace.sourceLocale,
|
|
2076
|
+
targetLocale: workspace.targetLocale,
|
|
2077
|
+
summary: workspace.summary,
|
|
2078
|
+
onTranslateAll: () => void workspace.translateAll(),
|
|
2079
|
+
isTranslating: workspace.isTranslating,
|
|
2080
|
+
readOnly
|
|
2081
|
+
};
|
|
2082
|
+
const actionsProps = {
|
|
2083
|
+
onTranslateAll: headerProps.onTranslateAll,
|
|
2084
|
+
isTranslating: workspace.isTranslating,
|
|
2085
|
+
readOnly
|
|
2086
|
+
};
|
|
2087
|
+
const localeSelectorProps = {
|
|
2088
|
+
targetLocale: workspace.targetLocale,
|
|
2089
|
+
targetLocales: workspace.targetLocales,
|
|
2090
|
+
localeOptions: workspace.localeOptions,
|
|
2091
|
+
newLocale,
|
|
2092
|
+
readOnly,
|
|
2093
|
+
onTargetLocaleChange: workspace.setTargetLocale,
|
|
2094
|
+
onNewLocaleChange: setNewLocale,
|
|
2095
|
+
onAddLocale: () => {
|
|
2096
|
+
const result = workspace.addLocale(newLocale);
|
|
2097
|
+
if (result.success) setNewLocale("");
|
|
2098
|
+
}
|
|
2099
|
+
};
|
|
2030
2100
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { spacing: 2, "data-testid": "translation-workspace", children: [
|
|
2031
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
|
|
2032
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "h6", children: "
|
|
2033
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.
|
|
2034
|
-
workspace.summary.
|
|
2035
|
-
|
|
2036
|
-
workspace.summary.
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
")"
|
|
2040
|
-
] }),
|
|
2041
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2101
|
+
workspaceSlots?.renderHeader?.(headerProps) ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "h6", children: translate("workspace.header.title") }),
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { variant: "body2", children: translate("workspace.header.progress", {
|
|
2104
|
+
translated: workspace.summary.translatedCount,
|
|
2105
|
+
total: workspace.summary.totalSlots,
|
|
2106
|
+
percent: workspace.summary.completionPercentage
|
|
2107
|
+
}) }),
|
|
2108
|
+
workspaceSlots?.renderActions?.(actionsProps) ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2042
2109
|
import_material16.Button,
|
|
2043
2110
|
{
|
|
2044
2111
|
variant: "contained",
|
|
2045
|
-
onClick:
|
|
2112
|
+
onClick: headerProps.onTranslateAll,
|
|
2046
2113
|
disabled: readOnly || workspace.isTranslating,
|
|
2047
|
-
children: "
|
|
2114
|
+
children: translate("workspace.header.translateAll")
|
|
2048
2115
|
}
|
|
2049
2116
|
)
|
|
2050
2117
|
] }),
|
|
2051
2118
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.LinearProgress, { variant: "determinate", value: workspace.summary.completionPercentage }),
|
|
2052
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2119
|
+
workspaceSlots?.renderLocaleSelector?.(localeSelectorProps) ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2120
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Typography, { variant: "body2", children: [
|
|
2121
|
+
translate("workspace.header.sourceLocale"),
|
|
2122
|
+
": ",
|
|
2123
|
+
workspace.sourceLocale
|
|
2124
|
+
] }),
|
|
2125
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_material16.Typography, { variant: "body2", children: [
|
|
2126
|
+
translate("workspace.header.targetLocale"),
|
|
2127
|
+
":"
|
|
2128
|
+
] }),
|
|
2053
2129
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2054
2130
|
import_material16.Tabs,
|
|
2055
2131
|
{
|
|
2056
2132
|
value: workspace.targetLocale,
|
|
2057
2133
|
onChange: (_event, value) => workspace.setTargetLocale(value),
|
|
2058
|
-
"aria-label": "
|
|
2059
|
-
children: workspace.targetLocales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2134
|
+
"aria-label": translate("workspace.header.targetLocale"),
|
|
2135
|
+
children: workspace.targetLocales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2136
|
+
import_material16.Tab,
|
|
2137
|
+
{
|
|
2138
|
+
value: locale,
|
|
2139
|
+
label: workspace.localeOptions.find((option) => option.locale === locale)?.label ?? locale
|
|
2140
|
+
},
|
|
2141
|
+
locale
|
|
2142
|
+
))
|
|
2060
2143
|
}
|
|
2061
2144
|
),
|
|
2062
2145
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2063
2146
|
import_material16.TextField,
|
|
2064
2147
|
{
|
|
2065
2148
|
size: "small",
|
|
2066
|
-
label: "
|
|
2149
|
+
label: translate("workspace.header.targetLocale"),
|
|
2067
2150
|
value: newLocale,
|
|
2068
2151
|
onChange: (event) => setNewLocale(event.target.value)
|
|
2069
2152
|
}
|
|
2070
2153
|
),
|
|
2071
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2072
|
-
import_material16.Button,
|
|
2073
|
-
{
|
|
2074
|
-
onClick: () => {
|
|
2075
|
-
workspace.addLocale(newLocale);
|
|
2076
|
-
setNewLocale("");
|
|
2077
|
-
},
|
|
2078
|
-
disabled: readOnly,
|
|
2079
|
-
children: "Add"
|
|
2080
|
-
}
|
|
2081
|
-
)
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Button, { onClick: localeSelectorProps.onAddLocale, disabled: readOnly, children: translate("builder.addLocale") })
|
|
2082
2155
|
] }),
|
|
2083
|
-
workspace.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "error", children: workspaceErrorMessage(workspace.error) }),
|
|
2084
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Stack, { spacing: 1.5, children: workspace.slots.
|
|
2085
|
-
|
|
2086
|
-
{
|
|
2156
|
+
workspace.error === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "error", children: workspaceErrorMessage(workspace.error, translate) }),
|
|
2157
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Stack, { spacing: 1.5, children: workspace.slots.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_material16.Typography, { color: "text.secondary", children: workspace.targetLocales.length === 0 ? translate("workspace.empty.noTargetLocales") : translate("workspace.empty.noSlotsToTranslate") }) : workspace.slots.map((slot) => {
|
|
2158
|
+
const rowProps = {
|
|
2087
2159
|
slot,
|
|
2088
2160
|
readOnly,
|
|
2089
2161
|
onChange: (text) => workspace.setTranslation(slot, text),
|
|
2090
2162
|
onTranslate: () => void workspace.translateSlot(slot)
|
|
2091
|
-
}
|
|
2092
|
-
slot.path
|
|
2093
|
-
)
|
|
2163
|
+
};
|
|
2164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: workspaceSlots?.renderSlotRow?.(rowProps) ?? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SlotCard, { ...rowProps, translate, renderStatusBadge: workspaceSlots?.renderStatusBadge }) }, slot.path);
|
|
2165
|
+
}) })
|
|
2094
2166
|
] });
|
|
2095
2167
|
}
|
|
2096
2168
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BuilderActionIconType, FieldPropertyControlMode, QuestionType, FieldEditorControlsConfig, FieldTypeSelectOptionsConfig, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, ChoiceGroupSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
1
|
+
import { BuilderActionIconType, FieldPropertyControlMode, QuestionType, FieldEditorControlsConfig, FieldTypeSelectOptionsConfig, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, ChoiceGroupSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps, TranslationWorkspaceSlots } from '@form-engine-ts/react';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, ComponentType, ReactElement } from 'react';
|
|
4
|
+
import { FormEngineMessages, FormEngineTranslator, LocaleOption, FormSchema, DisplayRule, TranslationAdapter, AsyncTranslationAdapter } from '@form-engine-ts/core';
|
|
4
5
|
import { CardProps, PaperProps, AccordionProps, StackProps, TextFieldProps, SelectProps, MenuProps, CheckboxProps, ButtonProps, IconButtonProps } from '@mui/material';
|
|
5
|
-
import { FormSchema, DisplayRule, TranslationAdapter, AsyncTranslationAdapter } from '@form-engine-ts/core';
|
|
6
6
|
|
|
7
7
|
type BuilderSectionName = "basicSettings" | "completionMessage" | "questions" | "addQuestion" | "localization" | "submissionSettings";
|
|
8
8
|
type MuiButtonVariant = "contained" | "outlined" | "text";
|
|
@@ -12,6 +12,18 @@ type MuiComponentSlotProps<T> = Partial<T> & {
|
|
|
12
12
|
interface LocaleOptionItem {
|
|
13
13
|
readonly value: string;
|
|
14
14
|
readonly label: string;
|
|
15
|
+
readonly translatable?: boolean;
|
|
16
|
+
readonly removable?: boolean;
|
|
17
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
18
|
+
}
|
|
19
|
+
type MuiLocaleOption = LocaleOption | LocaleOptionItem;
|
|
20
|
+
interface MuiFormEngineI18nOptions {
|
|
21
|
+
readonly locale?: string;
|
|
22
|
+
readonly fallbackLocale?: string;
|
|
23
|
+
readonly messages?: FormEngineMessages;
|
|
24
|
+
readonly translator?: FormEngineTranslator;
|
|
25
|
+
readonly getLocaleLabel?: (locale: string) => string;
|
|
26
|
+
readonly getActionLabel?: (actionType: string) => string;
|
|
15
27
|
}
|
|
16
28
|
type LocalizationSectionPlacement = "top" | "beforeQuestions" | "afterQuestions" | "bottom";
|
|
17
29
|
interface MuiLayoutOptions {
|
|
@@ -174,8 +186,9 @@ interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "dis
|
|
|
174
186
|
readonly muiSlotProps?: MuiBuilderSlotProps;
|
|
175
187
|
readonly components?: Partial<FormBuilderComponents>;
|
|
176
188
|
readonly slots?: Partial<FormBuilderSlots>;
|
|
189
|
+
readonly i18n?: MuiFormEngineI18nOptions;
|
|
177
190
|
}
|
|
178
|
-
declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, submissionSettingsOptions, muiSlotProps, components: customComponents, slots: customSlots, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
|
|
191
|
+
declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, submissionSettingsOptions, muiSlotProps, components: customComponents, slots: customSlots, i18n, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
|
|
179
192
|
|
|
180
193
|
interface ConditionEditorProps {
|
|
181
194
|
readonly schema: FormSchema;
|
|
@@ -210,7 +223,15 @@ interface TranslationWorkspaceProps {
|
|
|
210
223
|
readonly targetLocale?: string;
|
|
211
224
|
readonly translationAdapter?: TranslationAdapter | AsyncTranslationAdapter;
|
|
212
225
|
readonly readOnly?: boolean;
|
|
226
|
+
readonly availableLocales?: readonly (string | LocaleOption)[];
|
|
227
|
+
readonly onLocaleAdded?: (locale: string) => void;
|
|
228
|
+
readonly onLocaleRemoved?: (locale: string) => void;
|
|
229
|
+
readonly onLocaleChange?: (locale: string) => void;
|
|
230
|
+
readonly beforeRemoveLocale?: (locale: string, context: {
|
|
231
|
+
readonly slotCount: number;
|
|
232
|
+
}) => Promise<boolean> | boolean;
|
|
233
|
+
readonly slots?: TranslationWorkspaceSlots;
|
|
213
234
|
}
|
|
214
|
-
declare function TranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly }: TranslationWorkspaceProps): react.JSX.Element;
|
|
235
|
+
declare function TranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, availableLocales, onLocaleAdded, onLocaleRemoved, onLocaleChange, beforeRemoveLocale, slots: workspaceSlots }: TranslationWorkspaceProps): react.JSX.Element;
|
|
215
236
|
|
|
216
|
-
export { type BuilderSectionName, ConditionEditor, type ConditionEditorProps, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiChoiceGroupSlot, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, type MuiSlotProps, type MuiSubmissionSettingsOptions, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, TranslationWorkspace, type TranslationWorkspaceProps, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultFieldTypeIcon, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
|
237
|
+
export { type BuilderSectionName, ConditionEditor, type ConditionEditorProps, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiChoiceGroupSlot, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, type MuiFormEngineI18nOptions, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocaleOption, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, type MuiSlotProps, type MuiSubmissionSettingsOptions, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, TranslationWorkspace, type TranslationWorkspaceProps, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultFieldTypeIcon, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BuilderActionIconType, FieldPropertyControlMode, QuestionType, FieldEditorControlsConfig, FieldTypeSelectOptionsConfig, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, ChoiceGroupSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps } from '@form-engine-ts/react';
|
|
1
|
+
import { BuilderActionIconType, FieldPropertyControlMode, QuestionType, FieldEditorControlsConfig, FieldTypeSelectOptionsConfig, LocalizationSummaryContext, BuilderButtonProps, BuilderCheckboxProps, BuilderErrorMessageProps, BuilderFieldsetProps, BuilderIconButtonProps, BuilderSectionProps, BuilderSelectProps, BuilderTextAreaProps, BuilderTextInputProps, FormBuilderComponents, FormBuilderSlots, FormBuilderProps, BuilderFieldEditorSlotProps, BuilderLocalizationSlotProps, ChoiceGroupSlotProps, BuilderOptionEditorSlotProps, BuilderToolbarSlotProps, TranslationWorkspaceSlots } from '@form-engine-ts/react';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, ComponentType, ReactElement } from 'react';
|
|
4
|
+
import { FormEngineMessages, FormEngineTranslator, LocaleOption, FormSchema, DisplayRule, TranslationAdapter, AsyncTranslationAdapter } from '@form-engine-ts/core';
|
|
4
5
|
import { CardProps, PaperProps, AccordionProps, StackProps, TextFieldProps, SelectProps, MenuProps, CheckboxProps, ButtonProps, IconButtonProps } from '@mui/material';
|
|
5
|
-
import { FormSchema, DisplayRule, TranslationAdapter, AsyncTranslationAdapter } from '@form-engine-ts/core';
|
|
6
6
|
|
|
7
7
|
type BuilderSectionName = "basicSettings" | "completionMessage" | "questions" | "addQuestion" | "localization" | "submissionSettings";
|
|
8
8
|
type MuiButtonVariant = "contained" | "outlined" | "text";
|
|
@@ -12,6 +12,18 @@ type MuiComponentSlotProps<T> = Partial<T> & {
|
|
|
12
12
|
interface LocaleOptionItem {
|
|
13
13
|
readonly value: string;
|
|
14
14
|
readonly label: string;
|
|
15
|
+
readonly translatable?: boolean;
|
|
16
|
+
readonly removable?: boolean;
|
|
17
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
18
|
+
}
|
|
19
|
+
type MuiLocaleOption = LocaleOption | LocaleOptionItem;
|
|
20
|
+
interface MuiFormEngineI18nOptions {
|
|
21
|
+
readonly locale?: string;
|
|
22
|
+
readonly fallbackLocale?: string;
|
|
23
|
+
readonly messages?: FormEngineMessages;
|
|
24
|
+
readonly translator?: FormEngineTranslator;
|
|
25
|
+
readonly getLocaleLabel?: (locale: string) => string;
|
|
26
|
+
readonly getActionLabel?: (actionType: string) => string;
|
|
15
27
|
}
|
|
16
28
|
type LocalizationSectionPlacement = "top" | "beforeQuestions" | "afterQuestions" | "bottom";
|
|
17
29
|
interface MuiLayoutOptions {
|
|
@@ -174,8 +186,9 @@ interface MuiFormBuilderProps extends Omit<FormBuilderProps, "components" | "dis
|
|
|
174
186
|
readonly muiSlotProps?: MuiBuilderSlotProps;
|
|
175
187
|
readonly components?: Partial<FormBuilderComponents>;
|
|
176
188
|
readonly slots?: Partial<FormBuilderSlots>;
|
|
189
|
+
readonly i18n?: MuiFormEngineI18nOptions;
|
|
177
190
|
}
|
|
178
|
-
declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, submissionSettingsOptions, muiSlotProps, components: customComponents, slots: customSlots, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
|
|
191
|
+
declare function MuiFormBuilder({ muiOptions, layoutOptions, localizationOptions, submissionSettingsOptions, muiSlotProps, components: customComponents, slots: customSlots, i18n, sectionOrder, ...props }: MuiFormBuilderProps): react.JSX.Element;
|
|
179
192
|
|
|
180
193
|
interface ConditionEditorProps {
|
|
181
194
|
readonly schema: FormSchema;
|
|
@@ -210,7 +223,15 @@ interface TranslationWorkspaceProps {
|
|
|
210
223
|
readonly targetLocale?: string;
|
|
211
224
|
readonly translationAdapter?: TranslationAdapter | AsyncTranslationAdapter;
|
|
212
225
|
readonly readOnly?: boolean;
|
|
226
|
+
readonly availableLocales?: readonly (string | LocaleOption)[];
|
|
227
|
+
readonly onLocaleAdded?: (locale: string) => void;
|
|
228
|
+
readonly onLocaleRemoved?: (locale: string) => void;
|
|
229
|
+
readonly onLocaleChange?: (locale: string) => void;
|
|
230
|
+
readonly beforeRemoveLocale?: (locale: string, context: {
|
|
231
|
+
readonly slotCount: number;
|
|
232
|
+
}) => Promise<boolean> | boolean;
|
|
233
|
+
readonly slots?: TranslationWorkspaceSlots;
|
|
213
234
|
}
|
|
214
|
-
declare function TranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly }: TranslationWorkspaceProps): react.JSX.Element;
|
|
235
|
+
declare function TranslationWorkspace({ schema, onChange, sourceLocale, targetLocale, translationAdapter, readOnly, availableLocales, onLocaleAdded, onLocaleRemoved, onLocaleChange, beforeRemoveLocale, slots: workspaceSlots }: TranslationWorkspaceProps): react.JSX.Element;
|
|
215
236
|
|
|
216
|
-
export { type BuilderSectionName, ConditionEditor, type ConditionEditorProps, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiChoiceGroupSlot, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, type MuiSlotProps, type MuiSubmissionSettingsOptions, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, TranslationWorkspace, type TranslationWorkspaceProps, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultFieldTypeIcon, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
|
237
|
+
export { type BuilderSectionName, ConditionEditor, type ConditionEditorProps, DEFAULT_MUI_SECTION_ORDER, type LocaleOptionItem, type LocalizationSectionPlacement, MUI_LOCALIZATION_SECTION_ORDERS, type MuiAdapterOptions, type MuiBuilderOverrides, type MuiBuilderSlotProps, MuiButtonAdapter, type MuiButtonVariant, MuiCheckboxAdapter, MuiChoiceGroupSlot, MuiErrorMessageAdapter, type MuiFieldEditorOptions, MuiFieldEditorSlot, MuiFieldsetAdapter, MuiFormBuilder, MuiFormBuilderContext, type MuiFormBuilderContextValue, type MuiFormBuilderProps, type MuiFormEngineI18nOptions, MuiIconButtonAdapter, type MuiLayoutOptions, type MuiLocaleOption, type MuiLocalizationOptions, MuiLocalizationSlot, MuiOptionEditorSlot, MuiSectionAdapter, MuiSelectAdapter, type MuiSlotProps, type MuiSubmissionSettingsOptions, MuiTextAreaAdapter, MuiTextInputAdapter, MuiToolbarSlot, type ResolvedMuiAdapterOptions, TranslationWorkspace, type TranslationWorkspaceProps, createMuiBuilderComponents, createMuiBuilderProps, createMuiBuilderSlots, createMuiButtonAdapter, createMuiCheckboxAdapter, createMuiErrorMessageAdapter, createMuiFieldEditorSlot, createMuiFieldsetAdapter, createMuiIconButtonAdapter, createMuiLocalizationSlot, createMuiOptionEditorSlot, createMuiSectionAdapter, createMuiSelectAdapter, createMuiTextAreaAdapter, createMuiTextInputAdapter, createMuiToolbarSlot, mergeMuiAdapterOptions, muiBuilderComponents, muiBuilderSlots, muiDefaultFieldTypeIcon, muiDefaultIconResolver, resolveMuiAdapterOptions, useResolvedMuiAdapterOptions };
|
package/dist/index.js
CHANGED
|
@@ -1526,10 +1526,16 @@ function normalizeLocaleOptions(options, getLocaleLabel) {
|
|
|
1526
1526
|
const seen = /* @__PURE__ */ new Set();
|
|
1527
1527
|
const normalized = [];
|
|
1528
1528
|
for (const item of options) {
|
|
1529
|
-
const value = typeof item === "string" ? item : item.value;
|
|
1529
|
+
const value = typeof item === "string" ? item : "value" in item ? item.value : item.locale;
|
|
1530
1530
|
if (value.length === 0 || seen.has(value)) continue;
|
|
1531
1531
|
seen.add(value);
|
|
1532
|
-
normalized.push({
|
|
1532
|
+
normalized.push({
|
|
1533
|
+
value,
|
|
1534
|
+
label: typeof item === "string" ? getLocaleLabel?.(value) ?? value : item.label,
|
|
1535
|
+
...typeof item === "string" || item.translatable === void 0 ? {} : { translatable: item.translatable },
|
|
1536
|
+
...typeof item === "string" || item.removable === void 0 ? {} : { removable: item.removable },
|
|
1537
|
+
...typeof item === "string" || item.metadata === void 0 ? {} : { metadata: item.metadata }
|
|
1538
|
+
});
|
|
1533
1539
|
}
|
|
1534
1540
|
return normalized;
|
|
1535
1541
|
}
|
|
@@ -1572,6 +1578,8 @@ function createMuiLocalizationSlot(options) {
|
|
|
1572
1578
|
const hasLocaleSelector = filteredAvailableLocales !== void 0;
|
|
1573
1579
|
const localeLimitReached = policy?.maxLocales !== void 0 && registeredLocales.size >= policy.maxLocales;
|
|
1574
1580
|
const normalizedLocale = newLocale.trim();
|
|
1581
|
+
const currentLocaleOption = availableLocaleOptions?.find((locale) => locale.value === currentLocale);
|
|
1582
|
+
const currentLocaleTranslatable = currentLocaleOption?.translatable !== false;
|
|
1575
1583
|
const selectedLocaleAvailable = !hasLocaleSelector || filteredAvailableLocales.some((locale) => locale.value === normalizedLocale);
|
|
1576
1584
|
const localeAllowed = policy?.allowedLocales === void 0 || policy.allowedLocales.includes(normalizedLocale);
|
|
1577
1585
|
const canAddLocale = !readOnly && normalizedLocale.length > 0 && selectedLocaleAvailable && localeAllowed && !registeredLocales.has(normalizedLocale) && !localeLimitReached;
|
|
@@ -1737,7 +1745,7 @@ function createMuiLocalizationSlot(options) {
|
|
|
1737
1745
|
{
|
|
1738
1746
|
variant: "secondary",
|
|
1739
1747
|
noWrap: localizationOptions.noWrapActions ?? true,
|
|
1740
|
-
disabled: readOnly || !editingLocaleConfigured || isTranslating,
|
|
1748
|
+
disabled: readOnly || !editingLocaleConfigured || isTranslating || !currentLocaleTranslatable,
|
|
1741
1749
|
onClick: onAutoTranslate,
|
|
1742
1750
|
children: isTranslating ? translate("builder.translating") : translate("builder.autoTranslate")
|
|
1743
1751
|
}
|
|
@@ -1865,7 +1873,8 @@ function createMuiBuilderProps(options, overrides = {}) {
|
|
|
1865
1873
|
|
|
1866
1874
|
// src/MuiFormBuilder.tsx
|
|
1867
1875
|
import {
|
|
1868
|
-
FormBuilder
|
|
1876
|
+
FormBuilder,
|
|
1877
|
+
FormEngineI18nProvider
|
|
1869
1878
|
} from "@form-engine-ts/react";
|
|
1870
1879
|
import { useMemo } from "react";
|
|
1871
1880
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
@@ -1877,6 +1886,7 @@ function MuiFormBuilder({
|
|
|
1877
1886
|
muiSlotProps,
|
|
1878
1887
|
components: customComponents,
|
|
1879
1888
|
slots: customSlots,
|
|
1889
|
+
i18n,
|
|
1880
1890
|
sectionOrder,
|
|
1881
1891
|
...props
|
|
1882
1892
|
}) {
|
|
@@ -1888,7 +1898,14 @@ function MuiFormBuilder({
|
|
|
1888
1898
|
}),
|
|
1889
1899
|
[layoutOptions, localizationOptions, muiOptions, muiSlotProps]
|
|
1890
1900
|
);
|
|
1891
|
-
const
|
|
1901
|
+
const resolvedMuiOptions = useMemo(
|
|
1902
|
+
() => mergeMuiAdapterOptions(contextOptions, {
|
|
1903
|
+
...i18n?.getLocaleLabel === void 0 ? {} : { getLocaleLabel: i18n.getLocaleLabel },
|
|
1904
|
+
...i18n?.getActionLabel === void 0 ? {} : { getActionLabel: i18n.getActionLabel }
|
|
1905
|
+
}),
|
|
1906
|
+
[contextOptions, i18n?.getActionLabel, i18n?.getLocaleLabel]
|
|
1907
|
+
);
|
|
1908
|
+
const contextValue = useMemo(() => ({ options: resolvedMuiOptions }), [resolvedMuiOptions]);
|
|
1892
1909
|
const components = useMemo(() => ({ ...muiBuilderComponents, ...customComponents }), [customComponents]);
|
|
1893
1910
|
const slots = useMemo(() => ({ ...muiBuilderSlots, ...customSlots }), [customSlots]);
|
|
1894
1911
|
const placement = contextOptions.localizationOptions?.placement;
|
|
@@ -1909,7 +1926,7 @@ function MuiFormBuilder({
|
|
|
1909
1926
|
);
|
|
1910
1927
|
return order;
|
|
1911
1928
|
})();
|
|
1912
|
-
|
|
1929
|
+
const content = /* @__PURE__ */ jsx17(MuiFormBuilderContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx17(
|
|
1913
1930
|
FormBuilder,
|
|
1914
1931
|
{
|
|
1915
1932
|
...props,
|
|
@@ -1920,10 +1937,24 @@ function MuiFormBuilder({
|
|
|
1920
1937
|
...submissionSettingsOptions === void 0 ? {} : { submissionSettingsOptions }
|
|
1921
1938
|
}
|
|
1922
1939
|
) });
|
|
1940
|
+
if (i18n === void 0) return content;
|
|
1941
|
+
return /* @__PURE__ */ jsx17(
|
|
1942
|
+
FormEngineI18nProvider,
|
|
1943
|
+
{
|
|
1944
|
+
...i18n.locale === void 0 ? {} : { locale: i18n.locale },
|
|
1945
|
+
...i18n.fallbackLocale === void 0 ? {} : { fallbackLocale: i18n.fallbackLocale },
|
|
1946
|
+
...i18n.messages === void 0 ? {} : { messages: i18n.messages },
|
|
1947
|
+
...i18n.translator === void 0 ? {} : { translator: i18n.translator },
|
|
1948
|
+
children: content
|
|
1949
|
+
}
|
|
1950
|
+
);
|
|
1923
1951
|
}
|
|
1924
1952
|
|
|
1925
1953
|
// src/workspace/TranslationWorkspace.tsx
|
|
1926
|
-
import {
|
|
1954
|
+
import {
|
|
1955
|
+
useFormEngineI18n,
|
|
1956
|
+
useTranslationWorkspace
|
|
1957
|
+
} from "@form-engine-ts/react";
|
|
1927
1958
|
import {
|
|
1928
1959
|
Button as Button3,
|
|
1929
1960
|
Card as Card2,
|
|
@@ -1938,28 +1969,31 @@ import {
|
|
|
1938
1969
|
} from "@mui/material";
|
|
1939
1970
|
import { useState as useState2 } from "react";
|
|
1940
1971
|
import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1941
|
-
var
|
|
1942
|
-
missing: "
|
|
1943
|
-
translated: "
|
|
1944
|
-
stale: "
|
|
1945
|
-
manual: "
|
|
1946
|
-
"manual-stale": "
|
|
1972
|
+
var statusKey = {
|
|
1973
|
+
missing: "workspace.status.missing",
|
|
1974
|
+
translated: "workspace.status.translated",
|
|
1975
|
+
stale: "workspace.status.stale",
|
|
1976
|
+
manual: "workspace.status.manual",
|
|
1977
|
+
"manual-stale": "workspace.status.manualStale"
|
|
1947
1978
|
};
|
|
1948
1979
|
function SlotCard({
|
|
1949
1980
|
slot,
|
|
1950
1981
|
readOnly,
|
|
1951
1982
|
onChange,
|
|
1952
|
-
onTranslate
|
|
1983
|
+
onTranslate,
|
|
1984
|
+
translate,
|
|
1985
|
+
renderStatusBadge
|
|
1953
1986
|
}) {
|
|
1987
|
+
const status = slot.status ?? "missing";
|
|
1954
1988
|
return /* @__PURE__ */ jsx18(Card2, { variant: "outlined", children: /* @__PURE__ */ jsx18(CardContent, { children: /* @__PURE__ */ jsxs11(Stack6, { spacing: 1.5, children: [
|
|
1955
1989
|
/* @__PURE__ */ jsxs11(Stack6, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [
|
|
1956
1990
|
/* @__PURE__ */ jsx18(Typography5, { variant: "subtitle2", children: slot.path }),
|
|
1957
|
-
/* @__PURE__ */ jsx18(Chip2, { size: "small", label:
|
|
1991
|
+
renderStatusBadge?.({ status }) ?? /* @__PURE__ */ jsx18(Chip2, { size: "small", label: translate(statusKey[status]) })
|
|
1958
1992
|
] }),
|
|
1959
1993
|
/* @__PURE__ */ jsx18(
|
|
1960
1994
|
TextField4,
|
|
1961
1995
|
{
|
|
1962
|
-
label: "
|
|
1996
|
+
label: translate("workspace.slot.sourceText"),
|
|
1963
1997
|
value: slot.sourceText,
|
|
1964
1998
|
multiline: true,
|
|
1965
1999
|
fullWidth: true,
|
|
@@ -1969,7 +2003,7 @@ function SlotCard({
|
|
|
1969
2003
|
/* @__PURE__ */ jsx18(
|
|
1970
2004
|
TextField4,
|
|
1971
2005
|
{
|
|
1972
|
-
label: "
|
|
2006
|
+
label: translate("workspace.slot.translatedText"),
|
|
1973
2007
|
value: slot.existingText ?? "",
|
|
1974
2008
|
multiline: true,
|
|
1975
2009
|
fullWidth: true,
|
|
@@ -1977,28 +2011,28 @@ function SlotCard({
|
|
|
1977
2011
|
onChange: (event) => onChange(event.target.value)
|
|
1978
2012
|
}
|
|
1979
2013
|
),
|
|
1980
|
-
slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ jsx18(Typography5, { color: "warning.main", variant: "body2", children: "
|
|
1981
|
-
/* @__PURE__ */ jsx18(Button3, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: "
|
|
2014
|
+
slot.status === "stale" || slot.status === "manual-stale" ? /* @__PURE__ */ jsx18(Typography5, { color: "warning.main", variant: "body2", children: translate("workspace.status.stale") }) : null,
|
|
2015
|
+
/* @__PURE__ */ jsx18(Button3, { variant: "outlined", onClick: onTranslate, disabled: readOnly, children: translate("workspace.slot.translateSingle") })
|
|
1982
2016
|
] }) }) });
|
|
1983
2017
|
}
|
|
1984
|
-
function workspaceErrorMessage(error) {
|
|
2018
|
+
function workspaceErrorMessage(error, translate) {
|
|
1985
2019
|
switch (error.type) {
|
|
1986
2020
|
case "locale_not_allowed":
|
|
1987
|
-
return
|
|
2021
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1988
2022
|
case "locale_already_exists":
|
|
1989
|
-
return
|
|
2023
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1990
2024
|
case "invalid_locale_format":
|
|
1991
|
-
return
|
|
2025
|
+
return translate("workspace.errors.localeNotAllowed", { locale: error.locale });
|
|
1992
2026
|
case "max_locales_exceeded":
|
|
1993
|
-
return
|
|
2027
|
+
return translate("workspace.errors.maxLocalesExceeded", { max: error.max });
|
|
1994
2028
|
case "read_only_mode":
|
|
1995
|
-
return "
|
|
2029
|
+
return translate("workspace.errors.readOnly");
|
|
1996
2030
|
case "adapter_not_configured":
|
|
1997
|
-
return "
|
|
2031
|
+
return translate("workspace.errors.adapterNotConfigured");
|
|
1998
2032
|
case "target_locale_missing":
|
|
1999
|
-
return "
|
|
2033
|
+
return translate("workspace.empty.noTargetLocales");
|
|
2000
2034
|
case "translation_failed":
|
|
2001
|
-
return
|
|
2035
|
+
return translate("workspace.errors.translationFailed");
|
|
2002
2036
|
case "custom_validation_failed":
|
|
2003
2037
|
return error.message;
|
|
2004
2038
|
}
|
|
@@ -2009,81 +2043,123 @@ function TranslationWorkspace({
|
|
|
2009
2043
|
sourceLocale,
|
|
2010
2044
|
targetLocale,
|
|
2011
2045
|
translationAdapter,
|
|
2012
|
-
readOnly = false
|
|
2046
|
+
readOnly = false,
|
|
2047
|
+
availableLocales,
|
|
2048
|
+
onLocaleAdded,
|
|
2049
|
+
onLocaleRemoved,
|
|
2050
|
+
onLocaleChange,
|
|
2051
|
+
beforeRemoveLocale,
|
|
2052
|
+
slots: workspaceSlots
|
|
2013
2053
|
}) {
|
|
2054
|
+
const { translator } = useFormEngineI18n();
|
|
2055
|
+
const translate = (key, params = {}) => translator(key, params);
|
|
2014
2056
|
const workspace = useTranslationWorkspace({
|
|
2015
2057
|
schema,
|
|
2016
2058
|
...onChange === void 0 ? {} : { onChange },
|
|
2017
2059
|
...sourceLocale === void 0 ? {} : { sourceLocale },
|
|
2018
2060
|
...targetLocale === void 0 ? {} : { targetLocale },
|
|
2019
2061
|
...translationAdapter === void 0 ? {} : { translationAdapter },
|
|
2020
|
-
readOnly
|
|
2062
|
+
readOnly,
|
|
2063
|
+
...availableLocales === void 0 ? {} : { availableLocales },
|
|
2064
|
+
...onLocaleAdded === void 0 ? {} : { onLocaleAdded },
|
|
2065
|
+
...onLocaleRemoved === void 0 ? {} : { onLocaleRemoved },
|
|
2066
|
+
...onLocaleChange === void 0 ? {} : { onLocaleChange },
|
|
2067
|
+
...beforeRemoveLocale === void 0 ? {} : { beforeRemoveLocale }
|
|
2021
2068
|
});
|
|
2022
2069
|
const [newLocale, setNewLocale] = useState2("");
|
|
2070
|
+
const headerProps = {
|
|
2071
|
+
schema,
|
|
2072
|
+
sourceLocale: workspace.sourceLocale,
|
|
2073
|
+
targetLocale: workspace.targetLocale,
|
|
2074
|
+
summary: workspace.summary,
|
|
2075
|
+
onTranslateAll: () => void workspace.translateAll(),
|
|
2076
|
+
isTranslating: workspace.isTranslating,
|
|
2077
|
+
readOnly
|
|
2078
|
+
};
|
|
2079
|
+
const actionsProps = {
|
|
2080
|
+
onTranslateAll: headerProps.onTranslateAll,
|
|
2081
|
+
isTranslating: workspace.isTranslating,
|
|
2082
|
+
readOnly
|
|
2083
|
+
};
|
|
2084
|
+
const localeSelectorProps = {
|
|
2085
|
+
targetLocale: workspace.targetLocale,
|
|
2086
|
+
targetLocales: workspace.targetLocales,
|
|
2087
|
+
localeOptions: workspace.localeOptions,
|
|
2088
|
+
newLocale,
|
|
2089
|
+
readOnly,
|
|
2090
|
+
onTargetLocaleChange: workspace.setTargetLocale,
|
|
2091
|
+
onNewLocaleChange: setNewLocale,
|
|
2092
|
+
onAddLocale: () => {
|
|
2093
|
+
const result = workspace.addLocale(newLocale);
|
|
2094
|
+
if (result.success) setNewLocale("");
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2023
2097
|
return /* @__PURE__ */ jsxs11(Stack6, { spacing: 2, "data-testid": "translation-workspace", children: [
|
|
2024
|
-
/* @__PURE__ */ jsxs11(Stack6, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
|
|
2025
|
-
/* @__PURE__ */ jsx18(Typography5, { variant: "h6", children: "
|
|
2026
|
-
/* @__PURE__ */
|
|
2027
|
-
workspace.summary.
|
|
2028
|
-
|
|
2029
|
-
workspace.summary.
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
")"
|
|
2033
|
-
] }),
|
|
2034
|
-
/* @__PURE__ */ jsx18(
|
|
2098
|
+
workspaceSlots?.renderHeader?.(headerProps) ?? /* @__PURE__ */ jsxs11(Stack6, { direction: { xs: "column", sm: "row" }, spacing: 2, alignItems: { sm: "center" }, children: [
|
|
2099
|
+
/* @__PURE__ */ jsx18(Typography5, { variant: "h6", children: translate("workspace.header.title") }),
|
|
2100
|
+
/* @__PURE__ */ jsx18(Typography5, { variant: "body2", children: translate("workspace.header.progress", {
|
|
2101
|
+
translated: workspace.summary.translatedCount,
|
|
2102
|
+
total: workspace.summary.totalSlots,
|
|
2103
|
+
percent: workspace.summary.completionPercentage
|
|
2104
|
+
}) }),
|
|
2105
|
+
workspaceSlots?.renderActions?.(actionsProps) ?? /* @__PURE__ */ jsx18(
|
|
2035
2106
|
Button3,
|
|
2036
2107
|
{
|
|
2037
2108
|
variant: "contained",
|
|
2038
|
-
onClick:
|
|
2109
|
+
onClick: headerProps.onTranslateAll,
|
|
2039
2110
|
disabled: readOnly || workspace.isTranslating,
|
|
2040
|
-
children: "
|
|
2111
|
+
children: translate("workspace.header.translateAll")
|
|
2041
2112
|
}
|
|
2042
2113
|
)
|
|
2043
2114
|
] }),
|
|
2044
2115
|
/* @__PURE__ */ jsx18(LinearProgress, { variant: "determinate", value: workspace.summary.completionPercentage }),
|
|
2045
|
-
/* @__PURE__ */ jsxs11(Stack6, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2116
|
+
workspaceSlots?.renderLocaleSelector?.(localeSelectorProps) ?? /* @__PURE__ */ jsxs11(Stack6, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2117
|
+
/* @__PURE__ */ jsxs11(Typography5, { variant: "body2", children: [
|
|
2118
|
+
translate("workspace.header.sourceLocale"),
|
|
2119
|
+
": ",
|
|
2120
|
+
workspace.sourceLocale
|
|
2121
|
+
] }),
|
|
2122
|
+
/* @__PURE__ */ jsxs11(Typography5, { variant: "body2", children: [
|
|
2123
|
+
translate("workspace.header.targetLocale"),
|
|
2124
|
+
":"
|
|
2125
|
+
] }),
|
|
2046
2126
|
/* @__PURE__ */ jsx18(
|
|
2047
2127
|
Tabs2,
|
|
2048
2128
|
{
|
|
2049
2129
|
value: workspace.targetLocale,
|
|
2050
2130
|
onChange: (_event, value) => workspace.setTargetLocale(value),
|
|
2051
|
-
"aria-label": "
|
|
2052
|
-
children: workspace.targetLocales.map((locale) => /* @__PURE__ */ jsx18(
|
|
2131
|
+
"aria-label": translate("workspace.header.targetLocale"),
|
|
2132
|
+
children: workspace.targetLocales.map((locale) => /* @__PURE__ */ jsx18(
|
|
2133
|
+
Tab2,
|
|
2134
|
+
{
|
|
2135
|
+
value: locale,
|
|
2136
|
+
label: workspace.localeOptions.find((option) => option.locale === locale)?.label ?? locale
|
|
2137
|
+
},
|
|
2138
|
+
locale
|
|
2139
|
+
))
|
|
2053
2140
|
}
|
|
2054
2141
|
),
|
|
2055
2142
|
/* @__PURE__ */ jsx18(
|
|
2056
2143
|
TextField4,
|
|
2057
2144
|
{
|
|
2058
2145
|
size: "small",
|
|
2059
|
-
label: "
|
|
2146
|
+
label: translate("workspace.header.targetLocale"),
|
|
2060
2147
|
value: newLocale,
|
|
2061
2148
|
onChange: (event) => setNewLocale(event.target.value)
|
|
2062
2149
|
}
|
|
2063
2150
|
),
|
|
2064
|
-
/* @__PURE__ */ jsx18(
|
|
2065
|
-
Button3,
|
|
2066
|
-
{
|
|
2067
|
-
onClick: () => {
|
|
2068
|
-
workspace.addLocale(newLocale);
|
|
2069
|
-
setNewLocale("");
|
|
2070
|
-
},
|
|
2071
|
-
disabled: readOnly,
|
|
2072
|
-
children: "Add"
|
|
2073
|
-
}
|
|
2074
|
-
)
|
|
2151
|
+
/* @__PURE__ */ jsx18(Button3, { onClick: localeSelectorProps.onAddLocale, disabled: readOnly, children: translate("builder.addLocale") })
|
|
2075
2152
|
] }),
|
|
2076
|
-
workspace.error === void 0 ? null : /* @__PURE__ */ jsx18(Typography5, { color: "error", children: workspaceErrorMessage(workspace.error) }),
|
|
2077
|
-
/* @__PURE__ */ jsx18(Stack6, { spacing: 1.5, children: workspace.slots.
|
|
2078
|
-
|
|
2079
|
-
{
|
|
2153
|
+
workspace.error === void 0 ? null : /* @__PURE__ */ jsx18(Typography5, { color: "error", children: workspaceErrorMessage(workspace.error, translate) }),
|
|
2154
|
+
/* @__PURE__ */ jsx18(Stack6, { spacing: 1.5, children: workspace.slots.length === 0 ? /* @__PURE__ */ jsx18(Typography5, { color: "text.secondary", children: workspace.targetLocales.length === 0 ? translate("workspace.empty.noTargetLocales") : translate("workspace.empty.noSlotsToTranslate") }) : workspace.slots.map((slot) => {
|
|
2155
|
+
const rowProps = {
|
|
2080
2156
|
slot,
|
|
2081
2157
|
readOnly,
|
|
2082
2158
|
onChange: (text) => workspace.setTranslation(slot, text),
|
|
2083
2159
|
onTranslate: () => void workspace.translateSlot(slot)
|
|
2084
|
-
}
|
|
2085
|
-
slot.path
|
|
2086
|
-
)
|
|
2160
|
+
};
|
|
2161
|
+
return /* @__PURE__ */ jsx18("span", { children: workspaceSlots?.renderSlotRow?.(rowProps) ?? /* @__PURE__ */ jsx18(SlotCard, { ...rowProps, translate, renderStatusBadge: workspaceSlots?.renderStatusBadge }) }, slot.path);
|
|
2162
|
+
}) })
|
|
2087
2163
|
] });
|
|
2088
2164
|
}
|
|
2089
2165
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/mui",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@mui/material": "^6.0.0 || ^7.0.0",
|
|
47
47
|
"react": "^18.0.0 || ^19.0.0",
|
|
48
48
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
49
|
-
"@form-engine-ts/core": "5.0
|
|
50
|
-
"@form-engine-ts/react": "5.0
|
|
49
|
+
"@form-engine-ts/core": "5.1.0",
|
|
50
|
+
"@form-engine-ts/react": "5.1.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@emotion/react": "^11.14.0",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
"@types/react-dom": "^19.2.4",
|
|
59
59
|
"react": "^19.2.8",
|
|
60
60
|
"react-dom": "^19.2.8",
|
|
61
|
-
"@form-engine-ts/core": "5.0
|
|
62
|
-
"@form-engine-ts/react": "5.0
|
|
61
|
+
"@form-engine-ts/core": "5.1.0",
|
|
62
|
+
"@form-engine-ts/react": "5.1.0"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external @emotion/react --external @emotion/styled --external @form-engine-ts/core --external @form-engine-ts/react --external @mui/icons-material --external @mui/material --external react --external react-dom",
|