@interware/content-generator 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/_chunks/App-Cwr5ra5m.js +1380 -0
  2. package/dist/_chunks/App-h4_txTsI.mjs +1362 -0
  3. package/dist/_chunks/{ImageStudioTabs-BLAH3KYv.mjs → ImageStudioTabs-B-mOwDfY.mjs} +687 -682
  4. package/dist/_chunks/{ImageStudioTabs-DtusqpQO.js → ImageStudioTabs-CG4KTn1S.js} +683 -678
  5. package/dist/_chunks/{Settings-o2GngLaW.mjs → Settings-BT-EqvXs.mjs} +2 -2
  6. package/dist/_chunks/{Settings-BQXxV3LO.js → Settings-D4NGBTk1.js} +4 -4
  7. package/dist/_chunks/{StudioApp-BaySMwrk.js → StudioApp-_ViSAwCm.js} +2 -2
  8. package/dist/_chunks/{StudioApp-C_znlQRo.mjs → StudioApp-xaEy-uIk.mjs} +2 -2
  9. package/dist/_chunks/{index-BKigRXm3.mjs → index-D67xWUPz.mjs} +3 -28
  10. package/dist/_chunks/{index-BKhe-Jyx.js → index-NA9OuMGs.js} +3 -28
  11. package/dist/admin/index.js +1 -1
  12. package/dist/admin/index.mjs +1 -1
  13. package/dist/admin/src/features/articles/ArticlePage.d.ts +5 -0
  14. package/dist/admin/src/features/articles/ArticlesPage.d.ts +7 -0
  15. package/dist/admin/src/features/articles/NewArticlePage.d.ts +6 -0
  16. package/dist/admin/src/features/articles/SharePreview.d.ts +19 -0
  17. package/dist/admin/src/features/articles/articlesApi.d.ts +94 -0
  18. package/dist/admin/src/features/articles/model.d.ts +24 -0
  19. package/dist/admin/src/features/articles/useArticlesApi.d.ts +19 -0
  20. package/dist/admin/src/features/library/LibraryImagePicker.d.ts +6 -1
  21. package/dist/admin/src/lib/postText.d.ts +25 -0
  22. package/dist/server/index.js +515 -321
  23. package/dist/server/index.mjs +515 -321
  24. package/dist/server/src/articles/generation.d.ts +135 -0
  25. package/dist/server/src/articles/schedule.d.ts +12 -0
  26. package/dist/server/src/articles/sources.d.ts +12 -0
  27. package/dist/server/src/bootstrap.d.ts +2 -0
  28. package/dist/server/src/controllers/articles.d.ts +30 -0
  29. package/dist/server/src/controllers/controller.d.ts +0 -4
  30. package/dist/server/src/controllers/index.d.ts +92 -4
  31. package/dist/server/src/index.d.ts +122 -67
  32. package/dist/server/src/services/articles.d.ts +126 -0
  33. package/dist/server/src/services/image-studio.d.ts +0 -10
  34. package/dist/server/src/services/index.d.ts +30 -63
  35. package/dist/server/src/services/service.d.ts +1 -62
  36. package/package.json +1 -1
  37. package/dist/_chunks/App-CJxSC8yt.js +0 -1105
  38. package/dist/_chunks/App-qbgUXlOZ.mjs +0 -1087
  39. package/dist/_chunks/getTranslation-B6Bsu-uq.mjs +0 -5
  40. package/dist/_chunks/getTranslation-BRVMWSf8.js +0 -4
  41. package/dist/admin/src/components/commons/dialog/index.d.ts +0 -12
  42. package/dist/admin/src/components/commons/generate-image-dialog/index.d.ts +0 -5
  43. package/dist/admin/src/components/generate-content/Form.d.ts +0 -15
  44. package/dist/admin/src/components/home/table.d.ts +0 -13
  45. package/dist/admin/src/components/index.d.ts +0 -12
  46. package/dist/admin/src/containers/generate-content/index.d.ts +0 -2
  47. package/dist/admin/src/containers/home/index.d.ts +0 -2
  48. package/dist/admin/src/hooks/useDialog.d.ts +0 -11
  49. package/dist/admin/src/lib/use-cases/articles/index.d.ts +0 -16
  50. package/dist/admin/src/lib/use-cases/categories/index.d.ts +0 -16
  51. package/dist/admin/src/lib/use-cases/facebook/index.d.ts +0 -5
  52. package/dist/admin/src/lib/use-cases/generate-content/index.d.ts +0 -6
  53. package/dist/admin/src/lib/use-cases/linkedin/index.d.ts +0 -5
  54. package/dist/admin/src/lib/use-cases/users/index.d.ts +0 -16
  55. package/dist/admin/src/pages/GenerateContent.d.ts +0 -2
  56. package/dist/admin/src/pages/HomePage.d.ts +0 -2
  57. package/dist/admin/src/reducers/dialog/index.d.ts +0 -6
  58. package/dist/admin/src/types/reducers.d.ts +0 -4
