@studiolxd/brand 48.0.0 → 49.0.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 (42) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/dist/_shared/tokens.js +0 -1
  3. package/dist/_shared/untrustedtext.js +27 -26
  4. package/dist/_types/atoms/TypingIndicator/TypingIndicator.d.ts +29 -2
  5. package/dist/_types/messages/BrandMessages.d.ts +25 -1
  6. package/dist/_types/messages/index.d.ts +1 -1
  7. package/dist/_types/molecules/AssistantMessage/AssistantMessage.d.ts +15 -1
  8. package/dist/_types/molecules/ConversationList/ConversationList.d.ts +42 -8
  9. package/dist/_types/molecules/FilterBar/FilterBar.d.ts +4 -3
  10. package/dist/_types/molecules/MessageComposer/MessageComposer.d.ts +24 -1
  11. package/dist/_types/molecules/Pagination/Pagination.d.ts +16 -2
  12. package/dist/_types/organisms/AnnotationThread/AnnotationThread.d.ts +52 -7
  13. package/dist/_types/organisms/ConversationThread/ConversationThread.d.ts +26 -3
  14. package/dist/_types/templates/ChatShell/ChatShell.d.ts +22 -4
  15. package/dist/_types/templates/ConnectorAuth/ConnectorAuthShell.d.ts +6 -1
  16. package/dist/_types/templates/ConnectorAuth/ConnectorConsentPage.d.ts +52 -18
  17. package/dist/_types/templates/ConnectorAuth/ConnectorExternalSignInPage.d.ts +57 -17
  18. package/dist/_types/templates/ConnectorAuth/ConnectorRejectionPage.d.ts +59 -15
  19. package/dist/_types/templates/ConnectorAuth/ConnectorRequestSummary.d.ts +43 -12
  20. package/dist/_types/templates/ConnectorAuth/ConnectorSignInPage.d.ts +46 -12
  21. package/dist/_types/templates/ConnectorAuth/UntrustedText.d.ts +31 -4
  22. package/dist/annotation-thread.js +49 -46
  23. package/dist/assistant-message.js +12 -9
  24. package/dist/brand.css +2 -4
  25. package/dist/chat-shell.js +50 -49
  26. package/dist/connector-consent-page.js +58 -68
  27. package/dist/connector-external-sign-in-page.js +22 -28
  28. package/dist/connector-rejection-page.js +31 -62
  29. package/dist/connector-request-summary.js +22 -20
  30. package/dist/connector-sign-in-page.js +21 -25
  31. package/dist/conversation-list.js +56 -55
  32. package/dist/conversation-thread.js +33 -31
  33. package/dist/filter-bar.css +1 -1
  34. package/dist/message-composer.js +38 -37
  35. package/dist/pagination.js +12 -12
  36. package/dist/tokens.css +2 -4
  37. package/dist/typing-indicator.js +12 -9
  38. package/package.json +1 -1
  39. package/src/tokens/molecules/filter-bar.css +1 -2
  40. package/src/tokens/scss/molecules/_filter-bar.scss +1 -2
  41. package/src/tokens/surface-public.css +0 -1
  42. package/src/tokens/tokens.json +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,176 @@ El paquete sigue [semver](https://semver.org/lang/es/): **patch** para bug fixes
7
7
  regeneración de `dist`, **minor** para componentes/props/variantes/tokens nuevos, **major**
8
8
  para breaking changes.
9
9
 
10
+ ## [49.0.0] — 2026-09-16
11
+
12
+ > **Major.** La **última ola** del proveedor de textos, y la más distinta: el chat y las
13
+ > pantallas del conector. Doce espacios nuevos, y con ellos la línea que faltaba por
14
+ > trazar — **lo que afirma algo no se pone en un catálogo de cromo**. Los textos de
15
+ > consentimiento, los cinco motivos de rechazo, qué se concede y el nombre del asistente
16
+ > pasan a ser **props obligatorias y sin default**, como `confirmDialog.confirmLabel` en la
17
+ > v45. Con esto, ningún componente del paquete trae ya castellano puesto.
18
+
19
+ ### El chat y el conector leen del proveedor
20
+
21
+ Doce espacios nuevos en `BrandMessages`: `messageComposer`, `conversationList`,
22
+ `conversationThread`, `typingIndicator`, `annotationThread`, `chatShell`, `untrustedText`,
23
+ `connectorRequestSummary`, `connectorConsent`, `connectorSignIn`,
24
+ `connectorExternalSignIn` y `connectorRejection`. Mismo orden —**prop → proveedor →
25
+ error**— y cada texto se lee **donde se pinta**: una lista de conversaciones que carga bien
26
+ no exige el título de su aviso de error, un hilo de anotaciones abierto no exige los
27
+ rótulos de «atendida» ni de «resuelta», y un armazón de chat montado sin columna no exige
28
+ ninguno de sus dos textos.
29
+
30
+ ### La línea de esta ola: el cromo nombra un control, el contenido afirma algo
31
+
32
+ Es la distinción que las ocho olas anteriores rozaron y esta tiene que resolver, porque
33
+ aquí casi todo el texto es una frase larga de producto o de consentimiento. La regla, en
34
+ una línea: **si el texto nombra un control, un estado o un dato, es cromo y va al catálogo;
35
+ si afirma algo —qué se concede, a dónde sale un acceso, qué comprobación ha fallado, cómo
36
+ se llama el asistente—, es contenido y es prop obligatoria sin default.**
37
+
38
+ Tres parejas la enseñan mejor que cualquier definición:
39
+
40
+ - **`connectorConsent.deny` frente a `ConnectorConsentPage.approveLabel`.** «Denegar»
41
+ describe lo único que hace ese botón —no seguir— y no hay consecuencia que nombrar:
42
+ cromo. El otro es **donde se concede el acceso**, y tiene que nombrar la consecuencia:
43
+ obligatorio y fuera del catálogo. Es literalmente el caso de `confirmDialog.cancel`
44
+ frente a `ConfirmDialog.confirmLabel`, y se resuelve igual.
45
+ - **`connectorRequestSummary.scope` frente a `scopeReadLabel`.** El rótulo «Permiso» nombra
46
+ qué dato va en esa fila de la ficha: cromo. Lo que ese permiso **es** —«leer los datos de
47
+ este producto»— afirma qué va a poder hacer una herramienta con los datos de quien lee la
48
+ pantalla, y eso lo sabe el servidor de autorización, no un catálogo común.
49
+ - **`typingIndicator.typing(name)` frente a `TypingIndicator.name`.** Que alguien esté
50
+ escribiendo es cromo: lo dice igual cualquier chat, y el orden de las piezas es del
51
+ idioma. **Quién** escribe es contenido: un catálogo común dejaría diciendo «El asistente»
52
+ en un chat cuyo asistente tiene nombre propio.
53
+
54
+ ### `ConnectorRejectionPage` deja de traer los cinco rechazos dentro
55
+
56
+ Era el caso más claro de todos y el que más cambia: un `Record` con **veinte cadenas
57
+ castellanas** —título, explicación, qué hacer y rótulo de la salida, por cada uno de los
58
+ cinco motivos— vivía dentro del componente, y la prop `reason` elegía cuatro. Cada una de
59
+ esas veinte afirma algo sobre una comprobación de seguridad («no se ha enviado nada a
60
+ ninguna parte», «si no la reconoces, no vuelvas a intentarlo»), y eso no lo decide el
61
+ sistema de diseño.
62
+
63
+ Así que el `Record` se retira entero, `reason` **desaparece** y `title`, `description`,
64
+ `hint` y `retryLabel` pasan a ser obligatorias. El tipo `ConnectorRejectionReason` se
65
+ queda —es el **vocabulario** de los cinco motivos, escrito en el sistema— para que la
66
+ aplicación teclee contra él al sacar los cuatro textos de su catálogo. La maqueta, el
67
+ orden y la postura no cambian: ninguno de los cinco ofrece reintentar en el sitio.
68
+
69
+ ### `untrustedText.quotes`: las comillas son puntuación del idioma
70
+
71
+ Las comillas que enmarcan un dato de fuera no son una decisión del producto ni un adorno:
72
+ son `« »` en castellano, `“ ”` en inglés y `„ “` en alemán. Al catálogo, como el resto del
73
+ cromo. El **valor** que enmarcan sigue entrando por `value` y no pasa por ningún catálogo
74
+ —es dato de un tercero—: por eso se pinta entrecomillado, aislado en un `<bdi>` y con los
75
+ caracteres invisibles a la vista.
76
+
77
+ ### `chatShell.list` no es `conversationList.nav`, aunque hoy digan lo mismo
78
+
79
+ Dos espacios para la misma palabra, a propósito: son dos piezas distintas —el armazón de la
80
+ pantalla y la lista que cuelga de él—, y el armazón se monta también **sin lista**, dentro
81
+ de un `AppShell` donde la columna vive en el `Sidebar`. El precedente ya estaba puesto con
82
+ `appRoot.skipToContent` frente a `appShell.skipToContent`.
83
+
84
+ ### Los tres estados de `AnnotationThread` van clave a clave
85
+
86
+ Contra la regla general de que una **lista** se traduce pasándola entera. Es la misma
87
+ excepción que los seis tipos de la leyenda de `CalendarRoster`, y por la misma razón: es un
88
+ vocabulario **cerrado** del componente —abierta, atendida, resuelta— y obligar a la
89
+ aplicación a montar nada para traducir tres palabras era peor que darle tres claves. Las
90
+ props siguen ganando, así que una revisión puede llamar «Verificada» a `acknowledged`.
91
+
92
+ ### Para quien actualice
93
+
94
+ **1. El catálogo del `BrandMessagesProvider` tiene que crecer con los doce espacios**, o la
95
+ primera pantalla de chat o de conector **lanza en render**:
96
+
97
+ | Espacio | Claves | Qué es |
98
+ | --- | --- | --- |
99
+ | `messageComposer` | `placeholder`, `send` | el marcador del campo y el botón que manda |
100
+ | `conversationList` | `new`, `nav`, `delete(label)`, `empty`, `error` | el cromo de la lista y sus dos estados propios |
101
+ | `conversationThread` | `label` | el nombre de la región que anuncia los mensajes |
102
+ | `typingIndicator` | `typing(name)` | la plantilla del estado de escritura |
103
+ | `annotationThread` | `label`, `open`, `acknowledged`, `resolved`, `edited`, `replies(count)` | el hilo, sus tres estados, la marca de editada y el recuento |
104
+ | `chatShell` | `list`, `listTrigger` | la columna de conversaciones y el botón que la despliega |
105
+ | `untrustedText` | `expand`, `collapse`, `quotes` | el desplegador de un valor recortado y las comillas del idioma |
106
+ | `connectorRequestSummary` | `client`, `product`, `account`, `scope`, `redirect` | los cinco rótulos de la ficha de la petición |
107
+ | `connectorConsent` | `title`, `deny` | el título de la pantalla y la salida que no concede nada |
108
+ | `connectorSignIn` | `title`, `signIn`, `fallbackProduct` | identificarse dentro del flujo del conector |
109
+ | `connectorExternalSignIn` | `title`, `organization`, `submit(platform)` | el conector ajeno (hoy, el de Moodle) |
110
+ | `connectorRejection` | `code` | el rótulo del código técnico |
111
+
112
+ Cuatro de ellas interpolan un dato (`conversationList.delete`,
113
+ `typingIndicator.typing`, `annotationThread.replies`, `connectorExternalSignIn.submit`),
114
+ así que son funciones. Y `untrustedText.quotes` **no es una cadena**: es la pareja
115
+ `[apertura, cierre]`.
116
+
117
+ **2. Estas props pasan a ser obligatorias y sin default. Rompen a quien no las pase, y esa
118
+ es la parte breaking de la release:**
119
+
120
+ | Componente | Props que pasan a obligatorias |
121
+ | --- | --- |
122
+ | `TypingIndicator` | `name` |
123
+ | `AssistantMessage` | `streamingName` |
124
+ | `ConversationThread` | `streamingName` |
125
+ | `ConnectorRequestSummary` | `scopeReadLabel`, `scopeWriteLabel` |
126
+ | `ConnectorConsentPage` | `intro`, `redirectNotice`, `approveLabel`, `scopeReadLabel`, `scopeWriteLabel` |
127
+ | `ConnectorSignInPage` | `intro`, `scopeReadLabel`, `scopeWriteLabel` |
128
+ | `ConnectorExternalSignInPage` | `platformName`, `intro`, `signingInTo` |
129
+ | `ConnectorRejectionPage` | `title`, `description`, `hint`, `retryLabel` |
130
+
131
+ **3. Y estos dos cambios de forma:**
132
+
133
+ - **`ConnectorRejectionPage.reason` desaparece.** Los cuatro textos que elegía ahora se
134
+ pasan. `ConnectorRejectionReason` sigue exportado, como vocabulario.
135
+ - **`ConnectorExternalSignInPage.platformName` pasa de `ReactNode` a `string`**, porque el
136
+ catálogo la interpola dentro del rótulo del botón
137
+ (`connectorExternalSignIn.submit(platform)`). Y `submitLabel` pasa de
138
+ `(parts: { platform }) => ReactNode` a `(platform: string) => string`, la misma firma que
139
+ la clave a la que anula.
140
+
141
+ **Ojo con dos valores.** `messageComposer.placeholder` y `typingIndicator.typing` llevan
142
+ **puntos suspensivos** dentro («Escribe un mensaje…», «… está escribiendo…»): son parte del
143
+ texto, no adorno — ver `Foundations/Redacción` § «Los estados de carga llevan puntos
144
+ suspensivos». Y `conversationList.delete` recibe el título de la conversación **entero**, sin
145
+ recortar: es el `aria-label` del aspa, y ahí el recorte visual de la fila no pinta nada.
146
+
147
+ ## [48.1.0] — 2026-09-16
148
+
149
+ > **Minor.** `FilterBar` pasa a columnas fijas por punto de corte —4 en escritorio, 2 en
150
+ > tableta, 1 antes de `md`— que llenan la fila entera en vez de dejar hueco a la derecha.
151
+ > Y `Pagination` deja de pintarse con 0 registros, sea cual sea el resto de sus props.
152
+
153
+ ### `FilterBar`: columnas por punto de corte, no por aritmética del ancho disponible
154
+
155
+ `.filter-bar__row` era `repeat(auto-fill, minmax(<mínimo>, 1fr))`: el número de columnas
156
+ lo decidía solo el ancho disponible, así que cuatro filtros en escritorio podían dejar una
157
+ columna vacía a la derecha en vez de llenar la fila. Ahora el máximo de columnas es fijo
158
+ por punto de corte —4 en `lg`, 2 en `md`, 1 antes— y la rejilla es `auto-fit` con un
159
+ mínimo que es una fracción del contenedor: con menos filtros que el máximo, las columnas
160
+ que sobran colapsan y las que tienen contenido se reparten el ancho sobrante, así que la
161
+ fila siempre queda llena — tres filtros en escritorio son tres columnas iguales, no tres
162
+ de cuatro con hueco. Con más filtros que el máximo, saltan de fila como antes. El botón de
163
+ `actions` sigue siendo una celda más de la misma rejilla, así que participa del reparto.
164
+
165
+ Se retira el token `filter-bar.column-min-inline-size` (ya no decide nada: el máximo de
166
+ columnas es fijo en el CSS, no una medida). El resto de los tokens de la barra no cambia.
167
+
168
+ ### `Pagination`: con 0 registros, nunca se pinta
169
+
170
+ `total === 0` dejaba de pintar el `<nav>` solo si además `pageCount` no estaba informado y
171
+ `afterPageSize` estaba vacío — con `showTotal`, con el selector de página o con la ranura
172
+ llena, un listado sin resultados seguía sacando un paginador sin nada que paginar. Ahora
173
+ `total === 0` (o `pageCount === 0`) no pinta el `<nav>` **nunca**, con independencia de las
174
+ demás props. La ranura sigue salvando al paginador solo cuando el total **no se conoce
175
+ todavía** (la prop no se ha informado) y hay como mucho una página — una tabla que aún no
176
+ ha resuelto su total pero ya trae algo que exportar—; con una página y registros de verdad
177
+ (`total` informado y mayor que 0) se sigue pintando si hay selector, ranura o total, como
178
+ antes.
179
+
10
180
  ## [48.0.0] — 2026-09-16
11
181
 
12
182
  > **Major.** Novena familia al proveedor de textos: copiar, datos y estado. Diecisiete
@@ -2546,7 +2546,6 @@ var e = {
2546
2546
  "--filter-bar-gap": "1.5rem",
2547
2547
  "--filter-bar-column-gap": "1rem",
2548
2548
  "--filter-bar-row-gap": "0.75rem",
2549
- "--filter-bar-column-min-inline-size": "12rem",
2550
2549
  "--filter-bar-actions-gap": "0.75rem",
2551
2550
  "--filter-bar-label-offset": "calc(0.875rem * 1.5 + 0.5rem)",
2552
2551
  "--filter-bar-control-block-size": "2.5rem",
@@ -1,43 +1,44 @@
1
1
  import '../untrustedtext.css';
2
- import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
+ import { n as e } from "./brandmessagescontext.js";
3
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
4
  //#region src/stories/templates/ConnectorAuth/UntrustedText.tsx
4
- var n = /[\u061C\u200B\u200E\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g, r = 80;
5
- function i(e) {
6
- return e.replace(n, (e) => `[U+${e.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}]`);
5
+ var r = /[\u061C\u200B\u200E\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g, i = 80;
6
+ function a(e) {
7
+ return e.replace(r, (e) => `[U+${e.codePointAt(0).toString(16).toUpperCase().padStart(4, "0")}]`);
7
8
  }
8
- function a({ value: n, expandable: a = !1, expandLabel: o = "Ver el valor completo", collapseLabel: s = "Ver menos", quotes: c = ["«", "»"], className: l }) {
9
- let u = (...e) => [...e, l].filter(Boolean).join(" ");
10
- if (typeof n != "string") return /* @__PURE__ */ e("span", {
11
- className: u("connector-untrusted"),
12
- children: n
9
+ function o({ value: r, expandable: o = !1, expandLabel: s, collapseLabel: c, quotes: l, className: u }) {
10
+ let d = e("untrustedText"), f = (...e) => [...e, u].filter(Boolean).join(" ");
11
+ if (typeof r != "string") return /* @__PURE__ */ t("span", {
12
+ className: f("connector-untrusted"),
13
+ children: r
13
14
  });
14
- let d = i(n), f = Array.from(d).length > r, [p, m] = c, h = /* @__PURE__ */ t("span", {
15
- className: f ? "connector-untrusted__value connector-untrusted__value--clamped" : "connector-untrusted__value",
15
+ let p = a(r), m = Array.from(p).length > i, [h, g] = d("quotes", l), _ = /* @__PURE__ */ n("span", {
16
+ className: m ? "connector-untrusted__value connector-untrusted__value--clamped" : "connector-untrusted__value",
16
17
  children: [
17
- p,
18
- /* @__PURE__ */ e("bdi", { children: d }),
19
- m
18
+ h,
19
+ /* @__PURE__ */ t("bdi", { children: p }),
20
+ g
20
21
  ]
21
22
  });
22
- return !f || !a ? /* @__PURE__ */ e("span", {
23
- className: u("connector-untrusted"),
24
- children: h
25
- }) : /* @__PURE__ */ e("details", {
26
- className: u("connector-untrusted", "connector-untrusted--expandable"),
27
- children: /* @__PURE__ */ t("summary", {
23
+ return !m || !o ? /* @__PURE__ */ t("span", {
24
+ className: f("connector-untrusted"),
25
+ children: _
26
+ }) : /* @__PURE__ */ t("details", {
27
+ className: f("connector-untrusted", "connector-untrusted--expandable"),
28
+ children: /* @__PURE__ */ n("summary", {
28
29
  className: "connector-untrusted__summary",
29
- children: [h, /* @__PURE__ */ t("span", {
30
+ children: [_, /* @__PURE__ */ n("span", {
30
31
  className: "link connector-untrusted__toggle",
31
- children: [/* @__PURE__ */ e("span", {
32
+ children: [/* @__PURE__ */ t("span", {
32
33
  className: "connector-untrusted__more",
33
- children: o
34
- }), /* @__PURE__ */ e("span", {
34
+ children: d("expand", s)
35
+ }), /* @__PURE__ */ t("span", {
35
36
  className: "connector-untrusted__less",
36
- children: s
37
+ children: d("collapse", c)
37
38
  })]
38
39
  })]
39
40
  })
40
41
  });
41
42
  }
42
43
  //#endregion
43
- export { a as t };
44
+ export { o as t };
@@ -1,7 +1,34 @@
1
1
  import './TypingIndicator.css';
2
+ /**
3
+ * El verbo, y solo el verbo: «… está escribiendo…».
4
+ *
5
+ * La frase entera —«El asistente está escribiendo…»— tiene **dos mitades que
6
+ * no se deciden en el mismo sitio**. Que alguien esté escribiendo es cromo: lo
7
+ * dice igual cualquier chat de la suite, y el orden de las piezas es del
8
+ * idioma. **Quién** escribe es contenido: el asistente se llama como lo llame
9
+ * el producto, y un catálogo común lo dejaría diciendo «El asistente» en un
10
+ * chat cuyo asistente tiene nombre propio.
11
+ *
12
+ * De ahí que la clave sea una **función**: el catálogo pone la plantilla y el
13
+ * nombre entra por la prop `name`, que es obligatoria.
14
+ */
15
+ export interface TypingIndicatorMessages {
16
+ /** Plantilla del anuncio. Recibe el nombre de quien escribe. */
17
+ typing: (name: string) => string;
18
+ }
2
19
  export interface TypingIndicatorProps {
3
- /** Texto anunciado por lectores de pantalla. Default castellano: «El asistente está escribiendo…». */
20
+ /**
21
+ * Quién está escribiendo. **Obligatoria y sin default**: el nombre del
22
+ * asistente es contenido del producto, no cromo del sistema — ver
23
+ * `TypingIndicatorMessages`.
24
+ */
25
+ name: string;
26
+ /**
27
+ * La frase entera, cuando la plantilla del catálogo no vale. **Sin
28
+ * default**: sin ella, sale de `typingIndicator.typing(name)` del
29
+ * `BrandMessagesProvider`.
30
+ */
4
31
  label?: string;
5
32
  }
6
33
  /** Tres puntos cuadrados que laten en secuencia: «alguien está escribiendo». */
7
- export declare function TypingIndicator({ label }: TypingIndicatorProps): import("react/jsx-runtime").JSX.Element;
34
+ export declare function TypingIndicator({ name, label }: TypingIndicatorProps): import("react/jsx-runtime").JSX.Element;
@@ -62,6 +62,18 @@ import type { LegalFooterMessages } from '../sections/LegalFooter/LegalFooter';
62
62
  import type { CalendarRosterMessages } from '../molecules/CalendarRoster/CalendarRoster';
63
63
  import type { CalendarPlannerMessages } from '../molecules/CalendarPlanner/CalendarPlanner';
64
64
  import type { NotificationListMessages } from '../molecules/NotificationList/NotificationList';
65
+ import type { MessageComposerMessages } from '../molecules/MessageComposer/MessageComposer';
66
+ import type { ConversationListMessages } from '../molecules/ConversationList/ConversationList';
67
+ import type { ConversationThreadMessages } from '../organisms/ConversationThread/ConversationThread';
68
+ import type { TypingIndicatorMessages } from '../atoms/TypingIndicator/TypingIndicator';
69
+ import type { AnnotationThreadMessages } from '../organisms/AnnotationThread/AnnotationThread';
70
+ import type { ChatShellMessages } from '../templates/ChatShell/ChatShell';
71
+ import type { UntrustedTextMessages } from '../templates/ConnectorAuth/UntrustedText';
72
+ import type { ConnectorRequestSummaryMessages } from '../templates/ConnectorAuth/ConnectorRequestSummary';
73
+ import type { ConnectorConsentMessages } from '../templates/ConnectorAuth/ConnectorConsentPage';
74
+ import type { ConnectorSignInMessages } from '../templates/ConnectorAuth/ConnectorSignInPage';
75
+ import type { ConnectorExternalSignInMessages } from '../templates/ConnectorAuth/ConnectorExternalSignInPage';
76
+ import type { ConnectorRejectionMessages } from '../templates/ConnectorAuth/ConnectorRejectionPage';
65
77
  /**
66
78
  * El contrato de textos de la librería: un espacio por componente, y dentro
67
79
  * de cada espacio **todas las claves obligatorias**.
@@ -148,5 +160,17 @@ export interface BrandMessages {
148
160
  calendarRoster: CalendarRosterMessages;
149
161
  calendarPlanner: CalendarPlannerMessages;
150
162
  notificationList: NotificationListMessages;
163
+ messageComposer: MessageComposerMessages;
164
+ conversationList: ConversationListMessages;
165
+ conversationThread: ConversationThreadMessages;
166
+ typingIndicator: TypingIndicatorMessages;
167
+ annotationThread: AnnotationThreadMessages;
168
+ chatShell: ChatShellMessages;
169
+ untrustedText: UntrustedTextMessages;
170
+ connectorRequestSummary: ConnectorRequestSummaryMessages;
171
+ connectorConsent: ConnectorConsentMessages;
172
+ connectorSignIn: ConnectorSignInMessages;
173
+ connectorExternalSignIn: ConnectorExternalSignInMessages;
174
+ connectorRejection: ConnectorRejectionMessages;
151
175
  }
152
- export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, };
176
+ export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, };
@@ -2,4 +2,4 @@ export { BrandMessagesProvider } from './BrandMessagesProvider';
2
2
  export type { BrandMessagesProviderProps } from './BrandMessagesProvider';
3
3
  export { useBrandMessages } from './BrandMessagesContext';
4
4
  export type { BrandMessagesReader } from './BrandMessagesContext';
5
- export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, } from './BrandMessages';
5
+ export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, } from './BrandMessages';
@@ -19,7 +19,21 @@ export interface AssistantMessageProps extends React.ComponentPropsWithoutRef<'d
19
19
  timestampFormat?: Intl.DateTimeFormatOptions;
20
20
  /** Cuando true, muestra el indicador de escritura en lugar del contenido. */
21
21
  isStreaming?: boolean;
22
- /** Texto anunciado por lectores de pantalla para el estado de escritura. */
22
+ /**
23
+ * Quién escribe mientras se genera la respuesta, para el `TypingIndicator`.
24
+ * **Obligatoria y sin default**: el nombre del asistente es contenido del
25
+ * producto, y el verbo lo pone el catálogo
26
+ * (`typingIndicator.typing(name)`). Se pide siempre, aunque este mensaje no
27
+ * esté generándose: el mensaje del asistente puede estarlo en cualquier
28
+ * momento, y un nombre que aparece solo a veces es un texto sin traducir
29
+ * esperando su turno.
30
+ */
31
+ streamingName: string;
32
+ /**
33
+ * La frase entera del estado de escritura, cuando la plantilla del catálogo
34
+ * no vale. **Sin default**: sin ella, sale de
35
+ * `typingIndicator.typing(streamingName)`.
36
+ */
23
37
  streamingLabel?: string;
24
38
  /** Se añade DESPUÉS de las clases propias del componente (el consumidor añade, no sustituye). */
25
39
  className?: string;
@@ -1,5 +1,27 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import './ConversationList.css';
3
+ /**
4
+ * El cromo de la lista de conversaciones: el botón de abrir una nueva, el
5
+ * nombre de la navegación, el aspa de cada fila y los dos estados que la lista
6
+ * pinta ella misma —vacía y rota—.
7
+ *
8
+ * Los cinco son **genéricos**: dicen lo mismo en cualquier chat de la suite y
9
+ * ninguno afirma nada del producto. Los títulos de las conversaciones son
10
+ * datos y viajan en `conversations`; el detalle del fallo lo pone `error`, que
11
+ * nunca tuvo default.
12
+ */
13
+ export interface ConversationListMessages {
14
+ /** Rótulo del botón que abre una conversación nueva. */
15
+ new: string;
16
+ /** Nombre accesible del `<nav>` que envuelve la lista. */
17
+ nav: string;
18
+ /** Nombre accesible del aspa de una fila. Recibe el título de la conversación. */
19
+ delete: (label: string) => string;
20
+ /** Título del estado vacío que la lista pinta ella misma. */
21
+ empty: string;
22
+ /** Título del aviso de que la lista no se pudo cargar. */
23
+ error: string;
24
+ }
3
25
  export interface ConversationItem {
4
26
  id: string;
5
27
  label: string;
@@ -10,11 +32,20 @@ export interface ConversationListProps extends Omit<React.ComponentPropsWithoutR
10
32
  onNew: () => void;
11
33
  onSelect: (id: string) => void;
12
34
  onDelete: (id: string) => void;
13
- /** Texto del botón que abre una conversación nueva. Default castellano. */
35
+ /**
36
+ * Texto del botón que abre una conversación nueva. **Sin default**: sin él,
37
+ * sale de `conversationList.new` del `BrandMessagesProvider`.
38
+ */
14
39
  newLabel?: string;
15
- /** `aria-label` del `<nav>` que envuelve la lista. Default castellano. */
40
+ /**
41
+ * `aria-label` del `<nav>` que envuelve la lista. **Sin default**: sin él,
42
+ * sale de `conversationList.nav`.
43
+ */
16
44
  navLabel?: string;
17
- /** Nombre accesible del aspa de cada fila. Recibe el título de la conversación. */
45
+ /**
46
+ * Nombre accesible del aspa de cada fila. Recibe el título de la
47
+ * conversación. **Sin default**: sin él, sale de `conversationList.delete`.
48
+ */
18
49
  deleteLabel?: (label: string) => string;
19
50
  /**
20
51
  * La lista aún está cargando: en su sitio se pintan marcadores (`Skeleton`)
@@ -31,13 +62,16 @@ export interface ConversationListProps extends Omit<React.ComponentPropsWithoutR
31
62
  error?: ReactNode;
32
63
  /**
33
64
  * Título del `EmptyState` que la lista pinta **ella misma** cuando no hay
34
- * conversaciones. Default: "Todavía no hay conversaciones" (castellano). Sin
35
- * pasarla, el consumidor se lleva ese texto: el hueco vacío nunca se queda en
36
- * blanco, así que la pantalla no tiene que añadir un aviso propio encima —si
37
- * lo añade, se ven dos.
65
+ * conversaciones. **Sin default**: sin él, sale de
66
+ * `conversationList.empty`, así que el hueco vacío nunca se queda en blanco
67
+ * y la pantalla no tiene que añadir un aviso propio encima —si lo añade, se
68
+ * ven dos—. Solo se lee con la lista vacía.
38
69
  */
39
70
  emptyMessage?: string;
40
- /** `title` del `Alert` de error. Default castellano. */
71
+ /**
72
+ * `title` del `Alert` de error. **Sin default**: sin él, sale de
73
+ * `conversationList.error`, y solo se lee cuando hay `error`.
74
+ */
41
75
  errorTitle?: string;
42
76
  /** Se añade DESPUÉS de las clases propias del componente (el consumidor añade, no sustituye). */
43
77
  className?: string;
@@ -44,9 +44,10 @@ export interface FilterBarProps extends Omit<ComponentPropsWithoutRef<'div'>, 'c
44
44
  * consumidor, igual que en un formulario.
45
45
  *
46
46
  * Existe porque montarla a mano en un `Inline` se rompe en móvil: los campos
47
- * no encogen por debajo de su contenido y la fila se sale. Aquí la rejilla es
48
- * `auto-fit` sobre un ancho mínimo por token, así que el número de columnas lo
49
- * decide el sitio disponible y en pantalla estrecha queda una sola.
47
+ * no encogen por debajo de su contenido y la fila se sale. Aquí las columnas
48
+ * son fijas por punto de corte —4 en escritorio, 2 en tableta, 1 antes de
49
+ * `md`— y `auto-fit` hace que los filtros que haya llenen la fila entera, sin
50
+ * hueco a la derecha cuando hay menos de los que caben.
50
51
  *
51
52
  * `{...rest}` (`id`, `data-*`, `aria-*`…) va al `<div>`.
52
53
  */
@@ -1,12 +1,35 @@
1
1
  import { type ComponentProps, type ReactNode } from 'react';
2
2
  import './MessageComposer.css';
3
+ /**
4
+ * El cromo de la caja de escribir: el marcador del campo vacío y el rótulo del
5
+ * botón que manda. Son las dos palabras que dicen lo mismo en cualquier chat
6
+ * de la suite, así que van en el catálogo.
7
+ *
8
+ * Lo que NO va aquí es la línea de ayuda (`helperText`): la escribe el
9
+ * producto —el atajo de teclado, un aviso de privacidad— y nunca tuvo default
10
+ * en ningún idioma.
11
+ */
12
+ export interface MessageComposerMessages {
13
+ /** Marcador del campo vacío. */
14
+ placeholder: string;
15
+ /** Rótulo del botón de enviar. Es también su nombre accesible. */
16
+ send: string;
17
+ }
3
18
  export interface MessageComposerProps extends Omit<ComponentProps<'div'>, 'onChange'> {
4
19
  value: string;
5
20
  onChange: (value: string) => void;
6
21
  onSend: () => void;
22
+ /**
23
+ * Marcador del campo vacío. **Sin default**: sin él, sale de
24
+ * `messageComposer.placeholder` del `BrandMessagesProvider`.
25
+ */
7
26
  placeholder?: string;
8
27
  disabled?: boolean;
9
- /** Texto del botón de enviar. Es también su nombre accesible: no hay `aria-label` que lo contradiga. */
28
+ /**
29
+ * Texto del botón de enviar. Es también su nombre accesible: no hay
30
+ * `aria-label` que lo contradiga. **Sin default**: sin él, sale de
31
+ * `messageComposer.send`.
32
+ */
10
33
  sendLabel?: string;
11
34
  /**
12
35
  * Línea de ayuda bajo el marco, enlazada al campo con `aria-describedby`
@@ -33,9 +33,23 @@ export interface PaginationProps {
33
33
  * (`cursor`): para listados por cursor, donde no se sabe cuántas páginas hay.
34
34
  */
35
35
  mode?: 'pages' | 'cursor';
36
- /** Total de registros. Con `pageCount` o en modo `cursor` no hace falta. */
36
+ /**
37
+ * Total de registros. Con `pageCount` o en modo `cursor` no hace falta.
38
+ * Con `0` el paginador **no se pinta nunca** —ni con `pageCount` informado,
39
+ * ni con `showTotal`, ni con la ranura `afterPageSize` llena: no hay nada
40
+ * que paginar ni que exportar—. Ver la regla completa en `pageCount`.
41
+ */
37
42
  total?: number;
38
- /** Número de páginas, cuando quien pagina ya lo sabe (en vez de `total` + `pageSize`). */
43
+ /**
44
+ * Número de páginas, cuando quien pagina ya lo sabe (en vez de `total` +
45
+ * `pageSize`). Con `0`, igual que `total={0}`: el paginador no se pinta.
46
+ *
47
+ * Regla completa de cuándo el `<nav>` devuelve `null` (modo `pages`; en
48
+ * `cursor` no aplica, ver su prop): `total === 0`, o `pageCount === 0`, o
49
+ * (`total` sin informar y `pageCount` sin informar o `<= 1` y sin
50
+ * `afterPageSize`). Con una sola página pero `total` informado y mayor que
51
+ * 0, como hoy: se pinta si hay selector, ranura o `showTotal`.
52
+ */
39
53
  pageCount?: number;
40
54
  /** Página activa (1-indexed). En modo `cursor`, opcional. */
41
55
  page?: number;
@@ -1,5 +1,34 @@
1
1
  import { type ReactNode } from 'react';
2
2
  import './AnnotationThread.css';
3
+ /**
4
+ * El cromo del hilo de anotaciones: cómo se llama el hilo, cómo se dicen sus
5
+ * tres estados, cómo se marca una anotación editada y cómo se cuentan las
6
+ * respuestas.
7
+ *
8
+ * Los tres estados van **clave a clave** —como los seis tipos de la leyenda de
9
+ * `CalendarRoster`— porque son un vocabulario **cerrado** del componente: el
10
+ * hilo solo puede estar abierto, atendido o resuelto, y obligar a la
11
+ * aplicación a montar nada para traducir tres palabras era peor que darles
12
+ * tres claves. Las props siguen ganando: una revisión que llame «Verificada» a
13
+ * `acknowledged` sigue pudiendo.
14
+ *
15
+ * Quién escribió cada anotación, cuándo y qué dice son datos y viajan en
16
+ * `annotation` y `replies`.
17
+ */
18
+ export interface AnnotationThreadMessages {
19
+ /** Nombre accesible del hilo. */
20
+ label: string;
21
+ /** Rótulo del estado abierto. */
22
+ open: string;
23
+ /** Rótulo del estado atendido. */
24
+ acknowledged: string;
25
+ /** Rótulo del estado resuelto. */
26
+ resolved: string;
27
+ /** Marca de anotación editada, junto a la fecha. */
28
+ edited: string;
29
+ /** Rótulo que cuenta las respuestas. Recibe cuántas son, con su plural. */
30
+ replies: (count: number) => string;
31
+ }
3
32
  export interface AnnotationEntry {
4
33
  /** Identificador único dentro del hilo. */
5
34
  id: string;
@@ -60,20 +89,36 @@ export interface AnnotationThreadProps extends React.ComponentPropsWithoutRef<'a
60
89
  locale?: string;
61
90
  /** Formato de la fecha. Por defecto, día y hora cortos. */
62
91
  dateFormat?: Intl.DateTimeFormatOptions;
63
- /** Rótulo del estado abierto. Por defecto, en castellano: «Abierta». */
92
+ /**
93
+ * Rótulo del estado abierto. **Sin default**: sin él, sale de
94
+ * `annotationThread.open` del `BrandMessagesProvider`. Solo se lee con el
95
+ * hilo en ese estado.
96
+ */
64
97
  openLabel?: string;
65
- /** Rótulo del estado atendido. Por defecto, en castellano: «Atendida». */
98
+ /**
99
+ * Rótulo del estado atendido. **Sin default**: sin él, sale de
100
+ * `annotationThread.acknowledged`. Solo se lee con el hilo en ese estado.
101
+ */
66
102
  acknowledgedLabel?: string;
67
- /** Rótulo del estado resuelto. Por defecto, en castellano: «Resuelta». */
103
+ /**
104
+ * Rótulo del estado resuelto. **Sin default**: sin él, sale de
105
+ * `annotationThread.resolved`. Solo se lee con el hilo en ese estado.
106
+ */
68
107
  resolvedLabel?: string;
69
- /** Marca de anotación editada. Por defecto, en castellano: «editada». */
108
+ /**
109
+ * Marca de anotación editada. **Sin default**: sin ella, sale de
110
+ * `annotationThread.edited`, y solo se lee cuando alguna anotación lo está.
111
+ */
70
112
  editedLabel?: string;
71
113
  /**
72
- * Rótulo que cuenta las respuestas. Por defecto, en castellano:
73
- * «1 respuesta» / «N respuestas».
114
+ * Rótulo que cuenta las respuestas, con su plural. **Sin default**: sin él,
115
+ * sale de `annotationThread.replies`, y solo se lee cuando hay respuestas.
74
116
  */
75
117
  repliesLabel?: (count: number) => string;
76
- /** Nombre accesible del hilo. Por defecto, en castellano: «Hilo de anotaciones». */
118
+ /**
119
+ * Nombre accesible del hilo. **Sin default**: sin él, sale de
120
+ * `annotationThread.label`.
121
+ */
77
122
  label?: string;
78
123
  /** Se añade DESPUÉS de las clases propias. */
79
124
  className?: string;