@scryme/chat 2.91.2 → 2.91.4
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/dist/custom-message-schema.d.ts +631 -0
- package/dist/custom-message-schema.js +395 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/custom-message-schema.ts +517 -0
- package/src/index.ts +1 -1
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GraphQL-inspired Custom Message Schema
|
|
5
|
+
*
|
|
6
|
+
* This schema defines a structured, node-based representation for custom messages.
|
|
7
|
+
* It separates the underlying "Data" from the "UI" components, allowing for
|
|
8
|
+
* flexible and type-safe rendering.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Basic Value types for properties in custom message components */
|
|
12
|
+
export const PropertyValueSchema = z.union([
|
|
13
|
+
z.string(),
|
|
14
|
+
z.number(),
|
|
15
|
+
z.boolean(),
|
|
16
|
+
z.null(),
|
|
17
|
+
z.array(z.string()),
|
|
18
|
+
z.record(z.string(), z.any()),
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Validation Schema for Input components in custom messages.
|
|
23
|
+
*/
|
|
24
|
+
export const ValidationSchema = z.object({
|
|
25
|
+
/** Whether filling or selecting this field is strictly required before submitting an action */
|
|
26
|
+
required: z.boolean().optional(),
|
|
27
|
+
/** Regular expression string pattern for string validation */
|
|
28
|
+
pattern: z.string().optional(),
|
|
29
|
+
/** Minimum text length requirement */
|
|
30
|
+
minLength: z.number().optional(),
|
|
31
|
+
/** Maximum text length allowed */
|
|
32
|
+
maxLength: z.number().optional(),
|
|
33
|
+
/** Minimum numeric value allowed */
|
|
34
|
+
min: z.number().optional(),
|
|
35
|
+
/** Maximum numeric value allowed */
|
|
36
|
+
max: z.number().optional(),
|
|
37
|
+
/** Custom error message displayed when validation fails */
|
|
38
|
+
errorMessage: z.string().optional(),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type ValidationSchemaType = z.infer<typeof ValidationSchema>;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Data Source Schema for dynamic content (e.g., Select options or dynamic dropdowns).
|
|
45
|
+
*/
|
|
46
|
+
export const DataSourceSchema = z.object({
|
|
47
|
+
/** Source type: 'STATIC' for inline items, 'API' for external fetching, 'VARIABLE' for message data interpolation */
|
|
48
|
+
type: z.enum(['STATIC', 'API', 'VARIABLE']),
|
|
49
|
+
/** For STATIC: explicit list of available options */
|
|
50
|
+
items: z.array(z.object({
|
|
51
|
+
label: z.string(),
|
|
52
|
+
value: z.union([z.string(), z.number(), z.boolean()]),
|
|
53
|
+
})).optional(),
|
|
54
|
+
/** For API: endpoint URL from which items will be fetched */
|
|
55
|
+
url: z.string().optional(),
|
|
56
|
+
/** For API: HTTP request method */
|
|
57
|
+
method: z.enum(['GET', 'POST']).default('GET').optional(),
|
|
58
|
+
/** For API: HTTP headers to send with the fetch request */
|
|
59
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
60
|
+
/** For VARIABLE: property key inside the custom message `data` object containing option items */
|
|
61
|
+
key: z.string().optional(),
|
|
62
|
+
/** Key mapping configuration when response objects do not natively use `label` and `value` */
|
|
63
|
+
map: z.object({
|
|
64
|
+
label: z.string(),
|
|
65
|
+
value: z.string(),
|
|
66
|
+
}).optional(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Condition Schema for Visibility and Logical Evaluation.
|
|
71
|
+
*/
|
|
72
|
+
export const ConditionSchema = z.object({
|
|
73
|
+
/** The field ID or path inside data/formState to evaluate */
|
|
74
|
+
field: z.string(),
|
|
75
|
+
/** Comparison operator */
|
|
76
|
+
operator: z.enum(['EQUALS', 'NOT_EQUALS', 'CONTAINS', 'GREATER_THAN', 'LESS_THAN', 'EXISTS', 'NOT_EXISTS']),
|
|
77
|
+
/** Comparison target value */
|
|
78
|
+
value: z.any().optional(),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export type ConditionSchemaType = z.infer<typeof ConditionSchema>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Theme configuration for Custom Messages enabling developer branding overrides.
|
|
85
|
+
*/
|
|
86
|
+
export const CustomMessageThemeSchema = z.object({
|
|
87
|
+
/** Custom background color (Hex/RGB/HSL/CSS var) */
|
|
88
|
+
backgroundColor: z.string().optional(),
|
|
89
|
+
/** Custom border color */
|
|
90
|
+
borderColor: z.string().optional(),
|
|
91
|
+
/** Primary text color override */
|
|
92
|
+
textColor: z.string().optional(),
|
|
93
|
+
/** Accent / Brand highlight color */
|
|
94
|
+
accentColor: z.string().optional(),
|
|
95
|
+
/** Custom CSS class names applied to the container */
|
|
96
|
+
className: z.string().optional(),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export type CustomMessageTheme = z.infer<typeof CustomMessageThemeSchema>;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* A Node is the recursive structural building block of custom message UI components.
|
|
103
|
+
*/
|
|
104
|
+
export type MessageNode = {
|
|
105
|
+
/** The type identifier of the component (e.g., 'Layout.Card', 'Display.Field', 'Input.Text', 'Data.Stat') */
|
|
106
|
+
type: string;
|
|
107
|
+
/** Unique identifier for the node (required for form inputs to track state & validation) */
|
|
108
|
+
id?: string;
|
|
109
|
+
/** Key-value pairs for component properties and props configuration */
|
|
110
|
+
properties?: Record<string, any>;
|
|
111
|
+
/** Nested child nodes rendered inside this node */
|
|
112
|
+
children?: MessageNode[];
|
|
113
|
+
/** Optional conditional display logic evaluating visibility based on form state or message data */
|
|
114
|
+
condition?: ConditionSchemaType;
|
|
115
|
+
/** Optional validation rules for user inputs */
|
|
116
|
+
validation?: ValidationSchemaType;
|
|
117
|
+
/** Optional developer-defined metadata associated with this node */
|
|
118
|
+
metadata?: Record<string, any>;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Zod Schema for recursive MessageNode
|
|
122
|
+
export const MessageNodeSchema: z.ZodType<MessageNode> = z.lazy(() =>
|
|
123
|
+
z.object({
|
|
124
|
+
type: z.string().min(1),
|
|
125
|
+
id: z.string().optional(),
|
|
126
|
+
properties: z.record(z.string(), z.any()).optional(),
|
|
127
|
+
children: z.array(MessageNodeSchema).optional(),
|
|
128
|
+
condition: ConditionSchema.optional(),
|
|
129
|
+
validation: ValidationSchema.optional(),
|
|
130
|
+
metadata: z.record(z.string(), z.any()).optional(),
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Predefined Custom Message Types supported out of the box.
|
|
136
|
+
*/
|
|
137
|
+
export const PredefinedCustomMessageTypeSchema = z.enum([
|
|
138
|
+
'APPROVAL',
|
|
139
|
+
'REPORT',
|
|
140
|
+
'FORM',
|
|
141
|
+
'FEEDBACK',
|
|
142
|
+
'TASK_CARD',
|
|
143
|
+
'SURVEY',
|
|
144
|
+
'GENERIC',
|
|
145
|
+
]);
|
|
146
|
+
|
|
147
|
+
export type PredefinedCustomMessageType = z.infer<typeof PredefinedCustomMessageTypeSchema>;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Action item schema for interactive buttons rendered on custom messages.
|
|
151
|
+
*/
|
|
152
|
+
export const MessageActionSchema = z.object({
|
|
153
|
+
/** Unique action identifier */
|
|
154
|
+
id: z.string(),
|
|
155
|
+
/** Button text label */
|
|
156
|
+
label: z.string(),
|
|
157
|
+
/** Visual variant of the button */
|
|
158
|
+
type: z.enum(['PRIMARY', 'SECONDARY', 'DESTRUCTIVE', 'GHOST']).default('SECONDARY'),
|
|
159
|
+
/** Name of the icon (from Lucide icons library) to render on the button */
|
|
160
|
+
icon: z.string().optional(),
|
|
161
|
+
/** Handler configuration specifying what happens when the action button is clicked */
|
|
162
|
+
handler: z.object({
|
|
163
|
+
/** Action handler type: CALLBACK (sends payload back), LINK (navigates), MODAL (opens modal) */
|
|
164
|
+
type: z.enum(['CALLBACK', 'LINK', 'MODAL']),
|
|
165
|
+
/** Target URL for LINK type actions */
|
|
166
|
+
url: z.string().optional(),
|
|
167
|
+
/** Callback ID for CALLBACK type actions */
|
|
168
|
+
callbackId: z.string().optional(),
|
|
169
|
+
/** Custom key-value payload sent back with the callback */
|
|
170
|
+
payload: z.record(z.string(), z.any()).optional(),
|
|
171
|
+
/** Whether to automatically gather and send all current form input state in the callback payload */
|
|
172
|
+
includeFormState: z.boolean().default(true).optional(),
|
|
173
|
+
}),
|
|
174
|
+
/** Optional visibility condition for displaying this action button */
|
|
175
|
+
condition: ConditionSchema.optional(),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export type MessageAction = z.infer<typeof MessageActionSchema>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Root Custom Message Schema defining full metadata structures for dynamic & customized UI rendering.
|
|
182
|
+
*/
|
|
183
|
+
export const CustomMessageSchema = z.object({
|
|
184
|
+
/** Schema version string (e.g. "v1") */
|
|
185
|
+
version: z.string().default('v1'),
|
|
186
|
+
/** Optional template identifier reference */
|
|
187
|
+
templateId: z.string().optional(),
|
|
188
|
+
/** The logical message category type (e.g. 'APPROVAL', 'REPORT', 'FORM', 'FEEDBACK', 'TASK_CARD', 'SURVEY', or custom string) */
|
|
189
|
+
type: z.string(),
|
|
190
|
+
/** Top-level configuration, branding, and header context */
|
|
191
|
+
context: z.object({
|
|
192
|
+
/** Main title displayed on the message header */
|
|
193
|
+
title: z.string().min(1),
|
|
194
|
+
/** Optional subtitle or description */
|
|
195
|
+
description: z.string().optional(),
|
|
196
|
+
/** Lucide icon name for the message header */
|
|
197
|
+
icon: z.string().optional(),
|
|
198
|
+
/** Accent color override for header or priority elements */
|
|
199
|
+
color: z.string().optional(),
|
|
200
|
+
/** Priority indicator badge level */
|
|
201
|
+
priority: z.enum(['low', 'normal', 'high', 'urgent']).default('normal'),
|
|
202
|
+
}),
|
|
203
|
+
/** Theme styling configuration for developer customization */
|
|
204
|
+
theme: CustomMessageThemeSchema.optional(),
|
|
205
|
+
/** Hierarchical node tree defining the layout and components */
|
|
206
|
+
root: MessageNodeSchema,
|
|
207
|
+
/** Interactive action buttons attached to the message */
|
|
208
|
+
actions: z.array(MessageActionSchema).optional(),
|
|
209
|
+
/** Data dictionary used for variable interpolation (e.g., `{{user.name}}`) and logic */
|
|
210
|
+
data: z.record(z.string(), z.any()).optional(),
|
|
211
|
+
/** Target restrictions and permissions constraints */
|
|
212
|
+
constraints: z
|
|
213
|
+
.object({
|
|
214
|
+
/** Restrict interactability to specific user IDs */
|
|
215
|
+
targetUsers: z.array(z.string()).optional(),
|
|
216
|
+
/** Required user roles/permissions to execute actions */
|
|
217
|
+
requiresPermissions: z.array(z.string()).optional(),
|
|
218
|
+
/** ISO expiration timestamp after which actions become disabled */
|
|
219
|
+
expiresAt: z.string().datetime().optional(),
|
|
220
|
+
})
|
|
221
|
+
.optional(),
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
export type CustomMessage = z.infer<typeof CustomMessageSchema>;
|
|
225
|
+
|
|
226
|
+
// --- Helper Functions / Builders for Predefined Custom Message Schemas ---
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Builder options for creating an Approval custom message schema.
|
|
230
|
+
*/
|
|
231
|
+
export interface CreateApprovalMessageOptions {
|
|
232
|
+
title: string;
|
|
233
|
+
description?: string;
|
|
234
|
+
fields: Array<{ label: string; value: string }>;
|
|
235
|
+
callbackId: string;
|
|
236
|
+
priority?: 'low' | 'normal' | 'high' | 'urgent';
|
|
237
|
+
approveLabel?: string;
|
|
238
|
+
rejectLabel?: string;
|
|
239
|
+
data?: Record<string, any>;
|
|
240
|
+
theme?: CustomMessageTheme;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Creates a standard Approval Custom Message schema structure.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* const approvalSchema = createApprovalMessage({
|
|
249
|
+
* title: 'Expense Reimbursement Request',
|
|
250
|
+
* description: 'Requested by Jane Doe for $450.00',
|
|
251
|
+
* fields: [
|
|
252
|
+
* { label: 'Category', value: 'Travel' },
|
|
253
|
+
* { label: 'Amount', value: '$450.00' }
|
|
254
|
+
* ],
|
|
255
|
+
* callbackId: 'expense-approval-101'
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export const createApprovalMessage = (options: CreateApprovalMessageOptions): CustomMessage => ({
|
|
260
|
+
version: 'v1',
|
|
261
|
+
type: 'APPROVAL',
|
|
262
|
+
context: {
|
|
263
|
+
title: options.title,
|
|
264
|
+
description: options.description,
|
|
265
|
+
icon: 'CheckSquare',
|
|
266
|
+
priority: options.priority || 'normal',
|
|
267
|
+
},
|
|
268
|
+
theme: options.theme,
|
|
269
|
+
root: {
|
|
270
|
+
type: 'Layout.Card',
|
|
271
|
+
children: [
|
|
272
|
+
{
|
|
273
|
+
type: 'Layout.Grid',
|
|
274
|
+
properties: { columns: 2 },
|
|
275
|
+
children: options.fields.map(f => ({
|
|
276
|
+
type: 'Display.Field',
|
|
277
|
+
properties: { label: f.label, value: f.value },
|
|
278
|
+
})),
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
actions: [
|
|
283
|
+
{
|
|
284
|
+
id: 'approve',
|
|
285
|
+
label: options.approveLabel || 'Approve',
|
|
286
|
+
type: 'PRIMARY',
|
|
287
|
+
icon: 'Check',
|
|
288
|
+
handler: {
|
|
289
|
+
type: 'CALLBACK',
|
|
290
|
+
callbackId: options.callbackId,
|
|
291
|
+
payload: { action: 'approve' },
|
|
292
|
+
includeFormState: true,
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
id: 'reject',
|
|
297
|
+
label: options.rejectLabel || 'Reject',
|
|
298
|
+
type: 'DESTRUCTIVE',
|
|
299
|
+
icon: 'X',
|
|
300
|
+
handler: {
|
|
301
|
+
type: 'CALLBACK',
|
|
302
|
+
callbackId: options.callbackId,
|
|
303
|
+
payload: { action: 'reject' },
|
|
304
|
+
includeFormState: true,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
],
|
|
308
|
+
data: options.data,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Builder options for creating a Report custom message schema.
|
|
313
|
+
*/
|
|
314
|
+
export interface CreateReportMessageOptions {
|
|
315
|
+
title: string;
|
|
316
|
+
reportId: string;
|
|
317
|
+
summary: string;
|
|
318
|
+
metrics: Array<{ label: string; value: string | number }>;
|
|
319
|
+
viewReportUrl?: string;
|
|
320
|
+
data?: Record<string, any>;
|
|
321
|
+
theme?: CustomMessageTheme;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Creates a standard Report Custom Message schema structure.
|
|
326
|
+
*/
|
|
327
|
+
export const createReportMessage = (options: CreateReportMessageOptions): CustomMessage => ({
|
|
328
|
+
version: 'v1',
|
|
329
|
+
type: 'REPORT',
|
|
330
|
+
context: {
|
|
331
|
+
title: options.title,
|
|
332
|
+
icon: 'BarChart',
|
|
333
|
+
priority: 'normal',
|
|
334
|
+
},
|
|
335
|
+
theme: options.theme,
|
|
336
|
+
root: {
|
|
337
|
+
type: 'Layout.Stack',
|
|
338
|
+
children: [
|
|
339
|
+
{
|
|
340
|
+
type: 'Text.Paragraph',
|
|
341
|
+
properties: { content: options.summary },
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
type: 'Data.StatsGrid',
|
|
345
|
+
children: options.metrics.map(m => ({
|
|
346
|
+
type: 'Data.Stat',
|
|
347
|
+
properties: { label: m.label, value: m.value },
|
|
348
|
+
})),
|
|
349
|
+
},
|
|
350
|
+
],
|
|
351
|
+
},
|
|
352
|
+
actions: [
|
|
353
|
+
{
|
|
354
|
+
id: 'view_details',
|
|
355
|
+
label: 'View Full Report',
|
|
356
|
+
type: 'SECONDARY',
|
|
357
|
+
icon: 'ExternalLink',
|
|
358
|
+
handler: {
|
|
359
|
+
type: 'LINK',
|
|
360
|
+
url: options.viewReportUrl || `/reports/${options.reportId}`,
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
data: options.data,
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Input field definition for generic Form and Feedback custom messages.
|
|
369
|
+
*/
|
|
370
|
+
export interface FormFieldConfig {
|
|
371
|
+
id: string;
|
|
372
|
+
label: string;
|
|
373
|
+
type?: 'text' | 'textarea' | 'select' | 'checkbox';
|
|
374
|
+
placeholder?: string;
|
|
375
|
+
options?: Array<{ label: string; value: string }>;
|
|
376
|
+
required?: boolean;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Builder options for creating an interactive Form or Feedback custom message schema.
|
|
381
|
+
*/
|
|
382
|
+
export interface CreateFormMessageOptions {
|
|
383
|
+
title: string;
|
|
384
|
+
description?: string;
|
|
385
|
+
fields: FormFieldConfig[];
|
|
386
|
+
submitCallbackId: string;
|
|
387
|
+
submitLabel?: string;
|
|
388
|
+
type?: 'FORM' | 'FEEDBACK' | 'SURVEY';
|
|
389
|
+
data?: Record<string, any>;
|
|
390
|
+
theme?: CustomMessageTheme;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Creates an interactive Form / Survey / Feedback Custom Message schema structure.
|
|
395
|
+
*/
|
|
396
|
+
export const createFormMessage = (options: CreateFormMessageOptions): CustomMessage => ({
|
|
397
|
+
version: 'v1',
|
|
398
|
+
type: options.type || 'FORM',
|
|
399
|
+
context: {
|
|
400
|
+
title: options.title,
|
|
401
|
+
description: options.description,
|
|
402
|
+
icon: options.type === 'FEEDBACK' ? 'HelpCircle' : 'FileText',
|
|
403
|
+
priority: 'normal',
|
|
404
|
+
},
|
|
405
|
+
theme: options.theme,
|
|
406
|
+
root: {
|
|
407
|
+
type: 'Layout.Stack',
|
|
408
|
+
children: options.fields.map(field => {
|
|
409
|
+
const nodeType =
|
|
410
|
+
field.type === 'select'
|
|
411
|
+
? 'Input.Select'
|
|
412
|
+
: field.type === 'checkbox'
|
|
413
|
+
? 'Input.Checkbox'
|
|
414
|
+
: 'Input.Text';
|
|
415
|
+
|
|
416
|
+
const validation: ValidationSchemaType | undefined = field.required
|
|
417
|
+
? { required: true, errorMessage: `${field.label} is required` }
|
|
418
|
+
: undefined;
|
|
419
|
+
|
|
420
|
+
const properties: Record<string, any> = {
|
|
421
|
+
label: field.label,
|
|
422
|
+
placeholder: field.placeholder,
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
if (field.type === 'textarea') {
|
|
426
|
+
properties.multiline = true;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (field.type === 'select' && field.options) {
|
|
430
|
+
properties.dataSource = {
|
|
431
|
+
type: 'STATIC',
|
|
432
|
+
items: field.options,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return {
|
|
437
|
+
type: nodeType,
|
|
438
|
+
id: field.id,
|
|
439
|
+
properties,
|
|
440
|
+
validation,
|
|
441
|
+
};
|
|
442
|
+
}),
|
|
443
|
+
},
|
|
444
|
+
actions: [
|
|
445
|
+
{
|
|
446
|
+
id: 'submit',
|
|
447
|
+
label: options.submitLabel || 'Submit',
|
|
448
|
+
type: 'PRIMARY',
|
|
449
|
+
icon: 'Send',
|
|
450
|
+
handler: {
|
|
451
|
+
type: 'CALLBACK',
|
|
452
|
+
callbackId: options.submitCallbackId,
|
|
453
|
+
payload: { action: 'submit' },
|
|
454
|
+
includeFormState: true,
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
],
|
|
458
|
+
data: options.data,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Builder options for creating a Task Card custom message schema.
|
|
463
|
+
*/
|
|
464
|
+
export interface CreateTaskCardMessageOptions {
|
|
465
|
+
title: string;
|
|
466
|
+
description?: string;
|
|
467
|
+
status: string;
|
|
468
|
+
assignee?: string;
|
|
469
|
+
dueDate?: string;
|
|
470
|
+
callbackId: string;
|
|
471
|
+
data?: Record<string, any>;
|
|
472
|
+
theme?: CustomMessageTheme;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Creates a Task Card Custom Message schema structure.
|
|
477
|
+
*/
|
|
478
|
+
export const createTaskCardMessage = (options: CreateTaskCardMessageOptions): CustomMessage => ({
|
|
479
|
+
version: 'v1',
|
|
480
|
+
type: 'TASK_CARD',
|
|
481
|
+
context: {
|
|
482
|
+
title: options.title,
|
|
483
|
+
description: options.description,
|
|
484
|
+
icon: 'CheckSquare',
|
|
485
|
+
priority: 'normal',
|
|
486
|
+
},
|
|
487
|
+
theme: options.theme,
|
|
488
|
+
root: {
|
|
489
|
+
type: 'Layout.Stack',
|
|
490
|
+
children: [
|
|
491
|
+
{
|
|
492
|
+
type: 'Layout.Grid',
|
|
493
|
+
properties: { columns: 3 },
|
|
494
|
+
children: [
|
|
495
|
+
{ type: 'Display.Field', properties: { label: 'Status', value: options.status } },
|
|
496
|
+
{ type: 'Display.Field', properties: { label: 'Assignee', value: options.assignee || 'Unassigned' } },
|
|
497
|
+
{ type: 'Display.Field', properties: { label: 'Due Date', value: options.dueDate || 'None' } },
|
|
498
|
+
],
|
|
499
|
+
},
|
|
500
|
+
],
|
|
501
|
+
},
|
|
502
|
+
actions: [
|
|
503
|
+
{
|
|
504
|
+
id: 'complete_task',
|
|
505
|
+
label: 'Mark Completed',
|
|
506
|
+
type: 'PRIMARY',
|
|
507
|
+
icon: 'Check',
|
|
508
|
+
handler: {
|
|
509
|
+
type: 'CALLBACK',
|
|
510
|
+
callbackId: options.callbackId,
|
|
511
|
+
payload: { action: 'complete' },
|
|
512
|
+
includeFormState: false,
|
|
513
|
+
},
|
|
514
|
+
},
|
|
515
|
+
],
|
|
516
|
+
data: options.data,
|
|
517
|
+
});
|
package/src/index.ts
CHANGED