@cardinali-studio/adminkit 2.1.0-rc.1 → 2.1.0-rc.3

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.
@@ -233,12 +233,11 @@ export function PageEditor({ page, onChange, onRefresh, pristine, pickMedia, pic
233
233
  });
234
234
  return () => { alive = false; };
235
235
  }, [page.slug, showBody, pristine, loadedFor, translationActive]);
236
- if (translationActive && translationState === "loading" && !translation) {
237
- return _jsx("p", { className: "pane-empty ak-hint", children: "Carico la traduzione\u2026" });
238
- }
239
- if (translationActive && translationState === "error" && !translation) {
240
- return _jsx("p", { className: "pe-load-error", children: "Non sono riuscito a caricare la traduzione. Riprova o torna alla lingua predefinita." });
241
- }
236
+ /* La lingua secondaria nasce ereditando la pagina predefinita. Non sostituire mai
237
+ l'editor con una schermata vuota mentre si legge la sibling: oltre a sembrare una
238
+ perdita di contenuto, in caso di errore non lasciava nulla da cui ripartire. */
239
+ const translationLoading = translationActive && translationState === "loading" && !translation;
240
+ const translationFailed = translationActive && translationState === "error" && !translation;
242
241
  const shownPage = translationActive && translation
243
242
  ? { ...page, ...translation.page, ...(showBody ? { body: translation.body ?? "" } : {}) }
244
243
  : page;
@@ -302,5 +301,5 @@ export function PageEditor({ page, onChange, onRefresh, pristine, pickMedia, pic
302
301
  }
303
302
  return (_jsxs("div", { className: "ed", children: [translationActive && (_jsx("p", { className: "pe-translation-note", children: page.translations?.[activeLanguage]?.exists || page._translations?.[activeLanguage]
304
303
  ? `Stai modificando ${activeLanguage.toUpperCase()}. I campi non traducibili restano visibili e vengono copiati dalla lingua predefinita al salvataggio.`
305
- : `${activeLanguage.toUpperCase()} è uguale all’italiano finché non modifichi e salvi una traduzione.` })), _jsx(SchemaForm, { shape: definition?.shape ?? {}, value: shownPage, omit: commonOmissions, onChange: (next) => changeShown({ ...next, slug: page.slug }), pickMedia: pickMedia, pickMediaFiles: pickMediaFiles, translationReadOnly: translationActive }), showBody && (_jsxs("fieldset", { className: "ak-group", children: [_jsx("legend", { className: "ak-legend", children: "testo della pagina" }), bodyState === "loading" && _jsx("p", { className: "ak-hint", children: "Carico\u2026" }), bodyState === "error" && _jsx("p", { className: "ak-error", children: "Non sono riuscito a caricare il testo." }), _jsx("textarea", { className: "ak-input ak-textarea", rows: 12, value: typeof shownPage.body === "string" ? shownPage.body : "", onChange: (event) => changeShown({ ...shownPage, body: event.target.value }) })] }))] }));
304
+ : `${activeLanguage.toUpperCase()} è uguale all’italiano finché non modifichi e salvi una traduzione.` })), translationLoading && (_jsx("p", { className: "ak-hint", children: "Carico la traduzione: i contenuti italiani restano visibili nel frattempo." })), translationFailed && (_jsx("p", { className: "pe-load-error", children: "Non sono riuscito a caricare la traduzione. I contenuti italiani restano visibili: torna a IT e riprova EN." })), _jsx(SchemaForm, { shape: definition?.shape ?? {}, value: shownPage, omit: commonOmissions, onChange: (next) => changeShown({ ...next, slug: page.slug }), pickMedia: pickMedia, pickMediaFiles: pickMediaFiles, translationReadOnly: translationActive }), showBody && (_jsxs("fieldset", { className: "ak-group", children: [_jsx("legend", { className: "ak-legend", children: "testo della pagina" }), bodyState === "loading" && _jsx("p", { className: "ak-hint", children: "Carico\u2026" }), bodyState === "error" && _jsx("p", { className: "ak-error", children: "Non sono riuscito a caricare il testo." }), _jsx("textarea", { className: "ak-input ak-textarea", rows: 12, value: typeof shownPage.body === "string" ? shownPage.body : "", onChange: (event) => changeShown({ ...shownPage, body: event.target.value }) })] }))] }));
306
305
  }
@@ -319,7 +319,10 @@ async function commitPages(args, attempt = 0) {
319
319
  if (typeof update.body === "string") translated.body = update.body;
320
320
  else if (!oldTranslation && typeof p.body === "string") translated.body = p.body;
321
321
  }
322
- const valid = definition.payload.safeParse(translated);
322
+ /* `translated` è il modello di CONTENUTO della sibling: non contiene `slug`,
323
+ che appartiene al contratto HTTP del payload padre. Validarlo con `payload`
324
+ faceva rifiutare ogni prima traduzione come se fosse una pagina senza tipo. */
325
+ const valid = definition.object.safeParse(translated);
323
326
  if (!valid.success) { invalidTypes.push(`${p.slug}.${code}`); continue; }
324
327
  const content = withTranslationHeader(serializeItem(translated, {
325
328
  shape: definition.shape,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardinali-studio/adminkit",
3
- "version": "2.1.0-rc.1",
3
+ "version": "2.1.0-rc.3",
4
4
  "type": "module",
5
5
  "description": "Motore riusabile di un pannello di amministrazione per siti Hugo su Cloudflare Pages: codec del front matter guidato dallo schema, form React, libreria media su R2. NIENTE di specifico di un sito qui dentro.",
6
6
  "license": "UNLICENSED",