@@ -5,8 +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-BKigRXm3.mjs";
9
- import { g as getTranslation } from "./getTranslation-B6Bsu-uq.mjs";
8
+ import { P as PLUGIN_ID } from "./index-D67xWUPz.mjs";
10
9
  const useSettings = () => {
11
10
  const { get, post, del } = useFetchClient();
12
11
  const getSettings = useCallback(
@@ -136,6 +135,7 @@ const VertexSettings = ({ status, onSave, onRemove }) => {
136
135
  ] })
137
136
  ] }) });
138
137
  };
138
+ const getTranslation = (id) => `${PLUGIN_ID}.${id}`;
139
139
  const NOT_CONFIGURED = { configured: false, last4: null };
140
140
  const VERTEX_OFF = { configured: false, projectId: null, clientEmail: null };
141
141
  const serverMessage = (error, fallback) => error?.response?.data?.error?.message ?? fallback;
@@ -7,8 +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-BKhe-Jyx.js");
11
- const getTranslation = require("./getTranslation-BRVMWSf8.js");
10
+ const index = require("./index-NA9OuMGs.js");
12
11
  const useSettings = () => {
13
12
  const { get, post, del } = admin.useFetchClient();
14
13
  const getSettings = react.useCallback(
@@ -138,6 +137,7 @@ const VertexSettings = ({ status, onSave, onRemove }) => {
138
137
  ] })
139
138
  ] }) });
140
139
  };
140
+ const getTranslation = (id) => `${index.PLUGIN_ID}.${id}`;
141
141
  const NOT_CONFIGURED = { configured: false, last4: null };
142
142
  const VERTEX_OFF = { configured: false, projectId: null, clientEmail: null };
143
143
  const serverMessage = (error, fallback) => error?.response?.data?.error?.message ?? fallback;
@@ -225,7 +225,7 @@ const SettingsContainer = () => {
225
225
  }, []);
226
226
  return /* @__PURE__ */ jsxRuntime.jsx(PluginProviders.PluginProviders, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { padding: 6, gap: 3, children: [
227
227
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "start", children: [
228
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", children: formatMessage({ id: getTranslation.getTranslation("plugin.name") }) }),
228
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", children: formatMessage({ id: getTranslation("plugin.name") }) }),
229
229
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: "Para uso exclusivo de InterWare de México" })
230
230
  ] }) }),
231
231
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { children: /* @__PURE__ */ jsxRuntime.jsx(VertexSettings, { status: vertex, onSave: saveVertex, onRemove: deleteVertex }) }),
@@ -235,7 +235,7 @@ const SettingsContainer = () => {
235
235
  const SettingsPage = () => {
236
236
  const { formatMessage } = reactIntl.useIntl();
237
237
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [
238
- /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Title, { children: `${formatMessage({ id: getTranslation.getTranslation("plugin.name") })} | Settings` }),
238
+ /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Title, { children: `${formatMessage({ id: getTranslation("plugin.name") })} | Settings` }),
239
239
  /* @__PURE__ */ jsxRuntime.jsx(SettingsContainer, {})
240
240
  ] }) });
241
241
  };
@@ -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-BKhe-Jyx.js");
7
+ const index = require("./index-NA9OuMGs.js");
8
8
  const designSystem = require("@strapi/design-system");
9
- const ImageStudioTabs = require("./ImageStudioTabs-DtusqpQO.js");
9
+ const ImageStudioTabs = require("./ImageStudioTabs-CG4KTn1S.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, {}) })
@@ -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-BKigRXm3.mjs";
5
+ import { p as pluginPermissions } from "./index-D67xWUPz.mjs";
6
6
  import { Box } from "@strapi/design-system";
7
- import { I as ImageStudioTabs } from "./ImageStudioTabs-BLAH3KYv.mjs";
7
+ import { I as ImageStudioTabs } from "./ImageStudioTabs-B-mOwDfY.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, {}) })
@@ -1,7 +1,6 @@
1
1
  import { useRef, useEffect } from "react";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { Quotes, Lightning } from "@strapi/icons";
4
- import { createSlice } from "@reduxjs/toolkit";
5
4
  const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
6
5
  const v = glob[path];
7
6
  if (v) {
@@ -47,27 +46,6 @@ const pluginPermissions = {
47
46
  }
48
47
  ]
49
48
  };
