@hubspot/ui-extensions 0.0.0 → 0.0.1-beta.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.
@@ -0,0 +1,433 @@
1
+ import { ReactNode, ComponentType } from 'react';
2
+ export interface AlertProps {
3
+ title: string;
4
+ body?: string;
5
+ children?: ReactNode;
6
+ variant?: 'info' | 'warning' | 'success' | 'error' | 'danger';
7
+ }
8
+ export interface ButtonProps {
9
+ onClick?: () => void;
10
+ href?: string;
11
+ disabled?: boolean;
12
+ variant?: 'primary' | 'secondary' | 'destructive';
13
+ type?: 'button' | 'reset' | 'submit';
14
+ children: ReactNode;
15
+ }
16
+ export interface ButtonRowProps {
17
+ children: ReactNode;
18
+ disableDropdown?: boolean;
19
+ }
20
+ export interface CardProps {
21
+ children: ReactNode;
22
+ }
23
+ export interface DescriptionListItemProps {
24
+ children: ReactNode;
25
+ label: string;
26
+ }
27
+ export interface DescriptionListProps {
28
+ children: ReactNode;
29
+ direction?: 'row' | 'column';
30
+ }
31
+ export interface DividerProps {
32
+ distance?: 'flush' | 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large';
33
+ }
34
+ export interface EmptyStateProps {
35
+ flush?: boolean;
36
+ children: ReactNode;
37
+ title?: string;
38
+ layout?: 'horizontal' | 'vertical';
39
+ reverseOrder?: boolean;
40
+ imageWidth?: number;
41
+ }
42
+ export interface ErrorStateProps {
43
+ children: ReactNode;
44
+ title?: string;
45
+ type?: 'error' | 'support' | 'lock';
46
+ }
47
+ export type FormInputValues = Record<string, string | number>;
48
+ export interface FormProps {
49
+ children: ReactNode;
50
+ onSubmit?: (event: RemoteEvent<FormInputValues>) => void;
51
+ preventDefault?: boolean;
52
+ }
53
+ export interface HeadingProps {
54
+ children: ReactNode;
55
+ inline?: boolean;
56
+ }
57
+ export interface ImageProps {
58
+ alt?: string;
59
+ href?: string;
60
+ onClick?: () => void;
61
+ src: string;
62
+ width?: number;
63
+ }
64
+ export interface InputProps {
65
+ label: string;
66
+ name: string;
67
+ value?: string;
68
+ required?: boolean;
69
+ readOnly?: boolean;
70
+ description?: string;
71
+ tooltip?: string;
72
+ placeholder?: string;
73
+ error?: boolean;
74
+ validationMessage?: string;
75
+ onChange?: (value: string) => void;
76
+ onInput?: (value: string) => void;
77
+ onBlur?: (value: string) => void;
78
+ onFocus?: (value: string) => void;
79
+ }
80
+ export interface TextareaProps extends InputProps {
81
+ cols?: number;
82
+ maxLength?: number;
83
+ rows?: number;
84
+ resize?: 'vertical' | 'horizontal' | 'both' | 'none';
85
+ }
86
+ export interface ProgressBarProps {
87
+ title?: string;
88
+ showPercentage?: boolean;
89
+ value?: number;
90
+ valueMax?: number;
91
+ valueDescription?: string;
92
+ variant?: 'success' | 'danger' | 'warning';
93
+ }
94
+ export interface SelectProps {
95
+ label: string;
96
+ name: string;
97
+ value?: string | number;
98
+ required?: boolean;
99
+ readOnly?: boolean;
100
+ description?: string;
101
+ tooltip?: string;
102
+ placeholder?: string;
103
+ error?: boolean;
104
+ validationMessage?: string;
105
+ onChange?: (value: SelectProps['value']) => void;
106
+ options: {
107
+ label: string;
108
+ value: string | number;
109
+ }[];
110
+ }
111
+ export interface TagProps {
112
+ children: ReactNode;
113
+ onClick?: () => void;
114
+ variant?: 'default' | 'warning' | 'success' | 'error';
115
+ }
116
+ export interface TextFormatOptions {
117
+ fontWeight?: 'regular' | 'bold' | 'demibold';
118
+ italic?: boolean;
119
+ lineDecoration?: 'none' | 'underline' | 'strikethrough';
120
+ }
121
+ export type TextProps = {
122
+ variant?: 'bodytext' | 'microcopy';
123
+ inline?: boolean;
124
+ children: ReactNode;
125
+ format?: TextFormatOptions;
126
+ };
127
+ export interface TileProps {
128
+ children: ReactNode;
129
+ flush?: boolean;
130
+ }
131
+ interface Team {
132
+ id: number;
133
+ name: string;
134
+ teammates: number[];
135
+ }
136
+ export type ToggleGroupOption = {
137
+ label: string;
138
+ value: string;
139
+ initialIsChecked?: boolean;
140
+ readonly?: boolean;
141
+ description?: string;
142
+ };
143
+ interface ToggleGroupListBaseProps {
144
+ name: ToggleGroupProps['name'];
145
+ options: ToggleGroupProps['options'];
146
+ variant: ToggleGroupProps['variant'];
147
+ inline?: boolean;
148
+ }
149
+ export interface CheckboxListProps extends ToggleGroupListBaseProps {
150
+ value?: CheckboxGroupProps['value'];
151
+ onChange?: CheckboxGroupProps['onChange'];
152
+ }
153
+ export interface RadioButtonListProps extends ToggleGroupListBaseProps {
154
+ value?: RadioButtonGroupProps['value'];
155
+ onChange?: RadioButtonGroupProps['onChange'];
156
+ }
157
+ interface CheckboxGroupProps {
158
+ toggleType: 'checkboxList';
159
+ onChange?: (value: this['value']) => void;
160
+ value?: string[];
161
+ }
162
+ interface RadioButtonGroupProps {
163
+ toggleType: 'radioButtonList';
164
+ onChange?: (value: this['value']) => void;
165
+ value?: string;
166
+ }
167
+ export type ToggleGroupProps = {
168
+ name: string;
169
+ label: string;
170
+ validationMessage?: string;
171
+ required?: boolean;
172
+ tooltip?: string;
173
+ error?: boolean;
174
+ options: Array<ToggleGroupOption>;
175
+ inline?: boolean;
176
+ variant?: 'default' | 'small';
177
+ } & (CheckboxGroupProps | RadioButtonGroupProps);
178
+ export interface UserContext {
179
+ id: number;
180
+ emails: string[];
181
+ email: string;
182
+ firstName: string;
183
+ lastName: string;
184
+ roles: string[];
185
+ teams: Team[];
186
+ locale?: string;
187
+ }
188
+ export interface PortalContext {
189
+ id: number;
190
+ timezone: string;
191
+ }
192
+ export interface Context {
193
+ user: UserContext;
194
+ portal: PortalContext;
195
+ }
196
+ export interface StackProps {
197
+ distance?: 'flush' | 'small' | 'extra-small' | 'medium' | 'large';
198
+ children?: React.ReactNode;
199
+ direction?: 'row' | 'column';
200
+ }
201
+ export interface StatisticsTrendProps {
202
+ value: string;
203
+ direction: 'increase' | 'decrease';
204
+ }
205
+ export interface StatisticsItemProps {
206
+ id?: string;
207
+ label: string;
208
+ number: string;
209
+ children: ReactNode;
210
+ }
211
+ export interface StatisticsProps {
212
+ children: ReactNode;
213
+ }
214
+ export interface ServerlessRunnerParams {
215
+ /**
216
+ * Name of the serverless function
217
+ */
218
+ name: string;
219
+ /**
220
+ * Names of CRM object properties to be retrieved and supplied to the function as `context.propertiesToSend`
221
+ */
222
+ propertiesToSend?: string[];
223
+ /**
224
+ * Additional parameters to be supplied to the function as `context.parameters`
225
+ */
226
+ parameters?: JsonValue;
227
+ /**
228
+ * @deprecated Optional payload supplied to the function as `context.event.payload`.
229
+ * Support for this param may be removed in the future. Use `parameters` instead.
230
+ */
231
+ payload?: JsonValue;
232
+ }
233
+ export declare enum ServerlessExecutionStatus {
234
+ Success = "SUCCESS",
235
+ Error = "ERROR"
236
+ }
237
+ export type ServerlessExecutionResult = {
238
+ status: ServerlessExecutionStatus.Success;
239
+ response: JsonValue;
240
+ } | {
241
+ status: ServerlessExecutionStatus.Error;
242
+ message: string;
243
+ };
244
+ export type ServerlessFuncRunner = (params: ServerlessRunnerParams) => Promise<ServerlessExecutionResult>;
245
+ export interface ServerlessExecutionRequest {
246
+ appId: number;
247
+ extensibleCardId: number;
248
+ serverlessFunction: string;
249
+ location: keyof ExtensionPoints;
250
+ objectQuery?: {
251
+ objectId: number;
252
+ objectTypeId: string;
253
+ objectPropertyNames: string[];
254
+ };
255
+ parameters?: JsonValue;
256
+ event?: {
257
+ type: 'SERVERLESS_ACTION_HOOK';
258
+ payload: JsonValue;
259
+ };
260
+ }
261
+ export interface ServerlessExecutionResponse {
262
+ logId: string;
263
+ response?: JsonValue;
264
+ }
265
+ export interface ServerlessErrorResponse {
266
+ responseJSON?: {
267
+ message: string;
268
+ correlationId: string;
269
+ category: string;
270
+ subCategory?: string;
271
+ errors?: {
272
+ message: string;
273
+ subCategory: string;
274
+ }[];
275
+ };
276
+ status: number;
277
+ }
278
+ export interface ExtensionCardContextData {
279
+ cardId: string;
280
+ appId: number | string;
281
+ objectId: number | string;
282
+ objectTypeId: string;
283
+ location: keyof ExtensionPoints;
284
+ }
285
+ export type ExtensionPointAction = (...args: any[]) => Promise<any> | void;
286
+ export interface ExtensionPointContract {
287
+ actions?: {
288
+ [k: string]: ExtensionPointAction;
289
+ } | {};
290
+ customComponents: Record<string, ComponentType<any>>;
291
+ }
292
+ type AlertType = 'info' | 'warning' | 'success' | 'danger' | 'tip' | undefined;
293
+ export type AddAlertAction = (args: {
294
+ type?: AlertType;
295
+ message: string;
296
+ }) => void;
297
+ export type ReloadPageAction = () => void;
298
+ export type FetchCrmObjectPropertiesAction = (properties: string[]) => Promise<Record<string, string>>;
299
+ export type OpenIframeModalAction = (action: OpenIframeActionPayload) => void;
300
+ export interface CrmMiddleExtensionPoint extends ExtensionPointContract {
301
+ actions: {
302
+ addAlert: AddAlertAction;
303
+ reloadPage: ReloadPageAction;
304
+ fetchCrmObjectProperties: FetchCrmObjectPropertiesAction;
305
+ openIframeModal: OpenIframeModalAction;
306
+ };
307
+ customComponents: {
308
+ CrmPropertyList: ComponentType<CrmPropertyListProps>;
309
+ CrmAssociationTable: ComponentType<CrmAssociationTableProps>;
310
+ CrmDataHighlight: ComponentType<CrmDataHighlightProps>;
311
+ CrmReport: ComponentType<CrmReportProps>;
312
+ CrmAssociationPivot: ComponentType<CrmAssociationPivotProps>;
313
+ };
314
+ }
315
+ export interface CrmDataHighlightProps {
316
+ properties: string[];
317
+ objectTypeId?: string;
318
+ objectId?: number;
319
+ }
320
+ export interface CrmReportProps {
321
+ reportId: string;
322
+ }
323
+ export interface CrmPropertyListProps {
324
+ properties: string[];
325
+ direction?: string;
326
+ objectTypeId?: string;
327
+ objectId?: number;
328
+ }
329
+ type CrmSortDescriptor = {
330
+ columnName: string;
331
+ direction: 1 | -1;
332
+ };
333
+ interface CrmSearchFilter {
334
+ operator: 'EQ' | 'NEQ' | 'LT' | 'LTE' | 'GT' | 'GTE' | 'BETWEEN' | 'IN' | 'NOT_IN' | 'HAS_PROPERTY' | 'NOT_HAS_PROPERTY' | 'ROLLING_DATE_RANGE' | 'TIME_UNIT_TO_DATE';
335
+ value?: string | number;
336
+ values?: string | number;
337
+ highValue?: string | number;
338
+ property: string;
339
+ }
340
+ export interface CrmAssociationTableProps {
341
+ objectTypeId: string;
342
+ propertyColumns: Array<string>;
343
+ quickFilterProperties?: Array<string>;
344
+ searchable?: boolean;
345
+ pagination?: boolean;
346
+ pageSize?: number;
347
+ preFilters?: Array<CrmSearchFilter>;
348
+ sort?: Array<CrmSortDescriptor>;
349
+ }
350
+ export interface CrmAssociationPivotProps {
351
+ objectTypeId: string;
352
+ associationLabels?: Array<string>;
353
+ maxAssociations?: number;
354
+ preFilters?: Array<CrmSearchFilter>;
355
+ sort?: Array<CrmSortDescriptor>;
356
+ }
357
+ interface CrmSidebarExtensionPoint extends ExtensionPointContract {
358
+ actions: {
359
+ reloadPage: ReloadPageAction;
360
+ };
361
+ }
362
+ interface RemotePlaygroundExtensionPoint extends ExtensionPointContract {
363
+ actions: {
364
+ warn: () => void;
365
+ };
366
+ customComponents: {
367
+ ExampleCrmComponent: ComponentType<ExampleCrmComponentProps>;
368
+ };
369
+ }
370
+ export interface ExtensionPoints {
371
+ 'uie.playground.middle': RemotePlaygroundExtensionPoint;
372
+ 'crm.record.tab': CrmMiddleExtensionPoint;
373
+ 'crm.record.sidebar': CrmSidebarExtensionPoint;
374
+ }
375
+ export interface ExampleCrmComponentProps {
376
+ name: string;
377
+ size: 'sm' | 'md' | 'lg';
378
+ count: number;
379
+ }
380
+ export interface ExtensionPointApi<ExtensionPointName extends keyof ExtensionPoints> {
381
+ context: Context;
382
+ runServerlessFunction: ServerlessFuncRunner;
383
+ actions: ExtensionPoints[ExtensionPointName]['actions'];
384
+ }
385
+ interface OpenIframeActionPayload {
386
+ uri: string;
387
+ height: number;
388
+ width: number;
389
+ associatedObjectProperties?: string[];
390
+ }
391
+ export interface LoadingSpinnerProps {
392
+ label: string;
393
+ showLabel?: boolean;
394
+ size?: 'xs' | 'sm' | 'md';
395
+ layout?: 'inline' | 'centered';
396
+ }
397
+ export interface TableElementProps {
398
+ children: React.ReactNode;
399
+ }
400
+ interface BaseTableProps {
401
+ bordered?: boolean;
402
+ flush?: boolean;
403
+ children: React.ReactNode;
404
+ }
405
+ export interface TableNoPaginatedProps extends BaseTableProps {
406
+ paginated?: false;
407
+ }
408
+ export interface TablePaginatedProps extends BaseTableProps {
409
+ paginated: true;
410
+ pageCount: number;
411
+ onPageChange: (pageNumber: number) => void;
412
+ showButtonLabels?: boolean;
413
+ showFirstLastButtons?: boolean;
414
+ maxVisiblePageButtons?: number;
415
+ page?: number;
416
+ }
417
+ export type TableProps = TableNoPaginatedProps | TablePaginatedProps;
418
+ export declare class RemoteEvent<V> {
419
+ type: string;
420
+ bubbles: boolean;
421
+ timeStamp: number;
422
+ targetValue: V;
423
+ constructor(value: V, event: Event);
424
+ }
425
+ export interface LinkProps {
426
+ children: ReactNode;
427
+ href: string;
428
+ variant?: 'primary' | 'destructive' | 'light' | 'dark';
429
+ }
430
+ export type JsonValue = string | number | boolean | null | JsonValue[] | {
431
+ [key: string]: JsonValue;
432
+ };
433
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,17 @@
1
+ export var ServerlessExecutionStatus;
2
+ (function (ServerlessExecutionStatus) {
3
+ ServerlessExecutionStatus["Success"] = "SUCCESS";
4
+ ServerlessExecutionStatus["Error"] = "ERROR";
5
+ })(ServerlessExecutionStatus || (ServerlessExecutionStatus = {}));
6
+ export class RemoteEvent {
7
+ type;
8
+ bubbles;
9
+ timeStamp;
10
+ targetValue;
11
+ constructor(value, event) {
12
+ this.bubbles = event.bubbles;
13
+ this.type = event.type;
14
+ this.timeStamp = event.timeStamp;
15
+ this.targetValue = value;
16
+ }
17
+ }
@@ -0,0 +1,3 @@
1
+ import type { RemoteComponentType } from '@remote-ui/core';
2
+ import type { ReactComponentTypeFromRemoteComponentType } from '@remote-ui/react';
3
+ export declare function createExtensionComponent<ComponentType extends string, Props = Record<string, never>, AllowedChildren extends RemoteComponentType<string, any> | boolean = true>(componentType: ComponentType | RemoteComponentType<ComponentType, Props, AllowedChildren>): RemoteComponentType<ComponentType, Props, AllowedChildren> & ReactComponentTypeFromRemoteComponentType<RemoteComponentType<ComponentType, Props, AllowedChildren>>;
@@ -0,0 +1,4 @@
1
+ import { createRemoteReactComponent } from '@remote-ui/react';
2
+ export function createExtensionComponent(componentType) {
3
+ return createRemoteReactComponent(componentType);
4
+ }
package/package.json CHANGED
@@ -1,17 +1,52 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions",
3
- "version": "0.0.0",
3
+ "version": "0.0.1-beta.0",
4
4
  "description": "",
