@singleton-sd/post-kit-editor 0.4.0 → 0.6.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 (48) hide show
  1. package/README.md +68 -14
  2. package/dist/EditorErrorBoundary.d.ts +15 -0
  3. package/dist/EditorErrorBoundary.js +32 -0
  4. package/dist/EditorErrorBoundary.js.map +1 -0
  5. package/dist/canvas/EmailBuilderCanvas.js +2 -2
  6. package/dist/canvas/EmailBuilderCanvas.js.map +1 -1
  7. package/dist/editor-shell-states.d.ts +8 -0
  8. package/dist/editor-shell-states.js +15 -0
  9. package/dist/editor-shell-states.js.map +1 -0
  10. package/dist/email-template-editor.d.ts +9 -3
  11. package/dist/email-template-editor.js +137 -3
  12. package/dist/email-template-editor.js.map +1 -1
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +4 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/metadata/MetadataPanel.d.ts +3 -1
  17. package/dist/metadata/MetadataPanel.js +15 -3
  18. package/dist/metadata/MetadataPanel.js.map +1 -1
  19. package/dist/preview/PreviewDataEditor.d.ts +3 -1
  20. package/dist/preview/PreviewDataEditor.js +9 -2
  21. package/dist/preview/PreviewDataEditor.js.map +1 -1
  22. package/dist/preview/PreviewPane.d.ts +3 -1
  23. package/dist/preview/PreviewPane.js +5 -1
  24. package/dist/preview/PreviewPane.js.map +1 -1
  25. package/dist/save-send/SaveSendBar.d.ts +12 -0
  26. package/dist/save-send/SaveSendBar.js +43 -0
  27. package/dist/save-send/SaveSendBar.js.map +1 -0
  28. package/dist/save-send/dirty.d.ts +3 -0
  29. package/dist/save-send/dirty.js +27 -0
  30. package/dist/save-send/dirty.js.map +1 -0
  31. package/dist/save-send/recipient.d.ts +1 -0
  32. package/dist/save-send/recipient.js +15 -0
  33. package/dist/save-send/recipient.js.map +1 -0
  34. package/dist/save-send/types.d.ts +21 -0
  35. package/dist/save-send/types.js +27 -0
  36. package/dist/save-send/types.js.map +1 -0
  37. package/dist/validation/ValidationSummary.d.ts +5 -0
  38. package/dist/validation/ValidationSummary.js +29 -0
  39. package/dist/validation/ValidationSummary.js.map +1 -0
  40. package/dist/validation/extract-placeholders.d.ts +2 -0
  41. package/dist/validation/extract-placeholders.js +49 -0
  42. package/dist/validation/extract-placeholders.js.map +1 -0
  43. package/dist/validation/validate.d.ts +17 -0
  44. package/dist/validation/validate.js +154 -0
  45. package/dist/validation/validate.js.map +1 -0
  46. package/dist/variables/VariableCatalogue.js +1 -1
  47. package/dist/variables/VariableCatalogue.js.map +1 -1
  48. package/package.json +1 -1
package/README.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  React admin editor component for [PostKit](../../README.md) email templates. It
4
4
  edits the three Git-backed source files (`template.json`, `metadata.json`,
5
- `preview.json`) **in memory**. Persistence is not wired yet: `onSave` /
6
- `onSendTest` props are part of the public contract for later issues, but this
7
- package does not invoke them working edits are discarded when the component
8
- unmounts unless the host implements those callbacks (save/send-test UI lands in
9
- a follow-up issue).
5
+ `preview.json`) **in memory**, with Save and optional Send-test controls that
6
+ call **consumer-supplied** callbacks. The package never writes to disk, Git, or
7
+ the network, and never accepts API keys or other credentials as props.
10
8
 
11
9
  ## Installation
12
10
 
@@ -23,18 +21,49 @@ pnpm add react@^18.3.1 react-dom@^18.3.1
23
21
  ## Usage
24
22
 
25
23
  ```tsx
26
- import { EmailTemplateEditor, type TemplateSourceFiles } from '@singleton-sd/post-kit-editor';
24
+ import {
25
+ EmailTemplateEditor,
26
+ type TemplateSourceFiles,
27
+ type SerializedTemplateSource,
28
+ } from '@singleton-sd/post-kit-editor';
27
29
 
28
30
  export function TemplateAdminPage({ template }: { template: TemplateSourceFiles }) {
29
31
  return (
30
32
  <EmailTemplateEditor
31
33
  template={template}
32
34
  availableVariables={[{ name: 'name', description: 'Recipient display name' }]}
33
- onSave={async (files) => {
34
- await fetch('/api/templates', { method: 'PUT', body: JSON.stringify(files) });
35
+ onSave={async (serialized, files) => {
36
+ // Commit serialized.templateJson / metadataJson / previewJson to the
37
+ // consumer repository (e.g. via the app's own server endpoint).
38
+ const res = await fetch('/api/templates', {
39
+ method: 'PUT',
40
+ body: JSON.stringify({ serialized, key: files.metadata.key }),
41
+ });
42
+ // fetch() resolves for HTTP 4xx/5xx — return failure so the editor
43
+ // keeps dirty state and does not treat the rejection as success.
44
+ if (!res.ok) {
45
+ return { ok: false, message: 'Save failed.' };
46
+ }
47
+ }}
48
+ onSendTest={async (serialized, _files, recipient) => {
49
+ // Browser → your trusted server only. The server uses
50
+ // @singleton-sd/post-kit-client with POSTKIT_API_KEY from Azure Key
51
+ // Vault `ssd-global-kv-prod-ae` (production). Local `.env` is for
52
+ // development only — never embed a long-lived PostKit API key in
53
+ // browser code.
54
+ const res = await fetch('/api/templates/send-test', {
55
+ method: 'POST',
56
+ headers: { 'Content-Type': 'application/json' },
57
+ body: JSON.stringify({ serialized, recipient }),
58
+ });
59
+ if (!res.ok) {
60
+ return { ok: false, message: 'Test send failed.' };
61
+ }
62
+ }}
63
+ onDirtyChange={(dirty) => {
64
+ // Optional: guard in-app navigation while dirty.
35
65
  }}
36
66
  onPreviewRendered={(html) => {
37
- // Optional: host can offer “open preview in new tab”
38
67
  console.log('preview bytes', html.length);
39
68
  }}
40
69
  className="tenant-theme"
@@ -45,10 +74,35 @@ export function TemplateAdminPage({ template }: { template: TemplateSourceFiles
45
74
 
46
75
  ## Persistence is consumer-supplied
47
76
 
48
- The editor never writes to disk, Git, or a network endpoint. The `onSave` and
49
- `onSendTest` props exist so consumers can rely on a stable contract, but **this
50
- release does not call them** there is no Save / Send-Test control yet. Edits
51
- live only in React state (`workingFiles`) until a later issue adds that UI.
77
+ Save serializes the working state with `serializeTemplateSource()` and passes
78
+ both the `SerializedTemplateSource` strings and the structured
79
+ `TemplateSourceFiles` to `onSave`. The editor shows pending / success / failure
80
+ feedback and re-enables the control in every outcome. Rejected promises become
81
+ failure messages (no unhandled rejections).
82
+
83
+ Send-test chrome appears **only** when `onSendTest` is provided. The editor
84
+ validates a non-empty, plausible recipient address, then invokes the callback
85
+ with the same serialized payload. Test delivery must go through the consumer's
86
+ trusted server (typically `@singleton-sd/post-kit-client` server-side).
87
+
88
+ Optional `onDirtyChange` fires when working state diverges from the seeded
89
+ `template` prop and resets after a successful save.
90
+
91
+ ## Validation and accessibility
92
+
93
+ `validateTemplate(files)` (also exported) checks required metadata, key charset,
94
+ undeclared / unused variables, preview coverage, and optional `render-failed`
95
+ from the preview pane (passed through so the compiler is not invoked twice).
96
+ Error-severity issues disable Save and Send-test; warnings never block.
97
+
98
+ Optional props:
99
+
100
+ - `onValidationChange` — current `ValidationIssue[]` whenever it changes
101
+ - `loading` — non-interactive loading shell while the host fetches files
102
+ - `loadError` — non-interactive error shell with the host’s message
103
+
104
+ Inline field errors use `aria-describedby`. The validation summary is an
105
+ `aria-live` region; each entry focuses the responsible control.
52
106
 
53
107
  ## Preview data (synthetic only)
54
108
 
@@ -93,7 +147,7 @@ const html = renderToStaticMarkup(<EmailTemplateEditor template={template} onSav
93
147
  ```
