@cometchat/card-builder 1.0.1
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 +73 -0
- package/dist/App.d.ts +1 -0
- package/dist/bridge/api.d.ts +79 -0
- package/dist/bubble-builder.es.js +24009 -0
- package/dist/bubble-builder.umd.js +20 -0
- package/dist/card-builder.css +2 -0
- package/dist/components/Canvas.d.ts +2 -0
- package/dist/components/CanvasViewToggle.d.ts +6 -0
- package/dist/components/CredentialsModal.d.ts +11 -0
- package/dist/components/EditorLayout.d.ts +2 -0
- package/dist/components/ElementTree.d.ts +2 -0
- package/dist/components/LeftPanel.d.ts +2 -0
- package/dist/components/NotificationPreview.d.ts +3 -0
- package/dist/components/RightPanel.d.ts +2 -0
- package/dist/components/ShortcutsPanel.d.ts +2 -0
- package/dist/components/TemplateLibrary.d.ts +2 -0
- package/dist/components/TopBar.d.ts +2 -0
- package/dist/components/properties/ActionEditor.d.ts +7 -0
- package/dist/components/properties/CardStyleEditor.d.ts +2 -0
- package/dist/components/properties/ElementPropertyEditor.d.ts +8 -0
- package/dist/components/properties/IconPicker.d.ts +7 -0
- package/dist/components/properties/NotificationEditor.d.ts +2 -0
- package/dist/components/properties/VariableEditor.d.ts +2 -0
- package/dist/components/properties/VariableInput.d.ts +10 -0
- package/dist/components/renderers/ElementRenderer.d.ts +20 -0
- package/dist/components/ui/Button.d.ts +8 -0
- package/dist/components/ui/ColorPicker.d.ts +30 -0
- package/dist/components/ui/EmptyState.d.ts +7 -0
- package/dist/components/ui/MaterialIcon.d.ts +9 -0
- package/dist/components/ui/Modal.d.ts +11 -0
- package/dist/config/app-credentials.d.ts +39 -0
- package/dist/config/builder-config.d.ts +56 -0
- package/dist/config/component-templates.d.ts +11 -0
- package/dist/config/element-defaults.d.ts +8 -0
- package/dist/config/icon-library.d.ts +11 -0
- package/dist/config/theme.d.ts +11 -0
- package/dist/config/uikit-theme.d.ts +73 -0
- package/dist/favicon.svg +1 -0
- package/dist/hooks/useKeyboardShortcuts.d.ts +1 -0
- package/dist/icons.svg +24 -0
- package/dist/lib.d.ts +81 -0
- package/dist/store/builder-store.d.ts +127 -0
- package/dist/types/schema.d.ts +338 -0
- package/dist/utils/element-errors.d.ts +9 -0
- package/dist/utils/id.d.ts +4 -0
- package/dist/utils/portal-root.d.ts +2 -0
- package/dist/utils/validate.d.ts +6 -0
- package/package.json +54 -0
package/dist/lib.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { CardMessage, ElementType } from './types/schema';
|
|
2
|
+
import type { ComponentTemplateName } from './config/component-templates';
|
|
3
|
+
import type { CardVariable, NotificationConfig, BuilderChannels } from './config/builder-config';
|
|
4
|
+
import './index.css';
|
|
5
|
+
export type { CardVariable } from './config/builder-config';
|
|
6
|
+
export type { NotificationConfig, BuilderChannels } from './config/builder-config';
|
|
7
|
+
export interface CardBuilderOptions {
|
|
8
|
+
/** CometChat app ID (required for template save/load APIs) */
|
|
9
|
+
appId?: string;
|
|
10
|
+
/** App region — us, eu, etc. (required for template save/load APIs) */
|
|
11
|
+
region?: string;
|
|
12
|
+
/** Bearer token for REST API calls (required for template save/load APIs) */
|
|
13
|
+
token?: string;
|
|
14
|
+
/** CometChat REST API Key (required for sending messages) */
|
|
15
|
+
apiKey?: string;
|
|
16
|
+
/** Existing card JSON to load for editing */
|
|
17
|
+
card?: CardMessage;
|
|
18
|
+
/** Initial notification title (only used when channels includes push). */
|
|
19
|
+
notificationTitle?: string;
|
|
20
|
+
/** Initial notification body (only used when channels includes push). */
|
|
21
|
+
notificationBody?: string;
|
|
22
|
+
/** Template name */
|
|
23
|
+
templateName?: string;
|
|
24
|
+
/** Called when user clicks Save */
|
|
25
|
+
onSave?: (json: CardMessage, name: string, description: string) => void;
|
|
26
|
+
/** Called whenever the card JSON changes (any edit). Use for real-time sync. */
|
|
27
|
+
onChange?: (json: CardMessage) => void;
|
|
28
|
+
/** Available variables for {{placeholder}} insertion in text/URL fields */
|
|
29
|
+
variables?: CardVariable[];
|
|
30
|
+
/** Hide the top toolbar (save, export, import, undo/redo, template name). Default: false */
|
|
31
|
+
hideTopBar?: boolean;
|
|
32
|
+
/** Hide the template library view — go straight to editor. Default: false */
|
|
33
|
+
hideTemplateLibrary?: boolean;
|
|
34
|
+
/** Disable all editing interactions — read-only preview mode. Default: false */
|
|
35
|
+
readOnly?: boolean;
|
|
36
|
+
/** Show the variable editor tab for creating/managing variables in the builder. Default: true */
|
|
37
|
+
enableVariableEditor?: boolean;
|
|
38
|
+
/** Which channels to show: 'inapp', 'push', or 'both' (default). */
|
|
39
|
+
channels?: BuilderChannels;
|
|
40
|
+
/** Push notification preview config (app name, icon). Only used when channels is 'push' or 'both'. */
|
|
41
|
+
notification?: NotificationConfig;
|
|
42
|
+
/** Element types to hide from the palette (e.g. ['codeBlock', 'table', 'markdown']) */
|
|
43
|
+
hiddenElements?: ElementType[];
|
|
44
|
+
/** Component template names to hide from the palette (e.g. ['Product Card', 'Data Table']) */
|
|
45
|
+
hiddenComponents?: ComponentTemplateName[];
|
|
46
|
+
/** Hide the left panel (elements & components palette). Default: false */
|
|
47
|
+
hideElementPalette?: boolean;
|
|
48
|
+
/** Hide the right panel (tree, element properties, card settings). Default: false */
|
|
49
|
+
hidePropertyPanel?: boolean;
|
|
50
|
+
/** Show the canvas toolbar (zoom, dark mode, preview, JSON). Default: false */
|
|
51
|
+
showCanvasToolbar?: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface CardBuilderInstance {
|
|
54
|
+
loadCard: (card: CardMessage, name?: string) => void;
|
|
55
|
+
getCardJSON: () => CardMessage;
|
|
56
|
+
setVariables: (variables: CardVariable[]) => void;
|
|
57
|
+
setChannels: (channels: BuilderChannels) => void;
|
|
58
|
+
setCanvasView: (view: 'card' | 'notification') => void;
|
|
59
|
+
setReadOnly: (readOnly: boolean) => void;
|
|
60
|
+
/** Hide specific element types from the palette. Pass element type names (e.g. 'codeBlock', 'table'). */
|
|
61
|
+
setHiddenElements: (types: ElementType[]) => void;
|
|
62
|
+
/** Hide specific component templates from the palette. Pass template names (e.g. 'Product Card'). */
|
|
63
|
+
setHiddenComponents: (names: ComponentTemplateName[]) => void;
|
|
64
|
+
/** Show or hide the left panel at runtime. */
|
|
65
|
+
setHideElementPalette: (hide: boolean) => void;
|
|
66
|
+
/** Show or hide the right panel at runtime. */
|
|
67
|
+
setHidePropertyPanel: (hide: boolean) => void;
|
|
68
|
+
/** Show or hide the canvas toolbar at runtime. */
|
|
69
|
+
setShowCanvasToolbar: (show: boolean) => void;
|
|
70
|
+
/** Set notification title at runtime. */
|
|
71
|
+
setNotificationTitle: (title: string) => void;
|
|
72
|
+
/** Set notification body at runtime. */
|
|
73
|
+
setNotificationBody: (body: string) => void;
|
|
74
|
+
/** Set API key at runtime. */
|
|
75
|
+
setApiKey: (apiKey: string) => void;
|
|
76
|
+
destroy: () => void;
|
|
77
|
+
}
|
|
78
|
+
export { builderConfig } from './config/builder-config';
|
|
79
|
+
export declare function mountCardBuilder(container: HTMLElement, options: CardBuilderOptions): CardBuilderInstance;
|
|
80
|
+
export type { CardMessage, ElementType } from './types/schema';
|
|
81
|
+
export type { ComponentTemplateName } from './config/component-templates';
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { CardElement, CardStyle, CardMessage, Template, ElementType, MessageData } from '../types/schema';
|
|
2
|
+
import type { ComponentTemplateName } from '../config/component-templates';
|
|
3
|
+
import { type CardVariable } from '../config/builder-config';
|
|
4
|
+
export interface BuilderState {
|
|
5
|
+
templateId: string | null;
|
|
6
|
+
templateName: string;
|
|
7
|
+
templateDescription: string;
|
|
8
|
+
body: CardElement[];
|
|
9
|
+
style: CardStyle;
|
|
10
|
+
fallbackText: string;
|
|
11
|
+
notificationTitle: string;
|
|
12
|
+
notificationBody: string;
|
|
13
|
+
notificationData: Array<{
|
|
14
|
+
key: string;
|
|
15
|
+
value: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Custom message type for CometChat message structure (e.g. 'product', 'order') */
|
|
18
|
+
messageType: string;
|
|
19
|
+
notificationEnabled: boolean;
|
|
20
|
+
/** Which view the canvas shows: card editor or notification preview */
|
|
21
|
+
canvasView: 'card' | 'notification';
|
|
22
|
+
/** Which channels are available */
|
|
23
|
+
channels: 'inapp' | 'push' | 'both';
|
|
24
|
+
/** Whether channels was explicitly set (vs default) */
|
|
25
|
+
channelsExplicit: boolean;
|
|
26
|
+
/** Read-only mode — disables all editing interactions */
|
|
27
|
+
readOnly: boolean;
|
|
28
|
+
selectedPath: number[] | null;
|
|
29
|
+
selectedPaths: number[][];
|
|
30
|
+
isDirty: boolean;
|
|
31
|
+
useThemePlaceholders: boolean;
|
|
32
|
+
/** Element types hidden from the palette */
|
|
33
|
+
hiddenElements: Set<ElementType>;
|
|
34
|
+
/** Component template names hidden from the palette */
|
|
35
|
+
hiddenComponents: Set<ComponentTemplateName>;
|
|
36
|
+
view: 'library' | 'editor';
|
|
37
|
+
clipboard: CardElement | null;
|
|
38
|
+
showTemplatePicker: boolean;
|
|
39
|
+
/** Hide the left panel (elements & components palette) */
|
|
40
|
+
hideElementPalette: boolean;
|
|
41
|
+
/** Hide the right panel (tree, element properties, card settings) */
|
|
42
|
+
hidePropertyPanel: boolean;
|
|
43
|
+
/** Show the canvas toolbar (zoom, dark mode, preview, JSON). Default: false */
|
|
44
|
+
showCanvasToolbar: boolean;
|
|
45
|
+
/** Show the variable editor tab. Default: true */
|
|
46
|
+
enableVariableEditor: boolean;
|
|
47
|
+
variables: CardVariable[];
|
|
48
|
+
history: {
|
|
49
|
+
body: CardElement[];
|
|
50
|
+
style: CardStyle;
|
|
51
|
+
}[];
|
|
52
|
+
historyIndex: number;
|
|
53
|
+
templates: Template[];
|
|
54
|
+
templatesLoading: boolean;
|
|
55
|
+
templatesMeta: {
|
|
56
|
+
previous?: {
|
|
57
|
+
affix: string;
|
|
58
|
+
createdAt: number;
|
|
59
|
+
};
|
|
60
|
+
next?: {
|
|
61
|
+
affix: string;
|
|
62
|
+
createdAt: number;
|
|
63
|
+
};
|
|
64
|
+
} | null;
|
|
65
|
+
setView: (view: 'library' | 'editor') => void;
|
|
66
|
+
setShowTemplatePicker: (show: boolean) => void;
|
|
67
|
+
setHideElementPalette: (hide: boolean) => void;
|
|
68
|
+
setHidePropertyPanel: (hide: boolean) => void;
|
|
69
|
+
setShowCanvasToolbar: (show: boolean) => void;
|
|
70
|
+
setEnableVariableEditor: (enable: boolean) => void;
|
|
71
|
+
selectElement: (path: number[] | null) => void;
|
|
72
|
+
toggleSelectElement: (path: number[]) => void;
|
|
73
|
+
addElement: (element: CardElement, parentPath?: number[]) => void;
|
|
74
|
+
updateElement: (path: number[], updates: Partial<CardElement>) => void;
|
|
75
|
+
removeElement: (path: number[]) => void;
|
|
76
|
+
moveElement: (path: number[], direction: 'up' | 'down') => void;
|
|
77
|
+
updateStyle: (settings: Partial<CardStyle>) => void;
|
|
78
|
+
setFallbackText: (text: string) => void;
|
|
79
|
+
setNotificationTitle: (text: string) => void;
|
|
80
|
+
setNotificationBody: (text: string) => void;
|
|
81
|
+
setMessageType: (type: string) => void;
|
|
82
|
+
setNotificationData: (data: Array<{
|
|
83
|
+
key: string;
|
|
84
|
+
value: string;
|
|
85
|
+
}>) => void;
|
|
86
|
+
setNotificationEnabled: (enabled: boolean) => void;
|
|
87
|
+
setCanvasView: (view: 'card' | 'notification') => void;
|
|
88
|
+
setChannels: (channels: 'inapp' | 'push' | 'both') => void;
|
|
89
|
+
setReadOnly: (readOnly: boolean) => void;
|
|
90
|
+
setHiddenElements: (types: ElementType[]) => void;
|
|
91
|
+
setHiddenComponents: (names: ComponentTemplateName[]) => void;
|
|
92
|
+
setUseThemePlaceholders: (use: boolean) => void;
|
|
93
|
+
setVariables: (variables: CardVariable[]) => void;
|
|
94
|
+
addVariable: (variable: CardVariable) => void;
|
|
95
|
+
updateVariable: (index: number, variable: CardVariable) => void;
|
|
96
|
+
removeVariable: (index: number) => void;
|
|
97
|
+
setTemplateName: (name: string) => void;
|
|
98
|
+
setTemplateDescription: (desc: string) => void;
|
|
99
|
+
loadCard: (card: CardMessage, templateId?: string, name?: string, desc?: string) => void;
|
|
100
|
+
loadTemplate: (template: Template) => void;
|
|
101
|
+
newCard: () => void;
|
|
102
|
+
getCardJSON: (opts?: {
|
|
103
|
+
stripEmpty?: boolean;
|
|
104
|
+
}) => CardMessage;
|
|
105
|
+
/** Get the full CometChat message structure wrapping the card (used when channels not set) */
|
|
106
|
+
getMessageJSON: () => MessageData;
|
|
107
|
+
setTemplates: (templates: Template[]) => void;
|
|
108
|
+
fetchTemplates: (search?: string) => Promise<void>;
|
|
109
|
+
fetchNextPage: () => Promise<void>;
|
|
110
|
+
fetchPrevPage: () => Promise<void>;
|
|
111
|
+
saveTemplate: () => Promise<void>;
|
|
112
|
+
deleteTemplate: (id: string) => Promise<void>;
|
|
113
|
+
reorderElement: (fromPath: number[], toPath: number[], toIndex: number) => void;
|
|
114
|
+
moveElementToPath: (fromPath: number[], toParentPath: number[], toIndex: number) => void;
|
|
115
|
+
wrapElement: (path: number[], wrapperType: 'row' | 'column' | 'grid') => void;
|
|
116
|
+
unwrapElement: (path: number[]) => void;
|
|
117
|
+
wrapSelected: (wrapperType: 'row' | 'column' | 'grid') => void;
|
|
118
|
+
duplicateElement: (path: number[]) => void;
|
|
119
|
+
copyElement: (path: number[]) => void;
|
|
120
|
+
pasteElement: (targetPath?: number[]) => void;
|
|
121
|
+
undo: () => void;
|
|
122
|
+
redo: () => void;
|
|
123
|
+
canUndo: () => boolean;
|
|
124
|
+
canRedo: () => boolean;
|
|
125
|
+
clearAll: () => void;
|
|
126
|
+
}
|
|
127
|
+
export declare const useBuilderStore: import("zustand").UseBoundStore<import("zustand").StoreApi<BuilderState>>;
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
export type Padding = number | {
|
|
2
|
+
top?: number;
|
|
3
|
+
right?: number;
|
|
4
|
+
bottom?: number;
|
|
5
|
+
left?: number;
|
|
6
|
+
};
|
|
7
|
+
export type SizeOrPercentage = number | string;
|
|
8
|
+
export type ColorValue = {
|
|
9
|
+
light: string;
|
|
10
|
+
dark: string;
|
|
11
|
+
} | 'transparent';
|
|
12
|
+
/** Resolve a ColorValue to a hex string for the given mode. Returns 'transparent' for "transparent". */
|
|
13
|
+
export declare function resolveColor(cv: ColorValue | undefined, mode?: 'light' | 'dark'): string | undefined;
|
|
14
|
+
/** Create a ColorValue from a single hex (same for both modes). */
|
|
15
|
+
export declare function colorVal(hex: string): ColorValue;
|
|
16
|
+
/** Create a ColorValue with distinct light/dark values. */
|
|
17
|
+
export declare function colorValLD(light?: string, dark?: string): ColorValue;
|
|
18
|
+
export interface OpenUrlAction {
|
|
19
|
+
type: 'openUrl';
|
|
20
|
+
url: string;
|
|
21
|
+
openIn?: 'browser' | 'webview';
|
|
22
|
+
}
|
|
23
|
+
export interface ChatWithUserAction {
|
|
24
|
+
type: 'chatWithUser';
|
|
25
|
+
uid: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ChatWithGroupAction {
|
|
28
|
+
type: 'chatWithGroup';
|
|
29
|
+
guid: string;
|
|
30
|
+
}
|
|
31
|
+
export interface SendMessageAction {
|
|
32
|
+
type: 'sendMessage';
|
|
33
|
+
text: string;
|
|
34
|
+
receiverUid?: string;
|
|
35
|
+
receiverGuid?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface CopyToClipboardAction {
|
|
38
|
+
type: 'copyToClipboard';
|
|
39
|
+
value: string;
|
|
40
|
+
}
|
|
41
|
+
export interface DownloadFileAction {
|
|
42
|
+
type: 'downloadFile';
|
|
43
|
+
url: string;
|
|
44
|
+
filename?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface InitiateCallAction {
|
|
47
|
+
type: 'initiateCall';
|
|
48
|
+
uid?: string;
|
|
49
|
+
guid?: string;
|
|
50
|
+
callType: 'audio' | 'video';
|
|
51
|
+
}
|
|
52
|
+
export interface ApiCallAction {
|
|
53
|
+
type: 'apiCall';
|
|
54
|
+
url: string;
|
|
55
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
56
|
+
headers?: Record<string, string>;
|
|
57
|
+
body?: Record<string, unknown>;
|
|
58
|
+
}
|
|
59
|
+
export interface CustomCallbackAction {
|
|
60
|
+
type: 'customCallback';
|
|
61
|
+
}
|
|
62
|
+
export type CardAction = OpenUrlAction | ChatWithUserAction | ChatWithGroupAction | SendMessageAction | CopyToClipboardAction | DownloadFileAction | InitiateCallAction | ApiCallAction | CustomCallbackAction;
|
|
63
|
+
export declare const ACTION_TYPES: readonly ["openUrl", "chatWithUser", "chatWithGroup", "sendMessage", "copyToClipboard", "downloadFile", "initiateCall", "apiCall", "customCallback"];
|
|
64
|
+
export type ActionType = typeof ACTION_TYPES[number];
|
|
65
|
+
/** Reference to an icon. Use 'name' for built-in icons, 'url' for custom icon URLs. If both present, url takes precedence. */
|
|
66
|
+
export interface IconRef {
|
|
67
|
+
name?: string;
|
|
68
|
+
url?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface TextElement {
|
|
71
|
+
id: string;
|
|
72
|
+
type: 'text';
|
|
73
|
+
content: string;
|
|
74
|
+
variant?: 'title' | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'body' | 'caption1' | 'caption2';
|
|
75
|
+
color?: ColorValue;
|
|
76
|
+
align?: 'left' | 'center' | 'right' | 'justify';
|
|
77
|
+
fontWeight?: 'regular' | 'medium' | 'bold';
|
|
78
|
+
maxLines?: number;
|
|
79
|
+
padding?: Padding;
|
|
80
|
+
}
|
|
81
|
+
export interface ImageElement {
|
|
82
|
+
id: string;
|
|
83
|
+
type: 'image';
|
|
84
|
+
url: string;
|
|
85
|
+
altText?: string;
|
|
86
|
+
fit?: 'cover' | 'contain' | 'fill';
|
|
87
|
+
width?: SizeOrPercentage;
|
|
88
|
+
height?: SizeOrPercentage;
|
|
89
|
+
borderRadius?: number;
|
|
90
|
+
padding?: Padding;
|
|
91
|
+
}
|
|
92
|
+
export interface IconElement {
|
|
93
|
+
id: string;
|
|
94
|
+
type: 'icon';
|
|
95
|
+
name?: string;
|
|
96
|
+
url?: string;
|
|
97
|
+
size?: number;
|
|
98
|
+
color?: ColorValue;
|
|
99
|
+
backgroundColor?: ColorValue;
|
|
100
|
+
borderRadius?: number;
|
|
101
|
+
padding?: number;
|
|
102
|
+
}
|
|
103
|
+
export interface AvatarElement {
|
|
104
|
+
id: string;
|
|
105
|
+
type: 'avatar';
|
|
106
|
+
imageUrl?: string;
|
|
107
|
+
fallbackInitials?: string;
|
|
108
|
+
size?: number;
|
|
109
|
+
borderRadius?: number;
|
|
110
|
+
backgroundColor?: ColorValue;
|
|
111
|
+
fontSize?: number;
|
|
112
|
+
fontWeight?: 'regular' | 'medium' | 'bold';
|
|
113
|
+
}
|
|
114
|
+
export interface BadgeElement {
|
|
115
|
+
id: string;
|
|
116
|
+
type: 'badge';
|
|
117
|
+
text: string;
|
|
118
|
+
color?: ColorValue;
|
|
119
|
+
size?: number;
|
|
120
|
+
backgroundColor?: ColorValue;
|
|
121
|
+
borderColor?: ColorValue;
|
|
122
|
+
borderWidth?: number;
|
|
123
|
+
borderRadius?: number;
|
|
124
|
+
padding?: Padding;
|
|
125
|
+
fontSize?: number;
|
|
126
|
+
}
|
|
127
|
+
export interface DividerElement {
|
|
128
|
+
id: string;
|
|
129
|
+
type: 'divider';
|
|
130
|
+
color?: ColorValue;
|
|
131
|
+
thickness?: number;
|
|
132
|
+
margin?: number;
|
|
133
|
+
}
|
|
134
|
+
export interface SpacerElement {
|
|
135
|
+
id: string;
|
|
136
|
+
type: 'spacer';
|
|
137
|
+
height: number;
|
|
138
|
+
}
|
|
139
|
+
export interface ChipElement {
|
|
140
|
+
id: string;
|
|
141
|
+
type: 'chip';
|
|
142
|
+
text: string;
|
|
143
|
+
color?: ColorValue;
|
|
144
|
+
icon?: IconRef;
|
|
145
|
+
backgroundColor?: ColorValue;
|
|
146
|
+
borderColor?: ColorValue;
|
|
147
|
+
borderWidth?: number;
|
|
148
|
+
borderRadius?: number;
|
|
149
|
+
padding?: Padding;
|
|
150
|
+
fontSize?: number;
|
|
151
|
+
}
|
|
152
|
+
export interface ProgressBarElement {
|
|
153
|
+
id: string;
|
|
154
|
+
type: 'progressBar';
|
|
155
|
+
value: number;
|
|
156
|
+
color?: ColorValue;
|
|
157
|
+
trackColor?: ColorValue;
|
|
158
|
+
height?: number;
|
|
159
|
+
label?: string;
|
|
160
|
+
borderRadius?: number;
|
|
161
|
+
labelFontSize?: number;
|
|
162
|
+
labelColor?: ColorValue;
|
|
163
|
+
}
|
|
164
|
+
export interface CodeBlockElement {
|
|
165
|
+
id: string;
|
|
166
|
+
type: 'codeBlock';
|
|
167
|
+
content: string;
|
|
168
|
+
language?: string;
|
|
169
|
+
backgroundColor?: ColorValue;
|
|
170
|
+
textColor?: ColorValue;
|
|
171
|
+
padding?: Padding;
|
|
172
|
+
borderRadius?: number;
|
|
173
|
+
fontSize?: number;
|
|
174
|
+
languageLabelFontSize?: number;
|
|
175
|
+
languageLabelColor?: ColorValue;
|
|
176
|
+
}
|
|
177
|
+
export interface MarkdownElement {
|
|
178
|
+
id: string;
|
|
179
|
+
type: 'markdown';
|
|
180
|
+
content: string;
|
|
181
|
+
baseFontSize?: number;
|
|
182
|
+
linkColor?: ColorValue;
|
|
183
|
+
color?: ColorValue;
|
|
184
|
+
lineHeight?: number;
|
|
185
|
+
}
|
|
186
|
+
export interface RowElement {
|
|
187
|
+
id: string;
|
|
188
|
+
type: 'row';
|
|
189
|
+
items: CardElement[];
|
|
190
|
+
gap?: number;
|
|
191
|
+
align?: 'start' | 'center' | 'end' | 'spaceBetween' | 'spaceAround';
|
|
192
|
+
crossAlign?: 'start' | 'center' | 'end';
|
|
193
|
+
wrap?: boolean;
|
|
194
|
+
scrollable?: boolean;
|
|
195
|
+
peek?: number;
|
|
196
|
+
snap?: 'item' | 'free';
|
|
197
|
+
padding?: Padding;
|
|
198
|
+
backgroundColor?: ColorValue;
|
|
199
|
+
borderRadius?: number;
|
|
200
|
+
borderColor?: ColorValue;
|
|
201
|
+
borderWidth?: number;
|
|
202
|
+
}
|
|
203
|
+
export interface ColumnElement {
|
|
204
|
+
id: string;
|
|
205
|
+
type: 'column';
|
|
206
|
+
items: CardElement[];
|
|
207
|
+
gap?: number;
|
|
208
|
+
align?: 'start' | 'center' | 'end' | 'stretch';
|
|
209
|
+
crossAlign?: 'start' | 'center' | 'end';
|
|
210
|
+
padding?: Padding;
|
|
211
|
+
backgroundColor?: ColorValue;
|
|
212
|
+
borderRadius?: number;
|
|
213
|
+
borderColor?: ColorValue;
|
|
214
|
+
borderWidth?: number;
|
|
215
|
+
}
|
|
216
|
+
export interface GridElement {
|
|
217
|
+
id: string;
|
|
218
|
+
type: 'grid';
|
|
219
|
+
items: CardElement[];
|
|
220
|
+
columns?: 2 | 3 | 4;
|
|
221
|
+
gap?: number;
|
|
222
|
+
padding?: Padding;
|
|
223
|
+
backgroundColor?: ColorValue;
|
|
224
|
+
borderRadius?: number;
|
|
225
|
+
borderColor?: ColorValue;
|
|
226
|
+
borderWidth?: number;
|
|
227
|
+
}
|
|
228
|
+
export interface AccordionElement {
|
|
229
|
+
id: string;
|
|
230
|
+
type: 'accordion';
|
|
231
|
+
header: string;
|
|
232
|
+
headerIcon?: IconRef;
|
|
233
|
+
body: CardElement[];
|
|
234
|
+
expandedByDefault?: boolean;
|
|
235
|
+
border?: boolean;
|
|
236
|
+
padding?: Padding;
|
|
237
|
+
fontSize?: number;
|
|
238
|
+
fontWeight?: 'regular' | 'medium' | 'bold';
|
|
239
|
+
borderRadius?: number;
|
|
240
|
+
}
|
|
241
|
+
export interface TabsElement {
|
|
242
|
+
id: string;
|
|
243
|
+
type: 'tabs';
|
|
244
|
+
tabs: {
|
|
245
|
+
label: string;
|
|
246
|
+
content: CardElement[];
|
|
247
|
+
}[];
|
|
248
|
+
defaultActiveTab?: number;
|
|
249
|
+
tabAlign?: 'start' | 'center' | 'stretch';
|
|
250
|
+
tabPadding?: Padding;
|
|
251
|
+
contentPadding?: Padding;
|
|
252
|
+
fontSize?: number;
|
|
253
|
+
}
|
|
254
|
+
export interface ButtonElement {
|
|
255
|
+
id: string;
|
|
256
|
+
type: 'button';
|
|
257
|
+
label: string;
|
|
258
|
+
action: CardAction;
|
|
259
|
+
backgroundColor?: ColorValue;
|
|
260
|
+
textColor?: ColorValue;
|
|
261
|
+
borderColor?: ColorValue;
|
|
262
|
+
borderWidth?: number;
|
|
263
|
+
borderRadius?: number;
|
|
264
|
+
icon?: IconRef;
|
|
265
|
+
iconPosition?: 'left' | 'right';
|
|
266
|
+
size?: number;
|
|
267
|
+
fullWidth?: boolean;
|
|
268
|
+
padding?: Padding;
|
|
269
|
+
fontSize?: number;
|
|
270
|
+
}
|
|
271
|
+
export interface IconButtonElement {
|
|
272
|
+
id: string;
|
|
273
|
+
type: 'iconButton';
|
|
274
|
+
icon: IconRef;
|
|
275
|
+
action: CardAction;
|
|
276
|
+
size?: number;
|
|
277
|
+
color?: ColorValue;
|
|
278
|
+
backgroundColor?: ColorValue;
|
|
279
|
+
borderRadius?: number;
|
|
280
|
+
}
|
|
281
|
+
export interface LinkElement {
|
|
282
|
+
id: string;
|
|
283
|
+
type: 'link';
|
|
284
|
+
text: string;
|
|
285
|
+
action: CardAction;
|
|
286
|
+
color?: ColorValue;
|
|
287
|
+
underline?: boolean;
|
|
288
|
+
fontSize?: number;
|
|
289
|
+
}
|
|
290
|
+
export interface TableElement {
|
|
291
|
+
id: string;
|
|
292
|
+
type: 'table';
|
|
293
|
+
columns: string[];
|
|
294
|
+
rows: string[][];
|
|
295
|
+
headerBackgroundColor?: ColorValue;
|
|
296
|
+
border?: boolean;
|
|
297
|
+
stripedRows?: boolean;
|
|
298
|
+
cellPadding?: number;
|
|
299
|
+
fontSize?: number;
|
|
300
|
+
stripedRowColor?: ColorValue;
|
|
301
|
+
borderColor?: ColorValue;
|
|
302
|
+
}
|
|
303
|
+
export type CardElement = TextElement | ImageElement | IconElement | AvatarElement | BadgeElement | DividerElement | SpacerElement | ChipElement | ProgressBarElement | CodeBlockElement | MarkdownElement | RowElement | ColumnElement | GridElement | AccordionElement | TabsElement | ButtonElement | IconButtonElement | LinkElement | TableElement;
|
|
304
|
+
export type ElementType = CardElement['type'];
|
|
305
|
+
export interface CardStyle {
|
|
306
|
+
background?: ColorValue;
|
|
307
|
+
borderRadius?: number;
|
|
308
|
+
borderColor?: ColorValue;
|
|
309
|
+
borderWidth?: number;
|
|
310
|
+
padding?: Padding;
|
|
311
|
+
}
|
|
312
|
+
export interface CardMessage {
|
|
313
|
+
version: '1.0';
|
|
314
|
+
body: CardElement[];
|
|
315
|
+
style?: CardStyle;
|
|
316
|
+
fallbackText: string;
|
|
317
|
+
}
|
|
318
|
+
export interface MessageData {
|
|
319
|
+
category: string;
|
|
320
|
+
type: string;
|
|
321
|
+
data: {
|
|
322
|
+
text: string;
|
|
323
|
+
card: CardMessage;
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
export interface Template {
|
|
327
|
+
id: string;
|
|
328
|
+
name: string;
|
|
329
|
+
description?: string;
|
|
330
|
+
schemaVersion?: string;
|
|
331
|
+
messageData: MessageData;
|
|
332
|
+
thumbnail?: string;
|
|
333
|
+
createdBy?: string;
|
|
334
|
+
createdAt: number;
|
|
335
|
+
updatedAt: number;
|
|
336
|
+
}
|
|
337
|
+
export declare function isContainerElement(el: CardElement): el is RowElement | ColumnElement | GridElement | AccordionElement;
|
|
338
|
+
export declare function getContainerChildren(el: CardElement): CardElement[] | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CardElement } from '../types/schema';
|
|
2
|
+
export interface FieldError {
|
|
3
|
+
field: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
/** Returns field-level validation errors for a single element. */
|
|
7
|
+
export declare function getElementErrors(el: CardElement): FieldError[];
|
|
8
|
+
/** Quick check: does this element have any errors? Useful for tree indicators. */
|
|
9
|
+
export declare function hasElementErrors(el: CardElement): boolean;
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cometchat/card-builder",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/bubble-builder.umd.js",
|
|
6
|
+
"module": "dist/bubble-builder.es.js",
|
|
7
|
+
"types": "dist/lib.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/bubble-builder.es.js",
|
|
11
|
+
"require": "./dist/bubble-builder.umd.js",
|
|
12
|
+
"types": "./dist/lib.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./style.css": "./dist/bubble-builder.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"dev": "vite",
|
|
21
|
+
"build": "tsc -b && vite build",
|
|
22
|
+
"build:lib": "tsc -b && vite build --mode lib && tsc -p tsconfig.lib.json",
|
|
23
|
+
"lint": "eslint .",
|
|
24
|
+
"preview": "vite preview"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@dnd-kit/core": "^6.3.1",
|
|
28
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
29
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
30
|
+
"ajv": "^8.18.0",
|
|
31
|
+
"ajv-formats": "^3.0.1",
|
|
32
|
+
"lucide-react": "^1.6.0",
|
|
33
|
+
"react": "^19.2.4",
|
|
34
|
+
"react-dom": "^19.2.4",
|
|
35
|
+
"zustand": "^5.0.12"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@eslint/js": "^9.39.4",
|
|
39
|
+
"@types/node": "^24.12.0",
|
|
40
|
+
"@types/react": "^19.2.14",
|
|
41
|
+
"@types/react-dom": "^19.2.3",
|
|
42
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
43
|
+
"eslint": "^9.39.4",
|
|
44
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
45
|
+
"eslint-plugin-react-refresh": "^0.5.2",
|
|
46
|
+
"globals": "^17.4.0",
|
|
47
|
+
"postcss-prefix-selector": "^2.1.1",
|
|
48
|
+
"postcss-pxtorem": "^6.1.0",
|
|
49
|
+
"typescript": "~5.9.3",
|
|
50
|
+
"typescript-eslint": "^8.57.0",
|
|
51
|
+
"vite": "^8.0.1",
|
|
52
|
+
"vite-plugin-dts": "^4.5.4"
|
|
53
|
+
}
|
|
54
|
+
}
|