5
5
  "type": "module",
6
- "main": "index.ts",
7
- "scripts": {},
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "scripts": {
9
+ "clean": "rm -rf dist/",
10
+ "build": "npm run clean && tsc",
11
+ "watch": "npm run clean && tsc --watch",
12
+ "prepare": "npm run build"
13
+ },
14
+ "files": [
15
+ "dist/**/*"
16
+ ],
8
17
  "publishConfig": {
9
18
  "access": "public"
10
19
  },
20
+ "exports": {
21
+ ".": "./dist/index.js",
22
+ "./crm": "./dist/crm/index.js"
23
+ },
11
24
  "license": "MIT",
12
25
  "dependencies": {
13
26
  "@remote-ui/react": "^5.0.0",
14
27
  "react": "^18.2.0"
15
28
  },
16
- "gitHead": "ca7c7648663fd4c60ce98b616ba6d3662d949f07"
29
+ "engines": {
30
+ "node": ">=16"
31
+ },
32
+ "peerDependencies": {
33
+ "@remote-ui/react": "^5.0.0",
34
+ "react": "^18.2.0",
35
+ "typescript": "^5.0.4"
36
+ },
37
+ "peerDependenciesMeta": {
38
+ "react": {
39
+ "optional": false
40
+ },
41
+ "@remote-ui/react": {
42
+ "optional": false
43
+ },
44
+ "typescript": {
45
+ "optional": true
46
+ }
47
+ },
48
+ "devDependencies": {
49
+ "typescript": "5.0.4"
50
+ },
51
+ "gitHead": "0bfb66cacc456a73f05a40841938e6b42f87aaba"
17
52
  }