94
148
 
95
149
  Specs live next to the code as `src/**/*.spec.tsx`. Behaviour that needs
96
- interaction is factored into pure functions (preview rows, `renderTemplatePreview`)
150
+ interaction is factored into pure functions (preview rows, save/send helpers)
97
151
  that can be tested without a DOM.
98
152
 
99
153
  ## Development
@@ -0,0 +1,15 @@
1
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
2
+ export interface EditorErrorBoundaryProps {
3
+ children: ReactNode;
4
+ }
5
+ interface EditorErrorBoundaryState {
6
+ error: Error | null;
7
+ }
8
+ export declare class EditorErrorBoundary extends Component<EditorErrorBoundaryProps, EditorErrorBoundaryState> {
9
+ state: EditorErrorBoundaryState;
10
+ static getDerivedStateFromError(error: Error): EditorErrorBoundaryState;
11
+ componentDidCatch(error: Error, info: ErrorInfo): void;
12
+ private handleRetry;
13
+ render(): ReactNode;
14
+ }
15
+ export {};
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorErrorBoundary = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const email_template_editor_1 = require("./email-template-editor");
7
+ class EditorErrorBoundary extends react_1.Component {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.state = { error: null };
11
+ this.handleRetry = () => {
12
+ this.setState({ error: null });
13
+ };
14
+ }
15
+ static getDerivedStateFromError(error) {
16
+ return { error };
17
+ }
18
+ componentDidCatch(error, info) {
19
+ if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'test') {
20
+ console.error('post-kit-editor render failure', error, info.componentStack);
21
+ }
22
+ }
23
+ render() {
24
+ const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
25
+ if (this.state.error) {
26
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `${p}fatal-error`, "data-testid": `${p}fatal-error`, role: "alert", children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}fatal-error-heading`, children: "Editor failed to render" }), (0, jsx_runtime_1.jsx)("p", { className: `${p}fatal-error-message`, children: this.state.error.message }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: `${p}fatal-error-retry`, "data-testid": `${p}fatal-error-retry`, onClick: this.handleRetry, children: "Retry" })] }));
27
+ }
28
+ return this.props.children;
29
+ }
30
+ }
31
+ exports.EditorErrorBoundary = EditorErrorBoundary;
32
+ //# sourceMappingURL=EditorErrorBoundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EditorErrorBoundary.js","sourceRoot":"","sources":["../src/EditorErrorBoundary.tsx"],"names":[],"mappings":";;;;AAAA,iCAAyE;AAEzE,mEAA8D;AAc9D,MAAa,mBAAoB,SAAQ,iBAGxC;IAHD;;QAIE,UAAK,GAA6B,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAa1C,gBAAW,GAAG,GAAS,EAAE;YAC/B,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC;IAsBJ,CAAC;IAnCC,MAAM,CAAC,wBAAwB,CAAC,KAAY;QAC1C,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC;IAED,iBAAiB,CAAC,KAAY,EAAE,IAAe;QAE7C,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YACtE,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAMD,MAAM;QACJ,MAAM,CAAC,GAAG,2CAAmB,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,CACL,iCAAK,SAAS,EAAE,GAAG,CAAC,aAAa,iBAAe,GAAG,CAAC,aAAa,EAAE,IAAI,EAAC,OAAO,aAC7E,+BAAI,SAAS,EAAE,GAAG,CAAC,qBAAqB,wCAA8B,EACtE,8BAAG,SAAS,EAAE,GAAG,CAAC,qBAAqB,YAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAK,EACvE,mCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAE,GAAG,CAAC,mBAAmB,iBACrB,GAAG,CAAC,mBAAmB,EACpC,OAAO,EAAE,IAAI,CAAC,WAAW,sBAGlB,IACL,CACP,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;CACF;AAzCD,kDAyCC"}
@@ -8,8 +8,8 @@ const EditorBlock_1 = require("./EditorBlock");
8
8
  const email_builder_1 = require("@usewaypoint/email-builder");
9
9
  function EmailBuilderCanvas({ document, onChange, readOnly = false, }) {
10
10
  if (readOnly) {
11
- return ((0, jsx_runtime_1.jsx)("div", { className: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, "data-testid": `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, children: (0, jsx_runtime_1.jsx)(email_builder_1.Reader, { document: document, rootBlockId: "root" }) }));
11
+ return ((0, jsx_runtime_1.jsx)("div", { id: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, className: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, "data-testid": `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, role: "region", tabIndex: -1, "aria-label": "Email document canvas", children: (0, jsx_runtime_1.jsx)(email_builder_1.Reader, { document: document, rootBlockId: "root" }) }));
12
12
  }
13
- return ((0, jsx_runtime_1.jsx)(editor_context_1.CanvasEditorProvider, { document: document, onChange: onChange, children: (0, jsx_runtime_1.jsx)("div", { className: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, "data-testid": `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, children: (0, jsx_runtime_1.jsx)(EditorBlock_1.EditorBlock, { id: "root" }) }) }));
13
+ return ((0, jsx_runtime_1.jsx)(editor_context_1.CanvasEditorProvider, { document: document, onChange: onChange, children: (0, jsx_runtime_1.jsx)("div", { id: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, className: `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, "data-testid": `${email_template_editor_1.EDITOR_CLASS_PREFIX}canvas`, role: "region", tabIndex: -1, "aria-label": "Email document canvas", children: (0, jsx_runtime_1.jsx)(EditorBlock_1.EditorBlock, { id: "root" }) }) }));
14
14
  }
15
15
  //# sourceMappingURL=EmailBuilderCanvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmailBuilderCanvas.js","sourceRoot":"","sources":["../../src/canvas/EmailBuilderCanvas.tsx"],"names":[],"mappings":";;AAcA,gDAoBC;;AA/BD,oEAA+D;AAC/D,qDAAwD;AACxD,+CAA4C;AAC5C,8DAAoD;AAQpD,SAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,QAAQ,GAAG,KAAK,GACQ;IACxB,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CACL,gCAAK,SAAS,EAAE,GAAG,2CAAmB,QAAQ,iBAAe,GAAG,2CAAmB,QAAQ,YACzF,uBAAC,sBAAM,IAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAC,MAAM,GAAG,GAC7C,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,uBAAC,qCAAoB,IAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,YAC1D,gCAAK,SAAS,EAAE,GAAG,2CAAmB,QAAQ,iBAAe,GAAG,2CAAmB,QAAQ,YACzF,uBAAC,yBAAW,IAAC,EAAE,EAAC,MAAM,GAAG,GACrB,GACe,CACxB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"EmailBuilderCanvas.js","sourceRoot":"","sources":["../../src/canvas/EmailBuilderCanvas.tsx"],"names":[],"mappings":";;AAcA,gDAkCC;;AA7CD,oEAA+D;AAC/D,qDAAwD;AACxD,+CAA4C;AAC5C,8DAAoD;AAQpD,SAAgB,kBAAkB,CAAC,EACjC,QAAQ,EACR,QAAQ,EACR,QAAQ,GAAG,KAAK,GACQ;IACxB,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CACL,gCACE,EAAE,EAAE,GAAG,2CAAmB,QAAQ,EAClC,SAAS,EAAE,GAAG,2CAAmB,QAAQ,iBAC5B,GAAG,2CAAmB,QAAQ,EAC3C,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,CAAC,gBACD,uBAAuB,YAElC,uBAAC,sBAAM,IAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAC,MAAM,GAAG,GAC7C,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,uBAAC,qCAAoB,IAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,YAC1D,gCACE,EAAE,EAAE,GAAG,2CAAmB,QAAQ,EAClC,SAAS,EAAE,GAAG,2CAAmB,QAAQ,iBAC5B,GAAG,2CAAmB,QAAQ,EAC3C,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,CAAC,gBACD,uBAAuB,YAElC,uBAAC,yBAAW,IAAC,EAAE,EAAC,MAAM,GAAG,GACrB,GACe,CACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface EditorLoadingStateProps {
2
+ message?: string;
3
+ }
4
+ export declare function EditorLoadingState({ message, }: EditorLoadingStateProps): JSX.Element;
5
+ export interface EditorLoadErrorStateProps {
6
+ message: string;
7
+ }
8
+ export declare function EditorLoadErrorState({ message }: EditorLoadErrorStateProps): JSX.Element;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorLoadingState = EditorLoadingState;
4
+ exports.EditorLoadErrorState = EditorLoadErrorState;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const email_template_editor_1 = require("./email-template-editor");
7
+ function EditorLoadingState({ message = 'Loading template…', }) {
8
+ const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
9
+ return ((0, jsx_runtime_1.jsx)("div", { className: `${p}loading`, "data-testid": `${p}loading`, role: "status", "aria-busy": "true", "aria-live": "polite", children: (0, jsx_runtime_1.jsx)("p", { className: `${p}loading-message`, children: message }) }));
10
+ }
11
+ function EditorLoadErrorState({ message }) {
12
+ const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
13
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `${p}load-error`, "data-testid": `${p}load-error`, role: "alert", children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}load-error-heading`, children: "Could not load template" }), (0, jsx_runtime_1.jsx)("p", { className: `${p}load-error-message`, children: message })] }));
14
+ }
15
+ //# sourceMappingURL=editor-shell-states.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-shell-states.js","sourceRoot":"","sources":["../src/editor-shell-states.tsx"],"names":[],"mappings":";;AAUA,gDAeC;AAOD,oDAQC;;AAtCD,mEAA8D;AAQ9D,SAAgB,kBAAkB,CAAC,EACjC,OAAO,GAAG,mBAAmB,GACL;IACxB,MAAM,CAAC,GAAG,2CAAmB,CAAC;IAC9B,OAAO,CACL,gCACE,SAAS,EAAE,GAAG,CAAC,SAAS,iBACX,GAAG,CAAC,SAAS,EAC1B,IAAI,EAAC,QAAQ,eACH,MAAM,eACN,QAAQ,YAElB,8BAAG,SAAS,EAAE,GAAG,CAAC,iBAAiB,YAAG,OAAO,GAAK,GAC9C,CACP,CAAC;AACJ,CAAC;AAOD,SAAgB,oBAAoB,CAAC,EAAE,OAAO,EAA6B;IACzE,MAAM,CAAC,GAAG,2CAAmB,CAAC;IAC9B,OAAO,CACL,iCAAK,SAAS,EAAE,GAAG,CAAC,YAAY,iBAAe,GAAG,CAAC,YAAY,EAAE,IAAI,EAAC,OAAO,aAC3E,+BAAI,SAAS,EAAE,GAAG,CAAC,oBAAoB,wCAA8B,EACrE,8BAAG,SAAS,EAAE,GAAG,CAAC,oBAAoB,YAAG,OAAO,GAAK,IACjD,CACP,CAAC;AACJ,CAAC"}
@@ -1,11 +1,17 @@
1
+ import { type SaveResult, type SendTestResult, type SerializedTemplateSource } from './save-send/types';
1
2
  import type { TemplateSourceFiles, TemplateVariable } from './types';