50
- const initialState = {
51
- open: {}
52
- };
53
- const dialogSlice = createSlice({
54
- name: "sci_commonDialog",
55
- initialState,
56
- reducers: {
57
- openDialog: (state, action) => {
58
- state.open[action.payload] = true;
59
- },
60
- closeDialog: (state, action) => {
61
- state.open[action.payload] = false;
62
- }
63
- }
64
- });
65
- const { openDialog, closeDialog } = dialogSlice.actions;
66
- const dialogReducer = dialogSlice.reducer;
67
- const reducers = {
68
- // Reducer Syntax
69
- ["content_generator_commonDialog"]: dialogReducer
70
- };
71
49
  const index = {
72
50
  register(app) {
73
51
  app.addMenuLink({
@@ -78,7 +56,7 @@ const index = {
78
56
  defaultMessage: "Generador de contenido"
79
57
  },
80
58
  Component: async () => {
81
- const { App } = await import("./App-qbgUXlOZ.mjs");
59
+ const { App } = await import("./App-h4_txTsI.mjs");
82
60
  return App;
83
61
  },
84
62
  permissions: [
@@ -93,7 +71,7 @@ const index = {
93
71
  defaultMessage: "Estudio de imágenes"
94
72
  },
95
73
  Component: async () => {
96
- const { StudioApp } = await import("./StudioApp-C_znlQRo.mjs");
74
+ const { StudioApp } = await import("./StudioApp-xaEy-uIk.mjs");
97
75
  return StudioApp;
98
76
  },
99
77
  permissions: [
@@ -106,7 +84,6 @@ const index = {
106
84
  isReady: false,
107
85
  name: PLUGIN_ID
108
86
  });
109
- app.addReducers(reducers);
110
87
  app.addSettingsLink("global", {
111
88
  id: PLUGIN_ID,
112
89
  intlLabel: {
@@ -114,7 +91,7 @@ const index = {
114
91
  defaultMessage: PLUGIN_ID
115
92
  },
116
93
  Component: async () => {
117
- const component = await import("./Settings-o2GngLaW.mjs");
94
+ const component = await import("./Settings-BT-EqvXs.mjs");
118
95
  return component.default;
119
96
  },
120
97
  to: `plugins/${PLUGIN_ID}/settings`,
@@ -137,8 +114,6 @@ const index = {
137
114
  export {
138
115
  PLUGIN_ID as P,
139
116
  STUDIO_PATH as S,
140
- closeDialog as c,
141
117
  index as i,
142
- openDialog as o,
143
118
  pluginPermissions as p
144
119
  };
@@ -2,7 +2,6 @@
2
2
  const react = require("react");
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const icons = require("@strapi/icons");
5
- const toolkit = require("@reduxjs/toolkit");
6
5
  const __variableDynamicImportRuntimeHelper = (glob, path, segs) => {
7
6
  const v = glob[path];
8
7
  if (v) {
@@ -48,27 +47,6 @@ const pluginPermissions = {
48
47
  }
49
48
  ]
50
49
  };
51
- const initialState = {
52
- open: {}
53
- };
54
- const dialogSlice = toolkit.createSlice({
55
- name: "sci_commonDialog",
56
- initialState,
57
- reducers: {
58
- openDialog: (state, action) => {
59
- state.open[action.payload] = true;
60
- },
61
- closeDialog: (state, action) => {
62
- state.open[action.payload] = false;
63
- }
64
- }
65
- });
66
- const { openDialog, closeDialog } = dialogSlice.actions;
67
- const dialogReducer = dialogSlice.reducer;
68
- const reducers = {
69
- // Reducer Syntax
70
- ["content_generator_commonDialog"]: dialogReducer
71
- };
72
50
  const index = {
73
51
  register(app) {
74
52
  app.addMenuLink({
@@ -79,7 +57,7 @@ const index = {
79
57
  defaultMessage: "Generador de contenido"
80
58
  },
81
59
  Component: async () => {
82
- const { App } = await Promise.resolve().then(() => require("./App-CJxSC8yt.js"));
60
+ const { App } = await Promise.resolve().then(() => require("./App-Cwr5ra5m.js"));
83
61
  return App;
84
62
  },
85
63
  permissions: [
@@ -94,7 +72,7 @@ const index = {
94
72
  defaultMessage: "Estudio de imágenes"
95
73
  },
96
74
  Component: async () => {
97
- const { StudioApp } = await Promise.resolve().then(() => require("./StudioApp-BaySMwrk.js"));
75
+ const { StudioApp } = await Promise.resolve().then(() => require("./StudioApp-_ViSAwCm.js"));
98
76
  return StudioApp;
99
77
  },
100
78
  permissions: [
@@ -107,7 +85,6 @@ const index = {
107
85
  isReady: false,
108
86
  name: PLUGIN_ID
109
87
  });
110
- app.addReducers(reducers);
111
88
  app.addSettingsLink("global", {
112
89
  id: PLUGIN_ID,
113
90
  intlLabel: {
@@ -115,7 +92,7 @@ const index = {
115
92
  defaultMessage: PLUGIN_ID
116
93
  },
117
94
  Component: async () => {
118
- const component = await Promise.resolve().then(() => require("./Settings-BQXxV3LO.js"));
95
+ const component = await Promise.resolve().then(() => require("./Settings-D4NGBTk1.js"));
119
96
  return component.default;
120
97
  },
121
98
  to: `plugins/${PLUGIN_ID}/settings`,
@@ -137,7 +114,5 @@ const index = {
137
114
  };
138
115
  exports.PLUGIN_ID = PLUGIN_ID;
139
116
  exports.STUDIO_PATH = STUDIO_PATH;
140
- exports.closeDialog = closeDialog;
141
117
  exports.index = index;
142
- exports.openDialog = openDialog;
143
118
  exports.pluginPermissions = pluginPermissions;
@@ -1,3 +1,3 @@
1
1
  "use strict";
2
- const index = require("../_chunks/index-BKhe-Jyx.js");
2
+ const index = require("../_chunks/index-NA9OuMGs.js");
3
3
  module.exports = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "../_chunks/index-BKigRXm3.mjs";
1
+ import { i } from "../_chunks/index-D67xWUPz.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Pantalla del artículo (E6): vista previa, imagen elegida de la biblioteca, publicar ahora o
3
+ * programar, y compartir en redes cuando ya está publicado. Fuentes y SEO para revisar.
4
+ */
5
+ export declare const ArticlePage: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ export declare const articlePath: (documentId: string) => string;
2
+ export declare const NEW_ARTICLE_PATH = "/plugins/strapi-content-generator-gemini/generate-content";
3
+ /**
4
+ * Inicio del Generador de contenido (E6): en qué estado está cada artículo y qué le falta para
5
+ * publicarse. Publicar es lo obligatorio; compartir en redes, opcional.
6
+ */
7
+ export declare const ArticlesPage: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Nuevo artículo (E6): sin autor, con categoría que se crea si no existe, fuentes (URLs y búsqueda) e
3
+ * instrucciones en el mismo campo de Image Studio con «Enriquecer». Mientras genera muestra el avance;
4
+ * al terminar abre la pantalla del artículo.
5
+ */
6
+ export declare const NewArticlePage: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import type { RedSocial } from '../../lib/postText';
2
+ interface Props {
3
+ red: RedSocial;
4
+ mensaje: string;
5
+ article: {
6
+ titulo: string;
7
+ descripcion: string;
8
+ slug: string | null;
9
+ imageUrl: string | null;
10
+ imageName: string | null;
11
+ };
12
+ }
13
+ /**
14
+ * Vista previa aproximada del post (E6): encabezado de la página, texto y tarjeta del enlace como la arman
15
+ * LinkedIn y Facebook. Snowflake: el DS no tiene este componente; se pinta con sus tokens, sin marcas de
16
+ * terceros.
17
+ */
18
+ export declare const SharePreview: ({ red, mensaje, article }: Props) => import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,94 @@
1
+ export type Estado = 'borrador' | 'programado' | 'publicado';
2
+ export interface ArticleRow {
3
+ documentId: string;
4
+ titulo: string;
5
+ categoria: string | null;
6
+ estado: Estado;
7
+ imagen: boolean;
8
+ fechaPublicacion: string | null;
9
+ programadaPara: string | null;
10
+ linkedInPostId: string | null;
11
+ facebookPostId: string | null;
12
+ }
13
+ export interface Fuente {
14
+ titulo: string;
15
+ url: string;
16
+ tipo: 'referencia' | 'busqueda';
17
+ }
18
+ export interface ArticleDetail extends ArticleRow {
19
+ descripcion: string;
20
+ content: string;
21
+ minuteRead: number | null;
22
+ slug: string | null;
23
+ imageUrl: string | null;
24
+ imageName: string | null;
25
+ seo: {
26
+ metaTitle?: string;
27
+ metaDescription?: string;
28
+ } | null;
29
+ keywords: string[];
30
+ fuentes: Fuente[];
31
+ }
32
+ export interface GenerateBody {
33
+ titulo: string;
34
+ categoria: {
35
+ id: string;
36
+ } | {
37
+ nueva: string;
38
+ };
39
+ temperatura: number;
40
+ instrucciones: string;
41
+ urls: string[];
42
+ busqueda: boolean;
43
+ /** Con `false` se mandan las instrucciones tal cual. */
44
+ usarPromptBase: boolean;
45
+ /** Prompt base editado para esta generación. */
46
+ promptBase?: string;
47
+ }
48
+ /** Prompt base vigente: el guardado por el equipo o el predeterminado. */
49
+ export interface BasePrompt {
50
+ prompt: string;
51
+ personalizado: boolean;
52
+ }
53
+ export interface Categoria {
54
+ id: string;
55
+ nombre: string;
56
+ }
57
+ export type Red = 'linkedin' | 'facebook';
58
+ type Client = {
59
+ get: (url: string) => Promise<{
60
+ data: unknown;
61
+ }>;
62
+ post: (url: string, body: unknown, options?: {
63
+ signal?: AbortSignal;
64
+ }) => Promise<{
65
+ data: unknown;
66
+ }>;
67
+ put: (url: string, body: unknown) => Promise<{
68
+ data: unknown;
69
+ }>;
70
+ del: (url: string) => Promise<{
71
+ data: unknown;
72
+ }>;
73
+ };
74
+ /** Mensaje del servidor (400 y 404 traen uno legible) o el genérico dado. */
75
+ export declare const errorMessage: (err: unknown, fallback: string) => string;
76
+ /** Cliente de las rutas de artículos del plugin (E6). */
77
+ export declare const createArticlesApi: (client: Client) => {
78
+ list(): Promise<ArticleRow[]>;
79
+ detail(documentId: string): Promise<ArticleDetail>;
80
+ generate(body: GenerateBody): Promise<string>;
81
+ enrich(texto: string): Promise<string>;
82
+ basePrompt(): Promise<BasePrompt>;
83
+ saveBasePrompt(prompt: string): Promise<BasePrompt>;
84
+ resetBasePrompt(): Promise<BasePrompt>;
85
+ setImage(documentId: string, fileId: number): Promise<ArticleDetail>;
86
+ publish(documentId: string): Promise<ArticleDetail>;
87
+ schedule(documentId: string, at: string): Promise<ArticleDetail>;
88
+ unschedule(documentId: string): Promise<ArticleDetail>;
89
+ categories(): Promise<Categoria[]>;
90
+ /** Compartir en LinkedIn o Facebook con el texto escrito en el panel (vacío → el predeterminado). */
91
+ share(documentId: string, red: Red, mensaje: string): Promise<void>;
92
+ };
93
+ export type ArticlesApi = ReturnType<typeof createArticlesApi>;
94
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { ArticleRow } from './articlesApi';
2
+ export interface Accion {
3
+ label: string;
4
+ variant: 'secondary' | 'tertiary';
5
+ }
6
+ /** Lo que le toca a cada artículo en Inicio: publicar es lo obligatorio; compartir, opcional. */
7
+ export declare const nextAction: (r: ArticleRow) => Accion;
8
+ export interface Filtro {
9
+ id: string;
10
+ label: string;
11
+ test: (r: ArticleRow) => boolean;
12
+ }
13
+ export declare const FILTROS: Filtro[];
14
+ /** `2026-10-14` → «14 oct 2026». */
15
+ export declare const formatFecha: (fecha: string | null) => string;
16
+ /** Instante → fecha y hora en CDMX: «14 oct 2026 · 9:00». */
17
+ export declare const formatFechaHora: (iso: string) => string;
18
+ /** Fecha y hora escritas en CDMX → ISO en UTC para el servidor. */
19
+ export declare const fromMexicoLocal: (fecha: string, hora: string) => string;
20
+ /** ISO en UTC → fecha y hora de los campos, en CDMX. */
21
+ export declare const toMexicoLocal: (iso: string) => {
22
+ fecha: string;
23
+ hora: string;
24
+ };
@@ -0,0 +1,19 @@
1
+ /** Cliente de artículos conectado al panel (sesión y notificaciones de Strapi). */
2
+ export declare const useArticlesApi: () => {
3
+ api: {
4
+ list(): Promise<import("./articlesApi").ArticleRow[]>;
5
+ detail(documentId: string): Promise<import("./articlesApi").ArticleDetail>;
6
+ generate(body: import("./articlesApi").GenerateBody): Promise<string>;
7
+ enrich(texto: string): Promise<string>;
8
+ basePrompt(): Promise<import("./articlesApi").BasePrompt>;
9
+ saveBasePrompt(prompt: string): Promise<import("./articlesApi").BasePrompt>;
10
+ resetBasePrompt(): Promise<import("./articlesApi").BasePrompt>;
11
+ setImage(documentId: string, fileId: number): Promise<import("./articlesApi").ArticleDetail>;
12
+ publish(documentId: string): Promise<import("./articlesApi").ArticleDetail>;
13
+ schedule(documentId: string, at: string): Promise<import("./articlesApi").ArticleDetail>;
14
+ unschedule(documentId: string): Promise<import("./articlesApi").ArticleDetail>;
15
+ categories(): Promise<import("./articlesApi").Categoria[]>;
16
+ share(documentId: string, red: import("./articlesApi").Red, mensaje: string): Promise<void>;
17
+ };
18
+ notify: (type: 'success' | 'danger' | 'warning', message: string) => void;
19
+ };
@@ -1,3 +1,4 @@
1
+ import type { ReactNode } from 'react';
1
2
  import type { LibraryFile } from './uploadApi';
2
3
  interface LibraryImagePickerProps {
3
4
  open: boolean;
@@ -5,11 +6,15 @@ interface LibraryImagePickerProps {
5
6
  max: number;
6
7
  onClose: () => void;
7
8
  onPick: (files: LibraryFile[]) => void;
9
+ /** Título del modal (por defecto «Elegir de la biblioteca»). */
10
+ title?: string;
11
+ /** Contenido a la izquierda del pie, p. ej. un enlace a Image Studio (E6). */
12
+ footerStart?: ReactNode;
8
13
  }
9
14
  /**
10
15
  * Elegir imágenes de la biblioteca (S4.13, D2): navega las carpetas de «Generated» y muestra solo
11
16
  * imágenes. Lo elegido se conserva al cambiar de carpeta. Snowflake: el DS no tiene un selector de
12
17
  * archivos con miniaturas.
13
18
  */
14
- export declare const LibraryImagePicker: ({ open, max, onClose, onPick }: LibraryImagePickerProps) => import("react/jsx-runtime").JSX.Element;
19
+ export declare const LibraryImagePicker: ({ open, max, onClose, onPick, title, footerStart }: LibraryImagePickerProps) => import("react/jsx-runtime").JSX.Element;
15
20
  export {};
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Texto de las publicaciones en LinkedIn y Facebook (E6). Lo comparten el panel (prellena el campo) y el
3
+ * servidor (texto predeterminado si no llega uno), para que no se desincronicen.
4
+ */
5
+ export type RedSocial = 'linkedin' | 'facebook';
6
+ /** Máximo de LinkedIn para el texto de un post; se aplica a ambas redes. */
7
+ export declare const POST_MAX = 3000;
8
+ interface ArticuloPost {
9
+ titulo: string;
10
+ descripcion: string;
11
+ keywords: string[];
12
+ }
13
+ /** «nube híbrida» → «#nubehíbrida». Conserva acentos y ñ (antes se perdían). */
14
+ export declare const hashtags: (keywords: string[]) => string;
15
+ /** Lo que se publicaba antes del E6: LinkedIn sin título (va en la tarjeta del enlace); Facebook con título. */
16
+ export declare const defaultPostText: ({ titulo, descripcion, keywords }: ArticuloPost, red: RedSocial) => string;
17
+ /** Texto escrito en el diálogo: vacío → `null` (se usa el predeterminado); más de `POST_MAX` → error. */
18
+ export declare const checkPostText: (input: unknown) => {
19
+ ok: true;
20
+ text: string | null;
21
+ } | {
22
+ ok: false;
23
+ error: string;
24
+ };
25
+ export {};