package/components.ts DELETED
@@ -1,92 +0,0 @@
1
- import { createRemoteReactComponent } from '@remote-ui/react';
2
-
3
- import type {
4
- AlertProps,
5
- ButtonProps,
6
- ButtonRowProps,
7
- DescriptionListProps,
8
- DescriptionListItemProps,
9
- FormProps,
10
- HeadingProps,
11
- ImageProps,
12
- InputProps,
13
- ProgressBarProps,
14
- SelectProps,
15
- TagProps,
16
- TextProps,
17
- TileProps,
18
- StackProps,
19
- StatisticsProps,
20
- StatisticsItemProps,
21
- StatisticsTrendProps,
22
- } from './types';
23
-
24
- interface CardProps {
25
- style: React.CSSProperties;
26
- title: string;
27
- }
28
-
29
- const Alert = createRemoteReactComponent<'Alert', AlertProps>('Alert');
30
- const Button = createRemoteReactComponent<'Button', ButtonProps>('Button');
31
- const ButtonRow = createRemoteReactComponent<'ButtonRow', ButtonRowProps>(
32
- 'ButtonRow'
33
- );
34
- const Card = createRemoteReactComponent<'Card', CardProps>('Card');
35
- const DescriptionList = createRemoteReactComponent<
36
- 'DescriptionList',
37
- DescriptionListProps
38
- >('DescriptionList');
39
- const DescriptionListItem = createRemoteReactComponent<
40
- 'DescriptionListItem',
41
- DescriptionListItemProps
42
- >('DescriptionListItem');
43
- const Divider = createRemoteReactComponent<'Divider', {}>('Divider');
44
- const Form = createRemoteReactComponent<'Form', FormProps>('Form');
45
- const Heading = createRemoteReactComponent<'Heading', HeadingProps>('Heading');
46
- const Image = createRemoteReactComponent<'Image', ImageProps>('Image');
47
- const Input = createRemoteReactComponent<'Input', InputProps>('Input');
48
- const ProgressBar = createRemoteReactComponent<'ProgressBar', ProgressBarProps>(
49
- 'ProgressBar'
50
- );
51
- const Select = createRemoteReactComponent<'Select', SelectProps>('Select');
52
- const Tag = createRemoteReactComponent<'Tag', TagProps>('Tag');
53
- const Text = createRemoteReactComponent<'Text', TextProps>('Text');
54
- const Tile = createRemoteReactComponent<'Tile', TileProps>('Tile');
55
- const Stack = createRemoteReactComponent<'Stack', StackProps>('Stack');
56
-
57
- const StatisticsItem = createRemoteReactComponent<
58
- 'StatisticsItem',
59
- StatisticsItemProps
60
- >('StatisticsItem');
61
-
62
- const Statistics = createRemoteReactComponent<'Statistics', StatisticsProps>(
63
- 'Statistics'
64
- );
65
-
66
- const StatisticsTrend = createRemoteReactComponent<
67
- 'StatisticsTrend',
68
- StatisticsTrendProps
69
- >('StatisticsTrend');
70
-
71
- export {
72
- Alert,
73
- Button,
74
- ButtonRow,
75
- Card,
76
- DescriptionList,
77
- DescriptionListItem,
78
- Divider,
79
- Form,
80
- Heading,
81
- Image,
82
- Input,
83
- ProgressBar,
84
- Select,
85
- Stack,
86
- Statistics,
87
- StatisticsItem,
88
- StatisticsTrend,
89
- Tag,
90
- Text,
91
- Tile,
92
- };
package/hubspot.ts DELETED
@@ -1,20 +0,0 @@
1
- /* eslint-disable hubspot-dev/no-confusing-browser-globals */
2
-
3
- import { createRoot, RemoteRoot } from '@remote-ui/react';
4
- import { ReactElement } from 'react';
5
- import { Context } from './types';
6
-
7
- export const hubspot = {
8
- extend: render,
9
- };
10
-
11
- const extend = (...args) => (self as any).extend(...args);
12
-
13
- function render(
14
- renderCallback: (api: { context: Context }) => ReactElement<any>
15
- ) {
16
- return extend((root: RemoteRoot, api: { context: Context }) => {
17
- createRoot(root).render(renderCallback(api));
18
- root.mount();
19
- });
20
- }
package/index.ts DELETED
@@ -1,24 +0,0 @@
1
- export {
2
- Alert,
3
- Button,
4
- ButtonRow,
5
- Card,
6
- DescriptionList,
7
- DescriptionListItem,
8
- Divider,
9
- Form,
10
- Heading,
11
- Image,
12
- Input,
13
- ProgressBar,
14
- Select,
15
- Stack,
16
- Statistics,
17
- StatisticsItem,
18
- StatisticsTrend,
19
- Tag,
20
- Text,
21
- Tile,
22
- } from './components';
23
-
24
- export { hubspot } from './hubspot';