3
+ import { type ValidationIssue } from './validation/validate';
2
4
  export declare const EDITOR_CLASS_PREFIX = "pk-editor-";
3
5
  export interface EmailTemplateEditorProps {
4
6
  template: TemplateSourceFiles;
5
7
  availableVariables?: TemplateVariable[];
6
- onSave: (files: TemplateSourceFiles) => Promise<void> | void;
7
- onSendTest?: (files: TemplateSourceFiles, recipient: string) => Promise<void> | void;
8
+ onSave: (serialized: SerializedTemplateSource, files: TemplateSourceFiles) => Promise<SaveResult | void> | SaveResult | void;
9
+ onSendTest?: (serialized: SerializedTemplateSource, files: TemplateSourceFiles, recipient: string) => Promise<SendTestResult | void> | SendTestResult | void;
10
+ onDirtyChange?: (dirty: boolean) => void;
11
+ onValidationChange?: (issues: ValidationIssue[]) => void;
8
12
  onPreviewRendered?: (html: string) => void;
13
+ loading?: boolean;
14
+ loadError?: string;
9
15
  className?: string;
10
16
  }
11
- export declare function EmailTemplateEditor({ template, availableVariables, onPreviewRendered, className, }: EmailTemplateEditorProps): JSX.Element;
17
+ export declare function EmailTemplateEditor(props: EmailTemplateEditorProps): JSX.Element;
@@ -5,15 +5,82 @@ exports.EmailTemplateEditor = EmailTemplateEditor;
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
6
  const react_1 = require("react");
