@interware/content-generator 0.7.1 → 0.7.2
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/_chunks/{App-h4_txTsI.mjs → App-CTh6owSM.mjs} +2 -2
- package/dist/_chunks/{App-Cwr5ra5m.js → App-ugsCmlsC.js} +2 -2
- package/dist/_chunks/{ImageStudioTabs-CG4KTn1S.js → ImageStudioTabs-BFEF9ggK.js} +60 -46
- package/dist/_chunks/{ImageStudioTabs-B-mOwDfY.mjs → ImageStudioTabs-Umf3GODW.mjs} +60 -46
- package/dist/_chunks/{Settings-BT-EqvXs.mjs → Settings-CdGW2O8h.mjs} +1 -1
- package/dist/_chunks/{Settings-D4NGBTk1.js → Settings-Sk78JUBS.js} +1 -1
- package/dist/_chunks/{StudioApp-xaEy-uIk.mjs → StudioApp-CrGn-9Gg.mjs} +2 -2
- package/dist/_chunks/{StudioApp-_ViSAwCm.js → StudioApp-DoC0z4eh.js} +2 -2
- package/dist/_chunks/{index-NA9OuMGs.js → index-C2s9Jhcc.js} +3 -3
- package/dist/_chunks/{index-D67xWUPz.mjs → index-D6UAvh53.mjs} +3 -3
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/features/templates/editor/ColorField.d.ts +4 -2
- package/dist/admin/src/features/templates/model/palette.d.ts +2 -2
- package/dist/admin/src/lib/imageLimits.d.ts +9 -0
- package/dist/server/index.js +3 -2
- package/dist/server/index.mjs +3 -2
- package/package.json +1 -1
|
@@ -5,8 +5,8 @@ import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
|
|
|
5
5
|
import { useMemo, useState, useEffect, useRef, useCallback } from "react";
|
|
6
6
|
import { Box, Flex, Typography, Button, Badge, TextInput, Loader, Table, Thead, Tr, Th, VisuallyHidden, Tbody, Td, TextButton, IconButton, Link, LinkButton, Field, Radio, Modal, Textarea, Combobox, ComboboxOption, Toggle, Grid } from "@strapi/design-system";
|
|
7
7
|
import { Plus, Search, Check, Pencil, ExternalLink, ArrowLeft, Image, Clock, WarningCircle, Trash, Sparkle, PlusCircle } from "@strapi/icons";
|
|
8
|
-
import { P as PLUGIN_ID, S as STUDIO_PATH, p as pluginPermissions } from "./index-
|
|
9
|
-
import { L as LibraryImagePicker, P as PromptComposer, a as LEGACY_ROUTES, S as StudioRedirect, l as legacyRedirect } from "./ImageStudioTabs-
|
|
8
|
+
import { P as PLUGIN_ID, S as STUDIO_PATH, p as pluginPermissions } from "./index-D6UAvh53.mjs";
|
|
9
|
+
import { L as LibraryImagePicker, P as PromptComposer, a as LEGACY_ROUTES, S as StudioRedirect, l as legacyRedirect } from "./ImageStudioTabs-Umf3GODW.mjs";
|
|
10
10
|
import { useIntl } from "react-intl";
|
|
11
11
|
import { useFormik } from "formik";
|
|
12
12
|
import * as Yup from "yup";
|
|
@@ -7,8 +7,8 @@ const PluginProviders = require("./PluginProviders-D79TeGSE.js");
|
|
|
7
7
|
const react = require("react");
|
|
8
8
|
const designSystem = require("@strapi/design-system");
|
|
9
9
|
const icons = require("@strapi/icons");
|
|
10
|
-
const index = require("./index-
|
|
11
|
-
const ImageStudioTabs = require("./ImageStudioTabs-
|
|
10
|
+
const index = require("./index-C2s9Jhcc.js");
|
|
11
|
+
const ImageStudioTabs = require("./ImageStudioTabs-BFEF9ggK.js");
|
|
12
12
|
const reactIntl = require("react-intl");
|
|
13
13
|
const formik = require("formik");
|
|
14
14
|
const Yup = require("yup");
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
3
|
const designSystem = require("@strapi/design-system");
|
|
4
4
|
const reactRouterDom = require("react-router-dom");
|
|
5
|
-
const index = require("./index-
|
|
5
|
+
const index = require("./index-C2s9Jhcc.js");
|
|
6
6
|
const react = require("react");
|
|
7
7
|
const icons = require("@strapi/icons");
|
|
8
8
|
const styledComponents = require("styled-components");
|
|
@@ -740,6 +740,9 @@ const RemoveBackgroundButton = ({ src, onDone }) => {
|
|
|
740
740
|
)
|
|
741
741
|
] });
|
|
742
742
|
};
|
|
743
|
+
const IMAGE_MAX_MB = 30;
|
|
744
|
+
const IMAGE_MAX_BYTES = IMAGE_MAX_MB * 1024 * 1024;
|
|
745
|
+
const IMAGE_FORMATS_HINT = `PNG, JPG o WEBP de hasta ${IMAGE_MAX_MB} MB.`;
|
|
743
746
|
const NameDialog = ({ open, title, label, initial = "", confirmLabel, validate, onClose, onConfirm }) => {
|
|
744
747
|
const [name, setName] = react.useState(initial);
|
|
745
748
|
const [error, setError] = react.useState(null);
|
|
@@ -1253,7 +1256,10 @@ const EditEmpty = ({ disabled, onUpload, onOpenLibrary, onOpenRecent }) => {
|
|
|
1253
1256
|
style: { width: "100%", maxWidth: 600, border: `2px dashed ${over ? c.primary600 : c.neutral200}` },
|
|
1254
1257
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 3, style: { textAlign: "center" }, children: [
|
|
1255
1258
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", tag: "h2", children: "Elige la imagen que quieres editar" }),
|
|
1256
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1259
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
|
|
1260
|
+
"Arrástrala aquí, súbela o elígela de la biblioteca. ",
|
|
1261
|
+
IMAGE_FORMATS_HINT
|
|
1262
|
+
] }),
|
|
1257
1263
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, paddingTop: 2, children: [
|
|
1258
1264
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Upload, {}), disabled, onClick: () => input.current?.click(), children: "Subir imagen" }),
|
|
1259
1265
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Folder, {}), disabled, onClick: onOpenLibrary, children: "Elegir de la biblioteca" })
|
|
@@ -1328,7 +1334,7 @@ const ReferencePicker = ({
|
|
|
1328
1334
|
onChange,
|
|
1329
1335
|
onPickFromLibrary,
|
|
1330
1336
|
label = "Imágenes de referencia",
|
|
1331
|
-
hint =
|
|
1337
|
+
hint = IMAGE_FORMATS_HINT,
|
|
1332
1338
|
noun = REFERENCES
|
|
1333
1339
|
}) => {
|
|
1334
1340
|
const input = react.useRef(null);
|
|
@@ -1522,8 +1528,8 @@ const GeneratorTab = () => {
|
|
|
1522
1528
|
};
|
|
1523
1529
|
const uploadBase = (file) => {
|
|
1524
1530
|
if (!file) return;
|
|
1525
|
-
if (!IMAGE_MIMES.includes(file.type) || file.size >
|
|
1526
|
-
notify("warning",
|
|
1531
|
+
if (!IMAGE_MIMES.includes(file.type) || file.size > IMAGE_MAX_BYTES) {
|
|
1532
|
+
notify("warning", `Usa una imagen ${IMAGE_FORMATS_HINT}`);
|
|
1527
1533
|
return;
|
|
1528
1534
|
}
|
|
1529
1535
|
const reader = new FileReader();
|
|
@@ -1598,7 +1604,7 @@ const GeneratorTab = () => {
|
|
|
1598
1604
|
ReferencePicker,
|
|
1599
1605
|
{
|
|
1600
1606
|
label: "Referencias de estilo",
|
|
1601
|
-
hint:
|
|
1607
|
+
hint: `Guían el estilo, no se copian. ${IMAGE_FORMATS_HINT}`,
|
|
1602
1608
|
files: references,
|
|
1603
1609
|
max: model?.maxReferences ?? 0,
|
|
1604
1610
|
modelLabel: model?.label ?? "Este modelo",
|
|
@@ -2187,17 +2193,6 @@ const LibraryTab = () => {
|
|
|
2187
2193
|
/* @__PURE__ */ jsxRuntime.jsx(RemoveBackgroundDialog, { open: !!bgTarget, src: bgTarget?.src ?? "", onClose: () => setBgTarget(null), onApply: saveNoBackground })
|
|
2188
2194
|
] });
|
|
2189
2195
|
};
|
|
2190
|
-
const PALETTE = [
|
|
2191
|
-
{ label: "Navy", value: "#1F2A44" },
|
|
2192
|
-
{ label: "Rojo", value: "#E4002B" },
|
|
2193
|
-
{ label: "Teal", value: "#00C7B1" },
|
|
2194
|
-
{ label: "Teal suave", value: "#92CFC7" },
|
|
2195
|
-
{ label: "Amarillo", value: "#FFC844" },
|
|
2196
|
-
{ label: "Amarillo suave", value: "#F8DF8D" },
|
|
2197
|
-
{ label: "Gris", value: "#5B6473" },
|
|
2198
|
-
{ label: "Papel", value: "#EEF1F5" },
|
|
2199
|
-
{ label: "Blanco", value: "#FFFFFF" }
|
|
2200
|
-
];
|
|
2201
2196
|
const NAVY = "#1F2A44";
|
|
2202
2197
|
const RED$1 = "#E4002B";
|
|
2203
2198
|
const TEAL$1 = "#00C7B1";
|
|
@@ -3937,44 +3932,63 @@ const SaveTemplateDialog = ({ open, defaultName, defaultFolder, folders, onClose
|
|
|
3937
3932
|
] })
|
|
3938
3933
|
] }) });
|
|
3939
3934
|
};
|
|
3935
|
+
const parseHex = (raw) => {
|
|
3936
|
+
const hex = raw.trim().replace(/^#/, "");
|
|
3937
|
+
if (/^[0-9a-f]{3}$/i.test(hex)) return `#${[...hex].map((c) => c + c).join("")}`.toUpperCase();
|
|
3938
|
+
if (/^[0-9a-f]{6}$/i.test(hex)) return `#${hex}`.toUpperCase();
|
|
3939
|
+
return null;
|
|
3940
|
+
};
|
|
3940
3941
|
const ColorField = ({ label, value, onChange }) => {
|
|
3941
3942
|
const tc = useThemeColors();
|
|
3943
|
+
const current = parseHex(value ?? "") ?? "#000000";
|
|
3944
|
+
const [draft, setDraft] = react.useState(current);
|
|
3945
|
+
react.useEffect(() => setDraft((d) => parseHex(d) === current ? d : current), [current]);
|
|
3946
|
+
const apply = (text) => {
|
|
3947
|
+
const hex = parseHex(text);
|
|
3948
|
+
if (hex && hex !== current) onChange(hex);
|
|
3949
|
+
};
|
|
3950
|
+
const typeHex = (text) => {
|
|
3951
|
+
setDraft(text);
|
|
3952
|
+
if (text.trim().replace(/^#/, "").length === 6) apply(text);
|
|
3953
|
+
};
|
|
3954
|
+
const leave = () => {
|
|
3955
|
+
apply(draft);
|
|
3956
|
+
setDraft(parseHex(draft) ?? current);
|
|
3957
|
+
};
|
|
3942
3958
|
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
|
|
3943
3959
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
|
|
3944
|
-
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap:
|
|
3945
|
-
PALETTE.map((c) => {
|
|
3946
|
-
const active = value?.toUpperCase() === c.value;
|
|
3947
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3948
|
-
designSystem.Box,
|
|
3949
|
-
{
|
|
3950
|
-
tag: "button",
|
|
3951
|
-
color: "neutral800",
|
|
3952
|
-
type: "button",
|
|
3953
|
-
"aria-label": `${label}: ${c.label}`,
|
|
3954
|
-
"aria-pressed": active,
|
|
3955
|
-
title: c.label,
|
|
3956
|
-
onClick: () => onChange(c.value),
|
|
3957
|
-
style: {
|
|
3958
|
-
width: 22,
|
|
3959
|
-
height: 22,
|
|
3960
|
-
borderRadius: 4,
|
|
3961
|
-
cursor: "pointer",
|
|
3962
|
-
background: c.value,
|
|
3963
|
-
border: active ? `2px solid ${tc.primary600}` : `1px solid ${tc.neutral200}`,
|
|
3964
|
-
padding: 0
|
|
3965
|
-
}
|
|
3966
|
-
},
|
|
3967
|
-
c.value
|
|
3968
|
-
);
|
|
3969
|
-
}),
|
|
3960
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
3970
3961
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3971
3962
|
"input",
|
|
3972
3963
|
{
|
|
3973
3964
|
type: "color",
|
|
3974
|
-
"aria-label": `${label}
|
|
3975
|
-
|
|
3965
|
+
"aria-label": `${label}: selector`,
|
|
3966
|
+
title: "Abrir selector de color",
|
|
3967
|
+
value: current.toLowerCase(),
|
|
3976
3968
|
onChange: (e) => onChange(e.target.value.toUpperCase()),
|
|
3977
|
-
style: {
|
|
3969
|
+
style: {
|
|
3970
|
+
flexShrink: 0,
|
|
3971
|
+
width: 32,
|
|
3972
|
+
height: 32,
|
|
3973
|
+
padding: 2,
|
|
3974
|
+
borderRadius: 4,
|
|
3975
|
+
cursor: "pointer",
|
|
3976
|
+
border: `1px solid ${tc.neutral200}`,
|
|
3977
|
+
background: tc.neutral0
|
|
3978
|
+
}
|
|
3979
|
+
}
|
|
3980
|
+
),
|
|
3981
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3982
|
+
designSystem.TextInput,
|
|
3983
|
+
{
|
|
3984
|
+
"aria-label": `${label}: hexadecimal`,
|
|
3985
|
+
size: "S",
|
|
3986
|
+
value: draft,
|
|
3987
|
+
placeholder: "#1F2A44",
|
|
3988
|
+
maxLength: 7,
|
|
3989
|
+
spellCheck: false,
|
|
3990
|
+
onChange: (e) => typeHex(e.target.value),
|
|
3991
|
+
onBlur: leave
|
|
3978
3992
|
}
|
|
3979
3993
|
)
|
|
3980
3994
|
] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Modal, Flex, Button, Loader, Typography, Grid, Box, lightTheme, Checkbox, Field, TextInput, Dialog, SingleSelect, SingleSelectOption, Link, Badge, IconButtonGroup, IconButton, Toggle, Menu, NumberInput, Divider, Textarea, Tabs } from "@strapi/design-system";
|
|
3
3
|
import { useLocation, Navigate, useSearchParams } from "react-router-dom";
|
|
4
|
-
import { S as STUDIO_PATH } from "./index-
|
|
4
|
+
import { S as STUDIO_PATH } from "./index-D6UAvh53.mjs";
|
|
5
5
|
import { useMemo, useState, useEffect, useId, useRef, useReducer, useCallback, useSyncExternalStore, useLayoutEffect, memo, forwardRef } from "react";
|
|
6
6
|
import { ChevronRight, Folder, Magic, Pencil, Upload, Sparkle, Plus, Cross, Download, ArrowClockwise, House, ChevronDown, FilePdf, File as File$1, More, Trash, User, Star, SquaresFour, Quotes, PriceTag, Paragraph, NumberList, Minus, Italic, Image as Image$1, HeadingTwo, HeadingOne, Hashtag, Feather, Drag, BulletList, ArrowLeft, Check, ArrowsCounterClockwise, ArrowLineLeft, ArrowLineRight, Expand, WarningCircle, Play, Phone, Mail, PinMap, Earth, PresentationChart, ChartPie, ChartBubble, Cog, Database, Cloud, Globe, Server, Lightbulb, Crown, SealCheck, Briefcase, Rocket, Shield, CheckCircle, Lightning, Heart, Collapse, Bold, ArrowUp, ArrowDown, Duplicate, Lock, EyeStriked, Eye } from "@strapi/icons";
|
|
7
7
|
import { useTheme } from "styled-components";
|
|
@@ -737,6 +737,9 @@ const RemoveBackgroundButton = ({ src, onDone }) => {
|
|
|
737
737
|
)
|
|
738
738
|
] });
|
|
739
739
|
};
|
|
740
|
+
const IMAGE_MAX_MB = 30;
|
|
741
|
+
const IMAGE_MAX_BYTES = IMAGE_MAX_MB * 1024 * 1024;
|
|
742
|
+
const IMAGE_FORMATS_HINT = `PNG, JPG o WEBP de hasta ${IMAGE_MAX_MB} MB.`;
|
|
740
743
|
const NameDialog = ({ open, title, label, initial = "", confirmLabel, validate, onClose, onConfirm }) => {
|
|
741
744
|
const [name, setName] = useState(initial);
|
|
742
745
|
const [error, setError] = useState(null);
|
|
@@ -1250,7 +1253,10 @@ const EditEmpty = ({ disabled, onUpload, onOpenLibrary, onOpenRecent }) => {
|
|
|
1250
1253
|
style: { width: "100%", maxWidth: 600, border: `2px dashed ${over ? c.primary600 : c.neutral200}` },
|
|
1251
1254
|
children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "center", gap: 3, style: { textAlign: "center" }, children: [
|
|
1252
1255
|
/* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: "Elige la imagen que quieres editar" }),
|
|
1253
|
-
/* @__PURE__ */
|
|
1256
|
+
/* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
|
|
1257
|
+
"Arrástrala aquí, súbela o elígela de la biblioteca. ",
|
|
1258
|
+
IMAGE_FORMATS_HINT
|
|
1259
|
+
] }),
|
|
1254
1260
|
/* @__PURE__ */ jsxs(Flex, { gap: 3, paddingTop: 2, children: [
|
|
1255
1261
|
/* @__PURE__ */ jsx(Button, { variant: "tertiary", startIcon: /* @__PURE__ */ jsx(Upload, {}), disabled, onClick: () => input.current?.click(), children: "Subir imagen" }),
|
|
1256
1262
|
/* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Folder, {}), disabled, onClick: onOpenLibrary, children: "Elegir de la biblioteca" })
|
|
@@ -1325,7 +1331,7 @@ const ReferencePicker = ({
|
|
|
1325
1331
|
onChange,
|
|
1326
1332
|
onPickFromLibrary,
|
|
1327
1333
|
label = "Imágenes de referencia",
|
|
1328
|
-
hint =
|
|
1334
|
+
hint = IMAGE_FORMATS_HINT,
|
|
1329
1335
|
noun = REFERENCES
|
|
1330
1336
|
}) => {
|
|
1331
1337
|
const input = useRef(null);
|
|
@@ -1519,8 +1525,8 @@ const GeneratorTab = () => {
|
|
|
1519
1525
|
};
|
|
1520
1526
|
const uploadBase = (file) => {
|
|
1521
1527
|
if (!file) return;
|
|
1522
|
-
if (!IMAGE_MIMES.includes(file.type) || file.size >
|
|
1523
|
-
notify("warning",
|
|
1528
|
+
if (!IMAGE_MIMES.includes(file.type) || file.size > IMAGE_MAX_BYTES) {
|
|
1529
|
+
notify("warning", `Usa una imagen ${IMAGE_FORMATS_HINT}`);
|
|
1524
1530
|
return;
|
|
1525
1531
|
}
|
|
1526
1532
|
const reader = new FileReader();
|
|
@@ -1595,7 +1601,7 @@ const GeneratorTab = () => {
|
|
|
1595
1601
|
ReferencePicker,
|
|
1596
1602
|
{
|
|
1597
1603
|
label: "Referencias de estilo",
|
|
1598
|
-
hint:
|
|
1604
|
+
hint: `Guían el estilo, no se copian. ${IMAGE_FORMATS_HINT}`,
|
|
1599
1605
|
files: references,
|
|
1600
1606
|
max: model?.maxReferences ?? 0,
|
|
1601
1607
|
modelLabel: model?.label ?? "Este modelo",
|
|
@@ -2184,17 +2190,6 @@ const LibraryTab = () => {
|
|
|
2184
2190
|
/* @__PURE__ */ jsx(RemoveBackgroundDialog, { open: !!bgTarget, src: bgTarget?.src ?? "", onClose: () => setBgTarget(null), onApply: saveNoBackground })
|
|
2185
2191
|
] });
|
|
2186
2192
|
};
|
|
2187
|
-
const PALETTE = [
|
|
2188
|
-
{ label: "Navy", value: "#1F2A44" },
|
|
2189
|
-
{ label: "Rojo", value: "#E4002B" },
|
|
2190
|
-
{ label: "Teal", value: "#00C7B1" },
|
|
2191
|
-
{ label: "Teal suave", value: "#92CFC7" },
|
|
2192
|
-
{ label: "Amarillo", value: "#FFC844" },
|
|
2193
|
-
{ label: "Amarillo suave", value: "#F8DF8D" },
|
|
2194
|
-
{ label: "Gris", value: "#5B6473" },
|
|
2195
|
-
{ label: "Papel", value: "#EEF1F5" },
|
|
2196
|
-
{ label: "Blanco", value: "#FFFFFF" }
|
|
2197
|
-
];
|
|
2198
2193
|
const NAVY = "#1F2A44";
|
|
2199
2194
|
const RED$1 = "#E4002B";
|
|
2200
2195
|
const TEAL$1 = "#00C7B1";
|
|
@@ -3934,44 +3929,63 @@ const SaveTemplateDialog = ({ open, defaultName, defaultFolder, folders, onClose
|
|
|
3934
3929
|
] })
|
|
3935
3930
|
] }) });
|
|
3936
3931
|
};
|
|
3932
|
+
const parseHex = (raw) => {
|
|
3933
|
+
const hex = raw.trim().replace(/^#/, "");
|
|
3934
|
+
if (/^[0-9a-f]{3}$/i.test(hex)) return `#${[...hex].map((c) => c + c).join("")}`.toUpperCase();
|
|
3935
|
+
if (/^[0-9a-f]{6}$/i.test(hex)) return `#${hex}`.toUpperCase();
|
|
3936
|
+
return null;
|
|
3937
|
+
};
|
|
3937
3938
|
const ColorField = ({ label, value, onChange }) => {
|
|
3938
3939
|
const tc = useThemeColors();
|
|
3940
|
+
const current = parseHex(value ?? "") ?? "#000000";
|
|
3941
|
+
const [draft, setDraft] = useState(current);
|
|
3942
|
+
useEffect(() => setDraft((d) => parseHex(d) === current ? d : current), [current]);
|
|
3943
|
+
const apply = (text) => {
|
|
3944
|
+
const hex = parseHex(text);
|
|
3945
|
+
if (hex && hex !== current) onChange(hex);
|
|
3946
|
+
};
|
|
3947
|
+
const typeHex = (text) => {
|
|
3948
|
+
setDraft(text);
|
|
3949
|
+
if (text.trim().replace(/^#/, "").length === 6) apply(text);
|
|
3950
|
+
};
|
|
3951
|
+
const leave = () => {
|
|
3952
|
+
apply(draft);
|
|
3953
|
+
setDraft(parseHex(draft) ?? current);
|
|
3954
|
+
};
|
|
3939
3955
|
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
|
|
3940
3956
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", textColor: "neutral800", children: label }),
|
|
3941
|
-
/* @__PURE__ */ jsxs(Flex, { gap:
|
|
3942
|
-
PALETTE.map((c) => {
|
|
3943
|
-
const active = value?.toUpperCase() === c.value;
|
|
3944
|
-
return /* @__PURE__ */ jsx(
|
|
3945
|
-
Box,
|
|
3946
|
-
{
|
|
3947
|
-
tag: "button",
|
|
3948
|
-
color: "neutral800",
|
|
3949
|
-
type: "button",
|
|
3950
|
-
"aria-label": `${label}: ${c.label}`,
|
|
3951
|
-
"aria-pressed": active,
|
|
3952
|
-
title: c.label,
|
|
3953
|
-
onClick: () => onChange(c.value),
|
|
3954
|
-
style: {
|
|
3955
|
-
width: 22,
|
|
3956
|
-
height: 22,
|
|
3957
|
-
borderRadius: 4,
|
|
3958
|
-
cursor: "pointer",
|
|
3959
|
-
background: c.value,
|
|
3960
|
-
border: active ? `2px solid ${tc.primary600}` : `1px solid ${tc.neutral200}`,
|
|
3961
|
-
padding: 0
|
|
3962
|
-
}
|
|
3963
|
-
},
|
|
3964
|
-
c.value
|
|
3965
|
-
);
|
|
3966
|
-
}),
|
|
3957
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
3967
3958
|
/* @__PURE__ */ jsx(
|
|
3968
3959
|
"input",
|
|
3969
3960
|
{
|
|
3970
3961
|
type: "color",
|
|
3971
|
-
"aria-label": `${label}
|
|
3972
|
-
|
|
3962
|
+
"aria-label": `${label}: selector`,
|
|
3963
|
+
title: "Abrir selector de color",
|
|
3964
|
+
value: current.toLowerCase(),
|
|
3973
3965
|
onChange: (e) => onChange(e.target.value.toUpperCase()),
|
|
3974
|
-
style: {
|
|
3966
|
+
style: {
|
|
3967
|
+
flexShrink: 0,
|
|
3968
|
+
width: 32,
|
|
3969
|
+
height: 32,
|
|
3970
|
+
padding: 2,
|
|
3971
|
+
borderRadius: 4,
|
|
3972
|
+
cursor: "pointer",
|
|
3973
|
+
border: `1px solid ${tc.neutral200}`,
|
|
3974
|
+
background: tc.neutral0
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
),
|
|
3978
|
+
/* @__PURE__ */ jsx(
|
|
3979
|
+
TextInput,
|
|
3980
|
+
{
|
|
3981
|
+
"aria-label": `${label}: hexadecimal`,
|
|
3982
|
+
size: "S",
|
|
3983
|
+
value: draft,
|
|
3984
|
+
placeholder: "#1F2A44",
|
|
3985
|
+
maxLength: 7,
|
|
3986
|
+
spellCheck: false,
|
|
3987
|
+
onChange: (e) => typeHex(e.target.value),
|
|
3988
|
+
onBlur: leave
|
|
3975
3989
|
}
|
|
3976
3990
|
)
|
|
3977
3991
|
] })
|
|
@@ -5,7 +5,7 @@ import { useCallback, useState, useEffect } from "react";
|
|
|
5
5
|
import { Box, Grid, Field, Flex, Button, Typography, Textarea } from "@strapi/design-system";
|
|
6
6
|
import { Formik } from "formik";
|
|
7
7
|
import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
|
|
8
|
-
import { P as PLUGIN_ID } from "./index-
|
|
8
|
+
import { P as PLUGIN_ID } from "./index-D6UAvh53.mjs";
|
|
9
9
|
const useSettings = () => {
|
|
10
10
|
const { get, post, del } = useFetchClient();
|
|
11
11
|
const getSettings = useCallback(
|
|
@@ -7,7 +7,7 @@ const react = require("react");
|
|
|
7
7
|
const designSystem = require("@strapi/design-system");
|
|
8
8
|
const formik = require("formik");
|
|
9
9
|
const PluginProviders = require("./PluginProviders-D79TeGSE.js");
|
|
10
|
-
const index = require("./index-
|
|
10
|
+
const index = require("./index-C2s9Jhcc.js");
|
|
11
11
|
const useSettings = () => {
|
|
12
12
|
const { get, post, del } = admin.useFetchClient();
|
|
13
13
|
const getSettings = react.useCallback(
|
|
@@ -2,9 +2,9 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Page } from "@strapi/strapi/admin";
|
|
3
3
|
import { Routes, Route } from "react-router-dom";
|
|
4
4
|
import { P as PluginProviders } from "./PluginProviders-DWMpcAIh.mjs";
|
|
5
|
-
import { p as pluginPermissions } from "./index-
|
|
5
|
+
import { p as pluginPermissions } from "./index-D6UAvh53.mjs";
|
|
6
6
|
import { Box } from "@strapi/design-system";
|
|
7
|
-
import { I as ImageStudioTabs } from "./ImageStudioTabs-
|
|
7
|
+
import { I as ImageStudioTabs } from "./ImageStudioTabs-Umf3GODW.mjs";
|
|
8
8
|
const ImageStudio = () => /* @__PURE__ */ jsxs(Page.Main, { children: [
|
|
9
9
|
/* @__PURE__ */ jsx(Page.Title, { children: "Estudio de imágenes" }),
|
|
10
10
|
/* @__PURE__ */ jsx(Box, { style: { height: "100vh" }, children: /* @__PURE__ */ jsx(ImageStudioTabs, {}) })
|
|
@@ -4,9 +4,9 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const admin = require("@strapi/strapi/admin");
|
|
5
5
|
const reactRouterDom = require("react-router-dom");
|
|
6
6
|
const PluginProviders = require("./PluginProviders-D79TeGSE.js");
|
|
7
|
-
const index = require("./index-
|
|
7
|
+
const index = require("./index-C2s9Jhcc.js");
|
|
8
8
|
const designSystem = require("@strapi/design-system");
|
|
9
|
-
const ImageStudioTabs = require("./ImageStudioTabs-
|
|
9
|
+
const ImageStudioTabs = require("./ImageStudioTabs-BFEF9ggK.js");
|
|
10
10
|
const ImageStudio = () => /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [
|
|
11
11
|
/* @__PURE__ */ jsxRuntime.jsx(admin.Page.Title, { children: "Estudio de imágenes" }),
|
|
12
12
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { height: "100vh" }, children: /* @__PURE__ */ jsxRuntime.jsx(ImageStudioTabs.ImageStudioTabs, {}) })
|
|
@@ -57,7 +57,7 @@ const index = {
|
|
|
57
57
|
defaultMessage: "Generador de contenido"
|
|
58
58
|
},
|
|
59
59
|
Component: async () => {
|
|
60
|
-
const { App } = await Promise.resolve().then(() => require("./App-
|
|
60
|
+
const { App } = await Promise.resolve().then(() => require("./App-ugsCmlsC.js"));
|
|
61
61
|
return App;
|
|
62
62
|
},
|
|
63
63
|
permissions: [
|
|
@@ -72,7 +72,7 @@ const index = {
|
|
|
72
72
|
defaultMessage: "Estudio de imágenes"
|
|
73
73
|
},
|
|
74
74
|
Component: async () => {
|
|
75
|
-
const { StudioApp } = await Promise.resolve().then(() => require("./StudioApp-
|
|
75
|
+
const { StudioApp } = await Promise.resolve().then(() => require("./StudioApp-DoC0z4eh.js"));
|
|
76
76
|
return StudioApp;
|
|
77
77
|
},
|
|
78
78
|
permissions: [
|
|
@@ -92,7 +92,7 @@ const index = {
|
|
|
92
92
|
defaultMessage: PLUGIN_ID
|
|
93
93
|
},
|
|
94
94
|
Component: async () => {
|
|
95
|
-
const component = await Promise.resolve().then(() => require("./Settings-
|
|
95
|
+
const component = await Promise.resolve().then(() => require("./Settings-Sk78JUBS.js"));
|
|
96
96
|
return component.default;
|
|
97
97
|
},
|
|
98
98
|
to: `plugins/${PLUGIN_ID}/settings`,
|
|
@@ -56,7 +56,7 @@ const index = {
|
|
|
56
56
|
defaultMessage: "Generador de contenido"
|
|
57
57
|
},
|
|
58
58
|
Component: async () => {
|
|
59
|
-
const { App } = await import("./App-
|
|
59
|
+
const { App } = await import("./App-CTh6owSM.mjs");
|
|
60
60
|
return App;
|
|
61
61
|
},
|
|
62
62
|
permissions: [
|
|
@@ -71,7 +71,7 @@ const index = {
|
|
|
71
71
|
defaultMessage: "Estudio de imágenes"
|
|
72
72
|
},
|
|
73
73
|
Component: async () => {
|
|
74
|
-
const { StudioApp } = await import("./StudioApp-
|
|
74
|
+
const { StudioApp } = await import("./StudioApp-CrGn-9Gg.mjs");
|
|
75
75
|
return StudioApp;
|
|
76
76
|
},
|
|
77
77
|
permissions: [
|
|
@@ -91,7 +91,7 @@ const index = {
|
|
|
91
91
|
defaultMessage: PLUGIN_ID
|
|
92
92
|
},
|
|
93
93
|
Component: async () => {
|
|
94
|
-
const component = await import("./Settings-
|
|
94
|
+
const component = await import("./Settings-CdGW2O8h.mjs");
|
|
95
95
|
return component.default;
|
|
96
96
|
},
|
|
97
97
|
to: `plugins/${PLUGIN_ID}/settings`,
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
|
@@ -3,9 +3,11 @@ interface ColorFieldProps {
|
|
|
3
3
|
value: string;
|
|
4
4
|
onChange: (value: string) => void;
|
|
5
5
|
}
|
|
6
|
+
/** «#0af», «0AF», «00aaff» o «#00AAFF» → «#00AAFF». Cualquier otra cosa → null. */
|
|
7
|
+
export declare const parseHex: (raw: string) => string | null;
|
|
6
8
|
/**
|
|
7
|
-
* Selector de color (snowflake: el DS no tiene uno).
|
|
8
|
-
*
|
|
9
|
+
* Selector de color (snowflake: el DS no tiene uno). La muestra abre el selector de color del
|
|
10
|
+
* navegador y el campo acepta un hexadecimal escrito o pegado; solo se aplica cuando es válido.
|
|
9
11
|
*/
|
|
10
12
|
export declare const ColorField: ({ label, value, onChange }: ColorFieldProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
13
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Paleta InterWare (paleta canónica del brochure). Es la única que
|
|
3
|
-
* editor
|
|
2
|
+
* Paleta InterWare (paleta canónica del brochure). Es la única que usan las plantillas base; en el
|
|
3
|
+
* editor el color es libre (selector o hexadecimal).
|
|
4
4
|
*/
|
|
5
5
|
export declare const PALETTE: readonly [{
|
|
6
6
|
readonly label: "Navy";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tope por imagen de referencia o a editar; lo comparten el panel y el servidor. Medido en Vertex
|
|
3
|
+
* (2026-10-07, `scripts/vertex-diag-size.mjs`): una imagen generada en 2K pesa ~8 MB y en 4K hasta
|
|
4
|
+
* ~24 MB, y Google aceptó editarla en línea pese a los 7 MB que dice su documentación. 30 MB deja
|
|
5
|
+
* iterar sobre una 4K con margen.
|
|
6
|
+
*/
|
|
7
|
+
export declare const IMAGE_MAX_MB = 30;
|
|
8
|
+
export declare const IMAGE_MAX_BYTES: number;
|
|
9
|
+
export declare const IMAGE_FORMATS_HINT = "PNG, JPG o WEBP de hasta 30 MB.";
|
package/dist/server/index.js
CHANGED
|
@@ -428,10 +428,11 @@ const imageStudio$1 = ({ strapi }) => createImageStudio(async () => {
|
|
|
428
428
|
const { ai, backend } = await strapi.plugin("strapi-content-generator-gemini").service("service").geminiClient();
|
|
429
429
|
return { models: ai.models, backend };
|
|
430
430
|
});
|
|
431
|
+
const IMAGE_MAX_MB = 30;
|
|
432
|
+
const IMAGE_MAX_BYTES = IMAGE_MAX_MB * 1024 * 1024;
|
|
431
433
|
class InputError extends Error {
|
|
432
434
|
}
|
|
433
435
|
const ALLOWED = ["image/png", "image/jpeg", "image/webp"];
|
|
434
|
-
const MAX_BYTES = 10 * 1024 * 1024;
|
|
435
436
|
const str = (v) => typeof v === "string" ? v : "";
|
|
436
437
|
const bool = (v) => v === true || v === "true";
|
|
437
438
|
const list = (v) => v ? Array.isArray(v) ? v : [v] : [];
|
|
@@ -442,7 +443,7 @@ const clean = (text2, labels) => {
|
|
|
442
443
|
};
|
|
443
444
|
const checkImage = (f) => {
|
|
444
445
|
if (!ALLOWED.includes(f.mimetype ?? "")) throw new InputError("Las imágenes deben ser PNG, JPG o WEBP.");
|
|
445
|
-
if (f.size >
|
|
446
|
+
if (f.size > IMAGE_MAX_BYTES) throw new InputError(`Cada imagen puede pesar hasta ${IMAGE_MAX_MB} MB.`);
|
|
446
447
|
return f;
|
|
447
448
|
};
|
|
448
449
|
const parseGenerateInput = (fields, files) => {
|
package/dist/server/index.mjs
CHANGED
|
@@ -410,10 +410,11 @@ const imageStudio$1 = ({ strapi }) => createImageStudio(async () => {
|
|
|
410
410
|
const { ai, backend } = await strapi.plugin("strapi-content-generator-gemini").service("service").geminiClient();
|
|
411
411
|
return { models: ai.models, backend };
|
|
412
412
|
});
|
|
413
|
+
const IMAGE_MAX_MB = 30;
|
|
414
|
+
const IMAGE_MAX_BYTES = IMAGE_MAX_MB * 1024 * 1024;
|
|
413
415
|
class InputError extends Error {
|
|
414
416
|
}
|
|
415
417
|
const ALLOWED = ["image/png", "image/jpeg", "image/webp"];
|
|
416
|
-
const MAX_BYTES = 10 * 1024 * 1024;
|
|
417
418
|
const str = (v) => typeof v === "string" ? v : "";
|
|
418
419
|
const bool = (v) => v === true || v === "true";
|
|
419
420
|
const list = (v) => v ? Array.isArray(v) ? v : [v] : [];
|
|
@@ -424,7 +425,7 @@ const clean = (text2, labels) => {
|
|
|
424
425
|
};
|
|
425
426
|
const checkImage = (f) => {
|
|
426
427
|
if (!ALLOWED.includes(f.mimetype ?? "")) throw new InputError("Las imágenes deben ser PNG, JPG o WEBP.");
|
|
427
|
-
if (f.size >
|
|
428
|
+
if (f.size > IMAGE_MAX_BYTES) throw new InputError(`Cada imagen puede pesar hasta ${IMAGE_MAX_MB} MB.`);
|
|
428
429
|
return f;
|
|
429
430
|
};
|
|
430
431
|
const parseGenerateInput = (fields, files) => {
|
package/package.json
CHANGED