@trycourier/react-designer 0.7.0 → 0.8.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.
- package/README.md +2 -2
- package/dist/cjs/index.js +68 -57
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/styles.css +820 -94
- package/dist/components/Providers/TemplateProvider.d.ts +9 -0
- package/dist/components/Providers/store.d.ts +11 -0
- package/dist/components/TemplateEditor/Channels/Email/Email.d.ts +12 -2
- package/dist/components/TemplateEditor/Channels/Email/EmailLayout.d.ts +3 -1
- package/dist/components/TemplateEditor/Channels/Inbox/InboxLayout.d.ts +1 -1
- package/dist/components/TemplateEditor/Channels/Inbox/SideBar/useInboxButtonSync.d.ts +27 -0
- package/dist/components/TemplateEditor/Channels/MSTeams/MSTeamsLayout.d.ts +1 -1
- package/dist/components/TemplateEditor/Channels/Push/PushLayout.d.ts +1 -1
- package/dist/components/TemplateEditor/Channels/SMS/SMSLayout.d.ts +1 -1
- package/dist/components/TemplateEditor/Channels/Slack/SlackLayout.d.ts +1 -1
- package/dist/components/TemplateEditor/TemplateEditor.d.ts +17 -0
- package/dist/components/TemplateEditor/hooks/index.d.ts +1 -0
- package/dist/components/TemplateEditor/hooks/useEmailBackgroundColors.d.ts +9 -0
- package/dist/components/TemplateEditor/hooks/useEmailFontFamily.d.ts +10 -0
- package/dist/components/TemplateEditor/hooks/useFonts.d.ts +4 -0
- package/dist/components/TemplateEditor/hooks/useGoogleFontLoader.d.ts +5 -0
- package/dist/components/TemplateEditor/index.d.ts +1 -1
- package/dist/components/TemplateEditor/store.d.ts +17 -0
- package/dist/components/TranslationEditor/TranslationEditor.d.ts +17 -0
- package/dist/components/TranslationEditor/index.d.ts +1 -0
- package/dist/components/extensions/Button/Button.types.d.ts +2 -2
- package/dist/components/extensions/Button/inboxButtonStyle.d.ts +65 -0
- package/dist/components/extensions/ButtonRow/ButtonRow.types.d.ts +4 -0
- package/dist/components/extensions/Color/Color.d.ts +14 -0
- package/dist/components/extensions/ColumnCell/ColumnCell.types.d.ts +32 -0
- package/dist/components/extensions/{CustomCode/CustomCodeForm.d.ts → ColumnCell/ColumnCellForm.d.ts} +2 -2
- package/dist/components/extensions/ColumnCell/index.d.ts +2 -0
- package/dist/components/extensions/HTML/HTML.d.ts +11 -0
- package/dist/components/extensions/{CustomCode/CustomCode.types.d.ts → HTML/HTML.types.d.ts} +2 -2
- package/dist/components/extensions/HTML/HTMLComponent.d.ts +9 -0
- package/dist/components/extensions/HTML/HTMLForm.d.ts +9 -0
- package/dist/components/extensions/HTML/index.d.ts +6 -0
- package/dist/components/extensions/Link/LinkBubble.d.ts +1 -0
- package/dist/components/extensions/List/List.types.d.ts +5 -0
- package/dist/components/extensions/index.d.ts +3 -2
- package/dist/components/extensions/shared/conditionalAttribute.d.ts +19 -0
- package/dist/components/hooks/useVariables.d.ts +12 -7
- package/dist/components/ui/Blocks/HTMLBlock/HTMLBlock.d.ts +3 -0
- package/dist/components/ui/Blocks/HTMLBlock/index.d.ts +1 -0
- package/dist/components/ui/Blocks/index.d.ts +1 -1
- package/dist/components/ui/Conditions/ConditionGroupRow.d.ts +12 -0
- package/dist/components/ui/Conditions/ConditionRow.d.ts +11 -0
- package/dist/components/ui/Conditions/Conditions.d.ts +9 -0
- package/dist/components/ui/Conditions/ConditionsSection.d.ts +18 -0
- package/dist/components/ui/Conditions/index.d.ts +3 -0
- package/dist/components/ui/Conditions/useConditions.d.ts +13 -0
- package/dist/components/ui/ContentIcon/ContentIcon.d.ts +1 -1
- package/dist/components/ui/MainLayout/MainLayout.d.ts +1 -0
- package/dist/components/ui/TextMenu/components/TextColorButton.d.ts +6 -0
- package/dist/components/ui/TextMenu/config.d.ts +1 -0
- package/dist/components/ui/TextMenu/hooks/useTextmenuCommands.d.ts +2 -0
- package/dist/components/ui/TextMenu/hooks/useTextmenuStates.d.ts +1 -0
- package/dist/components/ui/Tooltip/types.d.ts +1 -1
- package/dist/components/ui/VariableEditor/VariableChipBase.d.ts +2 -0
- package/dist/components/ui-kit/Button/Button.d.ts +2 -2
- package/dist/components/ui-kit/FontSelect/FontSelect.d.ts +9 -0
- package/dist/components/ui-kit/FontSelect/index.d.ts +1 -0
- package/dist/components/ui-kit/Form/Form.d.ts +2 -1
- package/dist/components/ui-kit/InputColor/ColorPicker.d.ts +2 -1
- package/dist/components/ui-kit/InputColor/InputColor.d.ts +4 -1
- package/dist/components/ui-kit/PrefixInput/PrefixInput.d.ts +30 -0
- package/dist/components/ui-kit/PrefixInput/index.d.ts +2 -0
- package/dist/components/ui-kit/index.d.ts +2 -0
- package/dist/components/utils/resolveDataPath.d.ts +13 -0
- package/dist/components/utils/validateVariableName.d.ts +5 -2
- package/dist/esm/index.js +68 -57
- package/dist/esm/index.js.map +4 -4
- package/dist/esm/styles.css +820 -94
- package/dist/hooks/useLocalization.d.ts +30 -0
- package/dist/index.d.ts +16 -4
- package/dist/lib/utils/brandColors.d.ts +15 -0
- package/dist/lib/utils/extractTextFields.d.ts +60 -0
- package/dist/lib/utils/fontFamily.d.ts +23 -0
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/styles.css +820 -94
- package/dist/types/conditions.types.d.ts +21 -0
- package/dist/types/elemental.types.d.ts +67 -2
- package/dist/types/font.types.d.ts +8 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/validation.types.d.ts +15 -3
- package/package.json +6 -1
- package/dist/components/extensions/CustomCode/CustomCode.d.ts +0 -11
- package/dist/components/extensions/CustomCode/CustomCodeComponent.d.ts +0 -9
- package/dist/components/extensions/CustomCode/index.d.ts +0 -6
- package/dist/components/ui/Blocks/CustomCodeBlock/CustomCodeBlock.d.ts +0 -3
- package/dist/components/ui/Blocks/CustomCodeBlock/index.d.ts +0 -1
- /package/dist/components/extensions/{CustomCode → HTML}/MonacoCodeEditor.d.ts +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ElementalConditionOperator = "equals" | "not_equals" | "greater_than" | "less_than" | "greater_than_or_equals" | "less_than_or_equals" | "contains" | "not_contains" | "is_empty" | "is_not_empty";
|
|
2
|
+
export interface ElementalCondition {
|
|
3
|
+
property: string;
|
|
4
|
+
operator: ElementalConditionOperator;
|
|
5
|
+
value?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ElementalConditionGroup {
|
|
8
|
+
conditions: ElementalCondition[];
|
|
9
|
+
logical_operator: "and" | "or";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Structured condition format for the Elemental `if` field.
|
|
13
|
+
* An array of condition groups, evaluated with OR logic between groups.
|
|
14
|
+
* Within each group, conditions are joined by the group's `logical_operator`.
|
|
15
|
+
*/
|
|
16
|
+
export type ElementalConditionExpression = ElementalConditionGroup[];
|
|
17
|
+
/** Union type for the `if` field: legacy string expression or structured conditions. */
|
|
18
|
+
export type ElementalIfCondition = string | ElementalConditionExpression;
|
|
19
|
+
/** Operators that don't require a value (unary checks). */
|
|
20
|
+
export declare const UNARY_OPERATORS: ElementalConditionOperator[];
|
|
21
|
+
export declare const OPERATOR_LABELS: Record<ElementalConditionOperator, string>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ElementalConditionExpression } from "./conditions.types";
|
|
1
2
|
export type Align = "left" | "center" | "right" | "full";
|
|
2
3
|
export type IActionButtonStyle = "button" | "link";
|
|
3
4
|
export type TextStyle = "text" | "h1" | "h2" | "h3" | "subtext";
|
|
@@ -17,7 +18,7 @@ export interface ElementalContent {
|
|
|
17
18
|
version: "2022-01-01";
|
|
18
19
|
elements: ElementalNode[];
|
|
19
20
|
}
|
|
20
|
-
export type ElementalNode = ElementalTextNode | ElementalMetaNode | ElementalChannelNode | ElementalImageNode | ElementalActionNode | ElementalDividerNode | ElementalGroupNode | ElementalQuoteNode | ElementalHtmlNode | ElementalCommentNode | ElementalTextContentNode | ElementalListNode | ElementalListItemNode;
|
|
21
|
+
export type ElementalNode = ElementalTextNode | ElementalMetaNode | ElementalChannelNode | ElementalImageNode | ElementalActionNode | ElementalDividerNode | ElementalGroupNode | ElementalColumnsNode | ElementalColumnNode | ElementalQuoteNode | ElementalHtmlNode | ElementalCommentNode | ElementalTextContentNode | ElementalListNode | ElementalListItemNode;
|
|
21
22
|
export interface ElementalListNode extends IsElementalNode {
|
|
22
23
|
type: "list";
|
|
23
24
|
list_type: "ordered" | "unordered";
|
|
@@ -32,6 +33,11 @@ export interface ElementalListItemNode extends IsElementalNode {
|
|
|
32
33
|
type: "list-item";
|
|
33
34
|
background_color?: string;
|
|
34
35
|
elements: (ElementalTextContentNode | ElementalListNode)[];
|
|
36
|
+
locales?: ElementalLocales<{
|
|
37
|
+
content?: string;
|
|
38
|
+
elements?: ElementalTextContentNode[];
|
|
39
|
+
_sourceHash?: string;
|
|
40
|
+
}>;
|
|
35
41
|
}
|
|
36
42
|
export type ElementalTextNode = ElementalTextNodeWithContent | ElementalTextNodeWithElements;
|
|
37
43
|
export interface ElementalTextNodeWithElements extends IsElementalTextNode {
|
|
@@ -100,6 +106,9 @@ export interface ElementalChannelNode extends IsElementalNode {
|
|
|
100
106
|
type: "channel";
|
|
101
107
|
channel: string;
|
|
102
108
|
elements?: ElementalNode[];
|
|
109
|
+
background_color?: string;
|
|
110
|
+
content_body_color?: string;
|
|
111
|
+
font_family?: string;
|
|
103
112
|
raw?: {
|
|
104
113
|
html?: string;
|
|
105
114
|
transformers?: string[];
|
|
@@ -193,6 +202,62 @@ export interface ElementalGroupNode extends IsElementalNode {
|
|
|
193
202
|
elements?: ElementalNode[];
|
|
194
203
|
}>;
|
|
195
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Represents a columns container node that arranges child column elements horizontally.
|
|
207
|
+
* Used to create multi-column layouts in email templates.
|
|
208
|
+
*/
|
|
209
|
+
export interface ElementalColumnsNode extends IsElementalNode {
|
|
210
|
+
/** Node type identifier */
|
|
211
|
+
type: "columns";
|
|
212
|
+
/** Array of column elements to be arranged horizontally */
|
|
213
|
+
elements: ElementalColumnNode[];
|
|
214
|
+
/** Background color for the columns container (e.g., "#ffffff", "transparent") */
|
|
215
|
+
background_color?: string;
|
|
216
|
+
/** Border color for the columns container (e.g., "#000000") */
|
|
217
|
+
border_color?: string;
|
|
218
|
+
/** Border radius for the columns container (e.g., "8px") */
|
|
219
|
+
border_radius?: string;
|
|
220
|
+
/** Border width for the columns container (e.g., "2px") */
|
|
221
|
+
border_width?: string;
|
|
222
|
+
/** Gap/spacing between columns (e.g., "10px") */
|
|
223
|
+
gap?: string;
|
|
224
|
+
/** Padding for the columns container (e.g., "10px 20px") */
|
|
225
|
+
padding?: string;
|
|
226
|
+
/** Vertical alignment of columns within the container */
|
|
227
|
+
vertical_align?: "top" | "middle" | "bottom";
|
|
228
|
+
/** Locale-specific overrides for elements */
|
|
229
|
+
locales?: ElementalLocales<{
|
|
230
|
+
elements?: ElementalColumnNode[];
|
|
231
|
+
}>;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Represents a single column within a columns container.
|
|
235
|
+
* Contains elements that will be stacked vertically within the column.
|
|
236
|
+
*/
|
|
237
|
+
export interface ElementalColumnNode extends IsElementalNode {
|
|
238
|
+
/** Node type identifier */
|
|
239
|
+
type: "column";
|
|
240
|
+
/** Array of elements to be stacked vertically within this column */
|
|
241
|
+
elements: ElementalNode[];
|
|
242
|
+
/** Background color for the column (e.g., "#ffffff", "transparent") */
|
|
243
|
+
background_color?: string;
|
|
244
|
+
/** Border color for the column (e.g., "#000000") */
|
|
245
|
+
border_color?: string;
|
|
246
|
+
/** Border radius for the column (e.g., "8px") */
|
|
247
|
+
border_radius?: string;
|
|
248
|
+
/** Border width for the column (e.g., "2px") */
|
|
249
|
+
border_width?: string;
|
|
250
|
+
/** Internal padding for the column content (e.g., "10px", "10px 20px") */
|
|
251
|
+
padding?: string;
|
|
252
|
+
/** Vertical alignment of content within this column */
|
|
253
|
+
vertical_align?: "top" | "middle" | "bottom";
|
|
254
|
+
/** Column width (e.g., "50%", "200px", "auto") */
|
|
255
|
+
width?: string;
|
|
256
|
+
/** Locale-specific overrides for elements */
|
|
257
|
+
locales?: ElementalLocales<{
|
|
258
|
+
elements?: ElementalNode[];
|
|
259
|
+
}>;
|
|
260
|
+
}
|
|
196
261
|
export interface ElementalQuoteNode extends IsElementalNode {
|
|
197
262
|
type: "quote";
|
|
198
263
|
content: string;
|
|
@@ -223,7 +288,7 @@ interface IsElementalNode {
|
|
|
223
288
|
type: string;
|
|
224
289
|
channels?: string[];
|
|
225
290
|
ref?: string;
|
|
226
|
-
if?: string;
|
|
291
|
+
if?: string | ElementalConditionExpression;
|
|
227
292
|
loop?: string;
|
|
228
293
|
data?: Record<string, unknown>;
|
|
229
294
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context about where a variable chip is positioned in the document tree.
|
|
3
|
+
* Passed to the validate function so consumers can make context-aware decisions.
|
|
4
|
+
*/
|
|
5
|
+
export interface VariableValidationContext {
|
|
6
|
+
/** Whether the variable is inside a list node that has a loop configured */
|
|
7
|
+
isInsideLoop: boolean;
|
|
8
|
+
}
|
|
1
9
|
/**
|
|
2
10
|
* Configuration for custom variable validation in the editor.
|
|
3
11
|
* Allows consumers to restrict which variable names are allowed and
|
|
@@ -9,15 +17,19 @@ export interface VariableValidationConfig {
|
|
|
9
17
|
* (unless `overrideFormatValidation` is true).
|
|
10
18
|
*
|
|
11
19
|
* @param variableName - The variable name to validate (without curly braces)
|
|
20
|
+
* @param context - Positional context about where the variable chip lives
|
|
12
21
|
* @returns true if the variable is allowed, false otherwise
|
|
13
22
|
*
|
|
14
23
|
* @example
|
|
15
24
|
* ```tsx
|
|
16
|
-
* //
|
|
17
|
-
* validate: (name) =>
|
|
25
|
+
* // Allow $.item.* only inside loops
|
|
26
|
+
* validate: (name, ctx) => {
|
|
27
|
+
* if (name.startsWith('$.')) return ctx?.isInsideLoop ?? false;
|
|
28
|
+
* return allowedPrefixes.some(p => name.startsWith(p));
|
|
29
|
+
* }
|
|
18
30
|
* ```
|
|
19
31
|
*/
|
|
20
|
-
validate?: (variableName: string) => boolean;
|
|
32
|
+
validate?: (variableName: string, context?: VariableValidationContext) => boolean;
|
|
21
33
|
/**
|
|
22
34
|
* Behavior when validation fails.
|
|
23
35
|
* - 'mark': Keep the chip with invalid styling (default, shows red styling)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trycourier/react-designer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "React-based rich text designer component",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -86,7 +86,9 @@
|
|
|
86
86
|
"@testing-library/jest-dom": "^6.0.0",
|
|
87
87
|
"@testing-library/react": "^14.0.0",
|
|
88
88
|
"@testing-library/user-event": "^14.0.0",
|
|
89
|
+
"@tiptap/extension-text-style": "^2.11.5",
|
|
89
90
|
"@types/node": "^20.0.0",
|
|
91
|
+
"@types/pngjs": "^6.0.5",
|
|
90
92
|
"@types/react": "^18.2.0",
|
|
91
93
|
"@types/react-dom": "^18.0.0",
|
|
92
94
|
"@vitejs/plugin-react": "^4.0.0",
|
|
@@ -98,6 +100,8 @@
|
|
|
98
100
|
"esbuild-style-plugin": "^1.6.3",
|
|
99
101
|
"jsdom": "^22.1.0",
|
|
100
102
|
"nyc": "^17.1.0",
|
|
103
|
+
"pixelmatch": "^7.1.0",
|
|
104
|
+
"pngjs": "^7.0.0",
|
|
101
105
|
"postcss": "^8.4.49",
|
|
102
106
|
"postcss-import": "^16.1.0",
|
|
103
107
|
"postcss-nested": "^7.0.2",
|
|
@@ -152,6 +156,7 @@
|
|
|
152
156
|
"test:coverage:watch": "vitest --coverage",
|
|
153
157
|
"test:e2e": "playwright test --workers=4",
|
|
154
158
|
"test:e2e:fullcycle": "playwright test --config=playwright.fullcycle.config.ts",
|
|
159
|
+
"test:e2e:fullcycle:update-snapshots": "playwright test --config=playwright.fullcycle.config.ts --update-snapshots",
|
|
155
160
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
156
161
|
"analyze": "node build.js --analyze",
|
|
157
162
|
"release": "node scripts/publish.js",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Node } from "@tiptap/core";
|
|
2
|
-
import type { CustomCodeProps } from "./CustomCode.types";
|
|
3
|
-
declare module "@tiptap/core" {
|
|
4
|
-
interface Commands<ReturnType> {
|
|
5
|
-
customCode: {
|
|
6
|
-
setCustomCode: (props: Partial<CustomCodeProps>) => ReturnType;
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
export declare const defaultCustomCodeProps: CustomCodeProps;
|
|
11
|
-
export declare const CustomCode: Node<any, any>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type NodeViewProps } from "@tiptap/react";
|
|
2
|
-
import React from "react";
|
|
3
|
-
import type { CustomCodeProps } from "./CustomCode.types";
|
|
4
|
-
export declare const CustomCodeComponent: React.FC<CustomCodeProps & {
|
|
5
|
-
nodeKey?: string;
|
|
6
|
-
selected?: boolean;
|
|
7
|
-
updateAttributes?: (attrs: Partial<CustomCodeProps>) => void;
|
|
8
|
-
}>;
|
|
9
|
-
export declare const CustomCodeComponentNode: (props: NodeViewProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { CustomCode, defaultCustomCodeProps } from "./CustomCode";
|
|
2
|
-
export { CustomCodeComponent, CustomCodeComponentNode } from "./CustomCodeComponent";
|
|
3
|
-
export { MonacoCodeEditor } from "./MonacoCodeEditor";
|
|
4
|
-
export { CustomCodeForm } from "./CustomCodeForm";
|
|
5
|
-
export type { CustomCodeProps } from "./CustomCode.types";
|
|
6
|
-
export { customCodeSchema } from "./CustomCode.types";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./CustomCodeBlock";
|
|
File without changes
|