7
7
  const EmailBuilderCanvas_1 = require("./canvas/EmailBuilderCanvas");
8
+ const EditorErrorBoundary_1 = require("./EditorErrorBoundary");
9
+ const editor_shell_states_1 = require("./editor-shell-states");
8
10
  const insertion_target_1 = require("./insertion-target");
9
11
  const MetadataPanel_1 = require("./metadata/MetadataPanel");
10
12
  const PreviewDataEditor_1 = require("./preview/PreviewDataEditor");
11
13
  const PreviewPane_1 = require("./preview/PreviewPane");
14
+ const dirty_1 = require("./save-send/dirty");
15
+ const SaveSendBar_1 = require("./save-send/SaveSendBar");
16
+ const types_1 = require("./save-send/types");
17
+ const ValidationSummary_1 = require("./validation/ValidationSummary");
18
+ const validate_1 = require("./validation/validate");
12
19
  const VariableCatalogue_1 = require("./variables/VariableCatalogue");
13
20
  const working_files_1 = require("./working-files");
14
21
  exports.EDITOR_CLASS_PREFIX = 'pk-editor-';
15
- function EmailTemplateEditor({ template, availableVariables, onPreviewRendered, className, }) {
22
+ function EmailTemplateEditor(props) {
23
+ const rootClassName = [`${exports.EDITOR_CLASS_PREFIX}root`, props.className].filter(Boolean).join(' ');
24
+ if (props.loading) {
25
+ return ((0, jsx_runtime_1.jsx)("div", { className: rootClassName, "data-testid": `${exports.EDITOR_CLASS_PREFIX}root`, children: (0, jsx_runtime_1.jsx)(editor_shell_states_1.EditorLoadingState, {}) }));
26
+ }
27
+ if (props.loadError) {
28
+ return ((0, jsx_runtime_1.jsx)("div", { className: rootClassName, "data-testid": `${exports.EDITOR_CLASS_PREFIX}root`, children: (0, jsx_runtime_1.jsx)(editor_shell_states_1.EditorLoadErrorState, { message: props.loadError }) }));
29
+ }
30
+ return ((0, jsx_runtime_1.jsx)("div", { className: rootClassName, "data-testid": `${exports.EDITOR_CLASS_PREFIX}root`, children: (0, jsx_runtime_1.jsx)(EditorErrorBoundary_1.EditorErrorBoundary, { children: (0, jsx_runtime_1.jsx)(EmailTemplateEditorInner, { ...props }) }) }));
31
+ }
32
+ function EmailTemplateEditorInner({ template, availableVariables, onSave, onSendTest, onDirtyChange, onValidationChange, onPreviewRendered, }) {
16
33
  const [workingFiles, setWorkingFiles] = (0, react_1.useState)(template);
34
+ const [seedFiles, setSeedFiles] = (0, react_1.useState)(template);
35
+ const [saveFeedback, setSaveFeedback] = (0, react_1.useState)({ status: 'idle' });
36
+ const [sendFeedback, setSendFeedback] = (0, react_1.useState)({ status: 'idle' });
37
+ const [previewResult, setPreviewResult] = (0, react_1.useState)(null);
38
+ const onDirtyChangeRef = (0, react_1.useRef)(onDirtyChange);
39
+ onDirtyChangeRef.current = onDirtyChange;
40
+ const onValidationChangeRef = (0, react_1.useRef)(onValidationChange);
41
+ onValidationChangeRef.current = onValidationChange;
42
+ const lastDirtyRef = (0, react_1.useRef)(null);
43
+ const lastIssuesKeyRef = (0, react_1.useRef)(null);
44
+ const templateGenerationRef = (0, react_1.useRef)(0);
45
+ const seedFilesRef = (0, react_1.useRef)(seedFiles);
46
+ seedFilesRef.current = seedFiles;
47
+ (0, react_1.useEffect)(() => {
48
+ if (!(0, dirty_1.isWorkingDirty)(seedFilesRef.current, template)) {
49
+ return;
50
+ }
51
+ templateGenerationRef.current += 1;
52
+ setSaveFeedback({ status: 'idle' });
53
+ setSendFeedback({ status: 'idle' });
54
+ setPreviewResult(null);
55
+ setWorkingFiles(template);
56
+ setSeedFiles(template);
57
+ }, [template]);
58
+ (0, react_1.useEffect)(() => {
59
+ const dirty = (0, dirty_1.isWorkingDirty)(seedFiles, workingFiles);
60
+ if (lastDirtyRef.current === dirty) {
61
+ return;
62
+ }
63
+ lastDirtyRef.current = dirty;
64
+ onDirtyChangeRef.current?.(dirty);
65
+ }, [seedFiles, workingFiles]);
66
+ const issues = (0, validate_1.validateTemplate)(workingFiles, {
67
+ renderError: previewResult && !previewResult.ok ? previewResult.error : null,
68
+ });
69
+ (0, react_1.useEffect)(() => {
70
+ const key = JSON.stringify(issues);
71
+ if (lastIssuesKeyRef.current === key) {
72
+ return;
73
+ }
74
+ lastIssuesKeyRef.current = key;
75
+ onValidationChangeRef.current?.(issues);
76
+ }, [issues]);
77
+ const previewPending = previewResult === null;
78
+ const validationBlocked = (0, validate_1.hasValidationErrors)(issues) || previewPending;
79
+ const validationBlockedReason = previewPending
80
+ ? 'Wait for the preview to finish before saving or sending a test.'
81
+ : 'Fix validation errors before saving or sending a test.';
82
+ const metadataIssues = issues.filter((i) => i.field === 'metadata' || i.field === 'subject');
83
+ const previewDataIssues = issues.filter((i) => i.field === 'previewData');
17
84
  const handleDocumentChange = (0, react_1.useCallback)((document) => {
18
85
  setWorkingFiles((current) => (0, working_files_1.withDocument)(current, document));
19
86
  }, []);
@@ -26,7 +93,74 @@ function EmailTemplateEditor({ template, availableVariables, onPreviewRendered,
26
93
  const handlePreviewDataChange = (0, react_1.useCallback)((previewData) => {
27
94
  setWorkingFiles((current) => (0, working_files_1.withPreviewData)(current, previewData));
28
95
  }, []);
29
- const rootClassName = [`${exports.EDITOR_CLASS_PREFIX}root`, className].filter(Boolean).join(' ');
30
- return ((0, jsx_runtime_1.jsx)("div", { className: rootClassName, "data-testid": `${exports.EDITOR_CLASS_PREFIX}root`, children: (0, jsx_runtime_1.jsx)(insertion_target_1.InsertionTargetProvider, { children: (0, jsx_runtime_1.jsxs)("div", { className: `${exports.EDITOR_CLASS_PREFIX}layout`, "data-testid": `${exports.EDITOR_CLASS_PREFIX}layout`, children: [(0, jsx_runtime_1.jsxs)("aside", { className: `${exports.EDITOR_CLASS_PREFIX}sidebar`, children: [(0, jsx_runtime_1.jsx)(MetadataPanel_1.MetadataPanel, { metadata: workingFiles.metadata, previewData: workingFiles.previewData, onChange: handleMetadataChange }), (0, jsx_runtime_1.jsx)(VariableCatalogue_1.VariableCatalogue, { availableVariables: availableVariables, metadataVariables: workingFiles.metadata.variables, onMetadataVariablesChange: handleMetadataVariablesChange }), (0, jsx_runtime_1.jsx)(PreviewDataEditor_1.PreviewDataEditor, { declaredVariables: workingFiles.metadata.variables, previewData: workingFiles.previewData, onChange: handlePreviewDataChange })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${exports.EDITOR_CLASS_PREFIX}main`, children: [(0, jsx_runtime_1.jsx)(EmailBuilderCanvas_1.EmailBuilderCanvas, { document: workingFiles.templateJson, onChange: handleDocumentChange }), (0, jsx_runtime_1.jsx)(PreviewPane_1.PreviewPane, { files: workingFiles, onPreviewRendered: onPreviewRendered })] })] }) }) }));
96
+ const busy = saveFeedback.status === 'pending' || sendFeedback.status === 'pending';
97
+ const handleSave = (0, react_1.useCallback)(() => {
98
+ if (busy || validationBlocked) {
99
+ return;
100
+ }
101
+ let payload;
102
+ try {
103
+ payload = (0, types_1.buildSavePayload)(workingFiles);
104
+ }
105
+ catch (error) {
106
+ setSaveFeedback({
107
+ status: 'failure',
108
+ message: error instanceof Error ? error.message : String(error),
109
+ });
110
+ return;
111
+ }
112
+ const generation = templateGenerationRef.current;
113
+ setSaveFeedback({ status: 'pending' });
114
+ void (async () => {
115
+ const result = await (0, types_1.invokeConsumerAction)(() => onSave(payload.serialized, payload.files));
116
+ if (generation !== templateGenerationRef.current) {
117
+ return;
118
+ }
119
+ if (result.ok) {
120
+ setSeedFiles(payload.files);
121
+ setSaveFeedback({ status: 'success', message: result.message });
122
+ }
123
+ else {
124
+ setSaveFeedback({
125
+ status: 'failure',
126
+ message: result.message ?? 'Save failed.',
127
+ });
128
+ }
129
+ })();
130
+ }, [busy, onSave, validationBlocked, workingFiles]);
131
+ const handleSendTest = (0, react_1.useCallback)((recipient) => {
132
+ if (busy || validationBlocked || !onSendTest) {
133
+ return;
134
+ }
135
+ let payload;
136
+ try {
137
+ payload = (0, types_1.buildSavePayload)(workingFiles);
138
+ }
139
+ catch (error) {
140
+ setSendFeedback({
141
+ status: 'failure',
142
+ message: error instanceof Error ? error.message : String(error),
143
+ });
144
+ return;
145
+ }
146
+ const generation = templateGenerationRef.current;
147
+ setSendFeedback({ status: 'pending' });
148
+ void (async () => {
149
+ const result = await (0, types_1.invokeConsumerAction)(() => onSendTest(payload.serialized, payload.files, recipient));
150
+ if (generation !== templateGenerationRef.current) {
151
+ return;
152
+ }
153
+ if (result.ok) {
154
+ setSendFeedback({ status: 'success', message: result.message });
155
+ }
156
+ else {
157
+ setSendFeedback({
158
+ status: 'failure',
159
+ message: result.message ?? 'Send test failed.',
160
+ });
161
+ }
162
+ })();
163
+ }, [busy, onSendTest, validationBlocked, workingFiles]);
164
+ return ((0, jsx_runtime_1.jsx)(insertion_target_1.InsertionTargetProvider, { children: (0, jsx_runtime_1.jsxs)("div", { className: `${exports.EDITOR_CLASS_PREFIX}layout`, "data-testid": `${exports.EDITOR_CLASS_PREFIX}layout`, children: [(0, jsx_runtime_1.jsxs)("aside", { className: `${exports.EDITOR_CLASS_PREFIX}sidebar`, "aria-label": "Template settings", children: [(0, jsx_runtime_1.jsx)(SaveSendBar_1.SaveSendBar, { saveFeedback: saveFeedback, sendFeedback: sendFeedback, busy: busy, validationBlocked: validationBlocked, validationBlockedReason: validationBlockedReason, showSendTest: typeof onSendTest === 'function', onSave: handleSave, onSendTest: handleSendTest }), (0, jsx_runtime_1.jsx)(ValidationSummary_1.ValidationSummary, { issues: issues }), (0, jsx_runtime_1.jsx)(MetadataPanel_1.MetadataPanel, { metadata: workingFiles.metadata, previewData: workingFiles.previewData, onChange: handleMetadataChange, issues: metadataIssues }), (0, jsx_runtime_1.jsx)(VariableCatalogue_1.VariableCatalogue, { availableVariables: availableVariables, metadataVariables: workingFiles.metadata.variables, onMetadataVariablesChange: handleMetadataVariablesChange }), (0, jsx_runtime_1.jsx)(PreviewDataEditor_1.PreviewDataEditor, { declaredVariables: workingFiles.metadata.variables, previewData: workingFiles.previewData, onChange: handlePreviewDataChange, issues: previewDataIssues })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${exports.EDITOR_CLASS_PREFIX}main`, "aria-label": "Template canvas and preview", children: [(0, jsx_runtime_1.jsx)(EmailBuilderCanvas_1.EmailBuilderCanvas, { document: workingFiles.templateJson, onChange: handleDocumentChange }), (0, jsx_runtime_1.jsx)(PreviewPane_1.PreviewPane, { files: workingFiles, onPreviewRendered: onPreviewRendered, onPreviewResultChange: setPreviewResult })] })] }) }));
31
165
  }
32
166
  //# sourceMappingURL=email-template-editor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"email-template-editor.js","sourceRoot":"","sources":["../src/email-template-editor.tsx"],"names":[],"mappings":";;;AAmDA,kDA6DC;;AA9GD,iCAAqD;AAErD,oEAAiE;AACjE,yDAA6D;AAC7D,4DAAyD;AACzD,mEAAgE;AAChE,uDAAoD;AAGpD,qEAAkE;AAClE,mDAKyB;AAQZ,QAAA,mBAAmB,GAAG,YAAY,CAAC;AA0BhD,SAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,GACgB;IACzB,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAsB,QAAQ,CAAC,CAAC;IAEhF,MAAM,oBAAoB,GAAG,IAAA,mBAAW,EAAC,CAAC,QAA8B,EAAE,EAAE;QAC1E,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,4BAAY,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,oBAAoB,GAAG,IAAA,mBAAW,EAAC,CAAC,QAAgC,EAAE,EAAE;QAC5E,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,4BAAY,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,6BAA6B,GAAG,IAAA,mBAAW,EAAC,CAAC,SAAmB,EAAE,EAAE;QACxE,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,qCAAqB,EAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1E,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,uBAAuB,GAAG,IAAA,mBAAW,EAAC,CAAC,WAAgC,EAAE,EAAE;QAC/E,eAAe,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAA,+BAAe,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;IACtE,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,aAAa,GAAG,CAAC,GAAG,2BAAmB,MAAM,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1F,OAAO,CACL,gCAAK,SAAS,EAAE,aAAa,iBAAe,GAAG,2BAAmB,MAAM,YACtE,uBAAC,0CAAuB,cACtB,iCACE,SAAS,EAAE,GAAG,2BAAmB,QAAQ,iBAC5B,GAAG,2BAAmB,QAAQ,aAE3C,mCAAO,SAAS,EAAE,GAAG,2BAAmB,SAAS,aAC/C,uBAAC,6BAAa,IACZ,QAAQ,EAAE,YAAY,CAAC,QAAQ,EAC/B,WAAW,EAAE,YAAY,CAAC,WAAW,EACrC,QAAQ,EAAE,oBAAoB,GAC9B,EACF,uBAAC,qCAAiB,IAChB,kBAAkB,EAAE,kBAAkB,EACtC,iBAAiB,EAAE,YAAY,CAAC,QAAQ,CAAC,SAAS,EAClD,yBAAyB,EAAE,6BAA6B,GACxD,EACF,uBAAC,qCAAiB,IAChB,iBAAiB,EAAE,YAAY,CAAC,QAAQ,CAAC,SAAS,EAClD,WAAW,EAAE,YAAY,CAAC,WAAW,EACrC,QAAQ,EAAE,uBAAuB,GACjC,IACI,EACR,iCAAK,SAAS,EAAE,GAAG,2BAAmB,MAAM,aAC1C,uBAAC,uCAAkB,IACjB,QAAQ,EAAE,YAAY,CAAC,YAAY,EACnC,QAAQ,EAAE,oBAAoB,GAC9B,EACF,uBAAC,yBAAW,IAAC,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,GAAI,IACtE,IACF,GACkB,GACtB,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"email-template-editor.js","sourceRoot":"","sources":["../src/email-template-editor.tsx"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,3 +2,5 @@ export { type TemplateSourceFiles, type TemplateVariable, type EmailBuilderDocum
2
2
  export { EDITOR_CLASS_PREFIX, EmailTemplateEditor, type EmailTemplateEditorProps, } from './email-template-editor';
3
3
  export { EmailBuilderCanvas, type EmailBuilderCanvasProps } from './canvas/EmailBuilderCanvas';
4
4
  export { loadTemplateSource, serializeTemplateSource, TemplateSourceError } from './serialization';
5
+ export type { SerializedTemplateSource, SaveResult, SendTestResult } from './save-send/types';
6
+ export { validateTemplate, hasValidationErrors, type ValidationIssue, type ValidationSeverity, type ValidateTemplateOptions, } from './validation/validate';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TemplateSourceError = exports.serializeTemplateSource = exports.loadTemplateSource = exports.EmailBuilderCanvas = exports.EmailTemplateEditor = exports.EDITOR_CLASS_PREFIX = void 0;
3
+ exports.hasValidationErrors = exports.validateTemplate = exports.TemplateSourceError = exports.serializeTemplateSource = exports.loadTemplateSource = exports.EmailBuilderCanvas = exports.EmailTemplateEditor = exports.EDITOR_CLASS_PREFIX = void 0;
4
4
  var email_template_editor_1 = require("./email-template-editor");
5
5
  Object.defineProperty(exports, "EDITOR_CLASS_PREFIX", { enumerable: true, get: function () { return email_template_editor_1.EDITOR_CLASS_PREFIX; } });
6
6
  Object.defineProperty(exports, "EmailTemplateEditor", { enumerable: true, get: function () { return email_template_editor_1.EmailTemplateEditor; } });
@@ -10,4 +10,7 @@ var serialization_1 = require("./serialization");
10
10
  Object.defineProperty(exports, "loadTemplateSource", { enumerable: true, get: function () { return serialization_1.loadTemplateSource; } });
11
11
  Object.defineProperty(exports, "serializeTemplateSource", { enumerable: true, get: function () { return serialization_1.serializeTemplateSource; } });
12
12
  Object.defineProperty(exports, "TemplateSourceError", { enumerable: true, get: function () { return serialization_1.TemplateSourceError; } });
13
+ var validate_1 = require("./validation/validate");
14
+ Object.defineProperty(exports, "validateTemplate", { enumerable: true, get: function () { return validate_1.validateTemplate; } });
15
+ Object.defineProperty(exports, "hasValidationErrors", { enumerable: true, get: function () { return validate_1.hasValidationErrors; } });
13
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAKA,iEAIiC;AAH/B,4HAAA,mBAAmB,OAAA;AACnB,4HAAA,mBAAmB,OAAA;AAGrB,kEAA+F;AAAtF,wHAAA,kBAAkB,OAAA;AAC3B,iDAAmG;AAA1F,mHAAA,kBAAkB,OAAA;AAAE,wHAAA,uBAAuB,OAAA;AAAE,oHAAA,mBAAmB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAKA,iEAIiC;AAH/B,4HAAA,mBAAmB,OAAA;AACnB,4HAAA,mBAAmB,OAAA;AAGrB,kEAA+F;AAAtF,wHAAA,kBAAkB,OAAA;AAC3B,iDAAmG;AAA1F,mHAAA,kBAAkB,OAAA;AAAE,wHAAA,uBAAuB,OAAA;AAAE,oHAAA,mBAAmB,OAAA;AAEzE,kDAM+B;AAL7B,4GAAA,gBAAgB,OAAA;AAChB,+GAAA,mBAAmB,OAAA"}
@@ -1,7 +1,9 @@
1
1
  import type { TemplatePreviewData, TemplateSourceMetadata } from '@singleton-sd/post-kit-types';
2
+ import { type ValidationIssue } from '../validation/validate';
2
3
  export interface MetadataPanelProps {
3
4
  metadata: TemplateSourceMetadata;
4
5
  previewData: TemplatePreviewData;
5
6
  onChange: (metadata: TemplateSourceMetadata) => void;
7
+ issues?: readonly ValidationIssue[];
6
8
  }
7
- export declare function MetadataPanel({ metadata, previewData, onChange, }: MetadataPanelProps): JSX.Element;
9
+ export declare function MetadataPanel({ metadata, previewData, onChange, issues, }: MetadataPanelProps): JSX.Element;
@@ -5,12 +5,24 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const email_template_editor_1 = require("../email-template-editor");
7
7
  const insertion_target_1 = require("../insertion-target");
8
+ const validate_1 = require("../validation/validate");
8
9
  const insert_at_cursor_1 = require("./insert-at-cursor");
9
10
  const subject_preview_1 = require("./subject-preview");
10
11
  const template_key_1 = require("./template-key");
11
- function MetadataPanel({ metadata, previewData, onChange, }) {
12
+ function MetadataPanel({ metadata, previewData, onChange, issues = [], }) {
12
13
  const [keyError, setKeyError] = (0, react_1.useState)(null);
13
14
  const subjectRef = (0, react_1.useRef)(null);
15
+ const keyIssues = issues.filter((i) => i.field === 'metadata' && (i.code === 'missing-key' || i.code === 'invalid-key'));
16
+ const nameIssues = issues.filter((i) => i.field === 'metadata' && i.code === 'missing-name');
17
+ const subjectIssues = issues.filter((i) => i.field === 'subject');
18
+ const keyDescribedBy = [
19
+ keyError ? `${email_template_editor_1.EDITOR_CLASS_PREFIX}meta-key-error` : null,
20
+ ...keyIssues.map((i) => (0, validate_1.inlineIssueId)(i.code)),
21
+ ]
22
+ .filter(Boolean)
23
+ .join(' ');
24
+ const nameDescribedBy = nameIssues.map((i) => (0, validate_1.inlineIssueId)(i.code)).join(' ');
25
+ const subjectDescribedBy = subjectIssues.map((i) => (0, validate_1.inlineIssueId)(i.code, i.variable)).join(' ');
14
26
  const patch = (0, react_1.useCallback)((partial) => {
15
27
  onChange({ ...metadata, ...partial });
16
28
  }, [metadata, onChange]);
@@ -43,7 +55,7 @@ function MetadataPanel({ metadata, previewData, onChange, }) {
43
55
  const subjectFocus = (0, insertion_target_1.useRegisterInsertionTarget)('subject field', insertIntoSubject);
44
56
  const subjectPreview = (0, subject_preview_1.previewSubject)(metadata.subject, previewData);
45
57
  const p = email_template_editor_1.EDITOR_CLASS_PREFIX;
46
- return ((0, jsx_runtime_1.jsxs)("section", { className: `${p}metadata`, "data-testid": `${p}metadata`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}metadata-heading`, children: "Template metadata" }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-key`, children: "Key" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-key`, className: `${p}metadata-input`, type: "text", value: metadata.key, onChange: handleKeyChange, autoComplete: "off", spellCheck: false, "data-testid": `${p}meta-key` }), keyError ? ((0, jsx_runtime_1.jsx)("p", { className: `${p}metadata-error`, "data-testid": `${p}meta-key-error`, role: "status", children: keyError })) : null] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-name`, children: "Name" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-name`, className: `${p}metadata-input`, type: "text", value: metadata.name, onChange: (event) => patch({ name: event.target.value }), "data-testid": `${p}meta-name` })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-description`, children: "Description" }), (0, jsx_runtime_1.jsx)("textarea", { id: `${p}meta-description`, className: `${p}metadata-textarea`, value: metadata.description ?? '', onChange: (event) => {
58
+ return ((0, jsx_runtime_1.jsxs)("section", { className: `${p}metadata`, "data-testid": `${p}metadata`, children: [(0, jsx_runtime_1.jsx)("h2", { className: `${p}metadata-heading`, children: "Template metadata" }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-key`, children: "Key" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-key`, className: `${p}metadata-input`, type: "text", value: metadata.key, onChange: handleKeyChange, autoComplete: "off", spellCheck: false, "data-testid": `${p}meta-key`, "aria-invalid": keyError !== null || keyIssues.length > 0, "aria-describedby": keyDescribedBy || undefined }), keyError ? ((0, jsx_runtime_1.jsx)("p", { id: `${p}meta-key-error`, className: `${p}metadata-error`, "data-testid": `${p}meta-key-error`, role: "status", children: keyError })) : null, keyIssues.map((issue) => ((0, jsx_runtime_1.jsxs)("p", { id: (0, validate_1.inlineIssueId)(issue.code), className: `${p}metadata-error`, "data-testid": `${p}meta-key-validation`, role: "status", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "!" }), " ", issue.message] }, issue.code)))] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-name`, children: "Name" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-name`, className: `${p}metadata-input`, type: "text", value: metadata.name, onChange: (event) => patch({ name: event.target.value }), "data-testid": `${p}meta-name`, "aria-invalid": nameIssues.length > 0, "aria-describedby": nameDescribedBy || undefined }), nameIssues.map((issue) => ((0, jsx_runtime_1.jsxs)("p", { id: (0, validate_1.inlineIssueId)(issue.code), className: `${p}metadata-error`, "data-testid": `${p}meta-name-validation`, role: "status", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "!" }), " ", issue.message] }, issue.code)))] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-description`, children: "Description" }), (0, jsx_runtime_1.jsx)("textarea", { id: `${p}meta-description`, className: `${p}metadata-textarea`, value: metadata.description ?? '', onChange: (event) => {
47
59
  const description = event.target.value;
48
60
  if (description === '') {
49
61
  const { description: _removed, ...rest } = metadata;
@@ -51,6 +63,6 @@ function MetadataPanel({ metadata, previewData, onChange, }) {
51
63
  return;
52
64
  }
53
65
  patch({ description });
54
- }, rows: 3, "data-testid": `${p}meta-description` })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-subject`, children: "Subject" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-subject`, ref: subjectRef, className: `${p}metadata-input`, type: "text", value: metadata.subject, onChange: (event) => patch({ subject: event.target.value }), onFocus: subjectFocus.onFocus, onBlur: subjectFocus.onBlur, "data-testid": `${p}meta-subject` }), (0, jsx_runtime_1.jsxs)("p", { className: `${p}metadata-subject-preview`, "data-testid": `${p}meta-subject-preview`, children: ["Preview: ", subjectPreview] })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("span", { className: `${p}metadata-label`, children: "Schema version" }), (0, jsx_runtime_1.jsx)("span", { className: `${p}metadata-readonly`, "data-testid": `${p}meta-schema-version`, children: metadata.schemaVersion })] })] }));
66
+ }, rows: 3, "data-testid": `${p}meta-description` })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("label", { className: `${p}metadata-label`, htmlFor: `${p}meta-subject`, children: "Subject" }), (0, jsx_runtime_1.jsx)("input", { id: `${p}meta-subject`, ref: subjectRef, className: `${p}metadata-input`, type: "text", value: metadata.subject, onChange: (event) => patch({ subject: event.target.value }), onFocus: subjectFocus.onFocus, onBlur: subjectFocus.onBlur, "data-testid": `${p}meta-subject`, "aria-invalid": subjectIssues.length > 0, "aria-describedby": subjectDescribedBy || undefined }), subjectIssues.map((issue) => ((0, jsx_runtime_1.jsxs)("p", { id: (0, validate_1.inlineIssueId)(issue.code, issue.variable), className: `${p}metadata-error`, "data-testid": `${p}meta-subject-validation`, role: "status", children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", children: "!" }), " ", issue.message] }, `${issue.code}:${issue.variable ?? ''}`))), (0, jsx_runtime_1.jsxs)("p", { className: `${p}metadata-subject-preview`, "data-testid": `${p}meta-subject-preview`, children: ["Preview: ", subjectPreview] })] }), (0, jsx_runtime_1.jsxs)("div", { className: `${p}metadata-field`, children: [(0, jsx_runtime_1.jsx)("span", { className: `${p}metadata-label`, children: "Schema version" }), (0, jsx_runtime_1.jsx)("span", { className: `${p}metadata-readonly`, "data-testid": `${p}meta-schema-version`, children: metadata.schemaVersion })] })] }));
55
67
  }
56
68
  //# sourceMappingURL=MetadataPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MetadataPanel.js","sourceRoot":"","sources":["../../src/metadata/MetadataPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MetadataPanel.js","sourceRoot":"","sources":["../../src/metadata/MetadataPanel.tsx"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import type { TemplatePreviewData } from '@singleton-sd/post-kit-types';
2
+ import { type ValidationIssue } from '../validation/validate';
2
3
  export interface PreviewDataEditorProps {
3
4
  declaredVariables: readonly string[];
4
5
  previewData: TemplatePreviewData;
5
6
  onChange: (previewData: TemplatePreviewData) => void;
7
+ issues?: readonly ValidationIssue[];
6
8
  }
7
- export declare function PreviewDataEditor({ declaredVariables, previewData, onChange, }: PreviewDataEditorProps): JSX.Element;
9
+ export declare function PreviewDataEditor({ declaredVariables, previewData, onChange, issues, }: PreviewDataEditorProps): JSX.Element;