@hubspot/ui-extensions 0.9.8 → 0.10.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/dist/__tests__/{experimental → crm}/hooks/useAssociations.spec.js +123 -4
- package/dist/__tests__/{experimental → crm}/hooks/useCrmProperties.spec.js +17 -3
- package/dist/__tests__/{experimental/crm → crm/utils}/fetchAssociations.spec.js +1 -1
- package/dist/__tests__/{experimental/crm → crm/utils}/fetchCrmProperties.spec.js +1 -1
- package/dist/__tests__/test-d/extension-points.test-d.d.ts +1 -0
- package/dist/__tests__/test-d/extension-points.test-d.js +29 -0
- package/dist/{experimental → crm}/hooks/useAssociations.d.ts +2 -2
- package/dist/{experimental → crm}/hooks/useAssociations.js +4 -4
- package/dist/{experimental → crm}/hooks/useCrmProperties.d.ts +1 -1
- package/dist/{experimental → crm}/hooks/useCrmProperties.js +4 -1
- package/dist/crm/index.d.ts +2 -0
- package/dist/crm/index.js +2 -0
- package/dist/experimental/index.d.ts +3 -21
- package/dist/experimental/index.js +3 -13
- package/dist/experimental/types.d.ts +1 -22
- package/dist/experimental/types.js +4 -0
- package/dist/pages/home/components.d.ts +28 -0
- package/dist/pages/home/components.js +20 -0
- package/dist/types.d.ts +40 -1
- package/package.json +10 -4
- /package/dist/__tests__/{experimental → crm}/hooks/useAssociations.spec.d.ts +0 -0
- /package/dist/__tests__/{experimental → crm}/hooks/useCrmProperties.spec.d.ts +0 -0
- /package/dist/__tests__/{experimental/crm → crm/utils}/fetchAssociations.spec.d.ts +0 -0
- /package/dist/__tests__/{experimental/crm → crm/utils}/fetchCrmProperties.spec.d.ts +0 -0
- /package/dist/{experimental/crm → crm/utils}/fetchAssociations.d.ts +0 -0
- /package/dist/{experimental/crm → crm/utils}/fetchAssociations.js +0 -0
- /package/dist/{experimental/crm → crm/utils}/fetchCrmProperties.d.ts +0 -0
- /package/dist/{experimental/crm → crm/utils}/fetchCrmProperties.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderHook, waitFor } from '@testing-library/react';
|
|
2
|
-
import { useAssociations } from '../../../
|
|
3
|
-
import { fetchAssociations } from '../../../
|
|
2
|
+
import { useAssociations } from '../../../crm/hooks/useAssociations';
|
|
3
|
+
import { fetchAssociations } from '../../../crm/utils/fetchAssociations';
|
|
4
4
|
// Mock the logger module
|
|
5
5
|
jest.mock('../../../logger', () => ({
|
|
6
6
|
logger: {
|
|
@@ -11,8 +11,8 @@ jest.mock('../../../logger', () => ({
|
|
|
11
11
|
},
|
|
12
12
|
}));
|
|
13
13
|
// Mock the fetchAssociations function, keep utility functions
|
|
14
|
-
jest.mock('../../../
|
|
15
|
-
...jest.requireActual('../../../
|
|
14
|
+
jest.mock('../../../crm/utils/fetchAssociations', () => ({
|
|
15
|
+
...jest.requireActual('../../../crm/utils/fetchAssociations'),
|
|
16
16
|
fetchAssociations: jest.fn(),
|
|
17
17
|
}));
|
|
18
18
|
// Get reference to the mocked function
|
|
@@ -313,6 +313,125 @@ describe('useAssociations with Pagination', () => {
|
|
|
313
313
|
expect(result.current.isLoading).toBe(false);
|
|
314
314
|
});
|
|
315
315
|
});
|
|
316
|
+
it('should handle null config gracefully', async () => {
|
|
317
|
+
mockFetchAssociations.mockResolvedValue({
|
|
318
|
+
data: {
|
|
319
|
+
results: [],
|
|
320
|
+
hasMore: false,
|
|
321
|
+
nextOffset: 0,
|
|
322
|
+
},
|
|
323
|
+
cleanup: jest.fn(),
|
|
324
|
+
});
|
|
325
|
+
// @ts-expect-error - intentional type issue to check the failure state
|
|
326
|
+
const { result } = renderHook(() => useAssociations(null));
|
|
327
|
+
await waitFor(() => {
|
|
328
|
+
expect(result.current.isLoading).toBe(false);
|
|
329
|
+
expect(result.current.results).toEqual([]);
|
|
330
|
+
expect(result.current.pagination.pageSize).toBe(10); // DEFAULT_PAGE_SIZE
|
|
331
|
+
});
|
|
332
|
+
expect(mockFetchAssociations).toHaveBeenCalledWith(expect.objectContaining({
|
|
333
|
+
toObjectType: undefined,
|
|
334
|
+
properties: undefined,
|
|
335
|
+
pageLength: 10,
|
|
336
|
+
offset: undefined,
|
|
337
|
+
}), expect.any(Object));
|
|
338
|
+
});
|
|
339
|
+
it('should handle undefined config gracefully', async () => {
|
|
340
|
+
mockFetchAssociations.mockResolvedValue({
|
|
341
|
+
data: {
|
|
342
|
+
results: [],
|
|
343
|
+
hasMore: false,
|
|
344
|
+
nextOffset: 0,
|
|
345
|
+
},
|
|
346
|
+
cleanup: jest.fn(),
|
|
347
|
+
});
|
|
348
|
+
// @ts-expect-error - intentional type issue to check the failure state
|
|
349
|
+
const { result } = renderHook(() => useAssociations(undefined));
|
|
350
|
+
await waitFor(() => {
|
|
351
|
+
expect(result.current.isLoading).toBe(false);
|
|
352
|
+
expect(result.current.results).toEqual([]);
|
|
353
|
+
expect(result.current.pagination.pageSize).toBe(10); // DEFAULT_PAGE_SIZE
|
|
354
|
+
});
|
|
355
|
+
expect(mockFetchAssociations).toHaveBeenCalledWith(expect.objectContaining({
|
|
356
|
+
toObjectType: undefined,
|
|
357
|
+
properties: undefined,
|
|
358
|
+
pageLength: 10,
|
|
359
|
+
offset: undefined,
|
|
360
|
+
}), expect.any(Object));
|
|
361
|
+
});
|
|
362
|
+
it('should handle empty config object gracefully', async () => {
|
|
363
|
+
mockFetchAssociations.mockResolvedValue({
|
|
364
|
+
data: {
|
|
365
|
+
results: [],
|
|
366
|
+
hasMore: false,
|
|
367
|
+
nextOffset: 0,
|
|
368
|
+
},
|
|
369
|
+
cleanup: jest.fn(),
|
|
370
|
+
});
|
|
371
|
+
// @ts-expect-error - intentional type issue to check the failure state
|
|
372
|
+
const { result } = renderHook(() => useAssociations({}));
|
|
373
|
+
await waitFor(() => {
|
|
374
|
+
expect(result.current.isLoading).toBe(false);
|
|
375
|
+
expect(result.current.results).toEqual([]);
|
|
376
|
+
expect(result.current.pagination.pageSize).toBe(10); // DEFAULT_PAGE_SIZE
|
|
377
|
+
});
|
|
378
|
+
expect(mockFetchAssociations).toHaveBeenCalledWith(expect.objectContaining({
|
|
379
|
+
toObjectType: undefined,
|
|
380
|
+
properties: undefined,
|
|
381
|
+
pageLength: 10,
|
|
382
|
+
offset: undefined,
|
|
383
|
+
}), expect.any(Object));
|
|
384
|
+
});
|
|
385
|
+
it('should handle config with missing toObjectType', async () => {
|
|
386
|
+
mockFetchAssociations.mockResolvedValue({
|
|
387
|
+
data: {
|
|
388
|
+
results: [],
|
|
389
|
+
hasMore: false,
|
|
390
|
+
nextOffset: 0,
|
|
391
|
+
},
|
|
392
|
+
cleanup: jest.fn(),
|
|
393
|
+
});
|
|
394
|
+
const { result } = renderHook(() =>
|
|
395
|
+
// @ts-expect-error - intentional type issue to check the failure state
|
|
396
|
+
useAssociations({
|
|
397
|
+
properties: ['firstname'],
|
|
398
|
+
pageLength: 5,
|
|
399
|
+
}));
|
|
400
|
+
await waitFor(() => {
|
|
401
|
+
expect(result.current.isLoading).toBe(false);
|
|
402
|
+
expect(result.current.pagination.pageSize).toBe(5);
|
|
403
|
+
});
|
|
404
|
+
expect(mockFetchAssociations).toHaveBeenCalledWith(expect.objectContaining({
|
|
405
|
+
toObjectType: undefined,
|
|
406
|
+
properties: ['firstname'],
|
|
407
|
+
pageLength: 5,
|
|
408
|
+
offset: undefined,
|
|
409
|
+
}), expect.any(Object));
|
|
410
|
+
});
|
|
411
|
+
it('should handle config with missing properties', async () => {
|
|
412
|
+
mockFetchAssociations.mockResolvedValue({
|
|
413
|
+
data: {
|
|
414
|
+
results: [],
|
|
415
|
+
hasMore: false,
|
|
416
|
+
nextOffset: 0,
|
|
417
|
+
},
|
|
418
|
+
cleanup: jest.fn(),
|
|
419
|
+
});
|
|
420
|
+
const { result } = renderHook(() => useAssociations({
|
|
421
|
+
toObjectType: '0-1',
|
|
422
|
+
pageLength: 8,
|
|
423
|
+
}));
|
|
424
|
+
await waitFor(() => {
|
|
425
|
+
expect(result.current.isLoading).toBe(false);
|
|
426
|
+
expect(result.current.pagination.pageSize).toBe(8);
|
|
427
|
+
});
|
|
428
|
+
expect(mockFetchAssociations).toHaveBeenCalledWith(expect.objectContaining({
|
|
429
|
+
toObjectType: '0-1',
|
|
430
|
+
properties: undefined,
|
|
431
|
+
pageLength: 8,
|
|
432
|
+
offset: undefined,
|
|
433
|
+
}), expect.any(Object));
|
|
434
|
+
});
|
|
316
435
|
});
|
|
317
436
|
describe('options handling', () => {
|
|
318
437
|
it('should pass formatting options to fetchAssociations', async () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { renderHook, waitFor } from '@testing-library/react';
|
|
2
|
-
import { useCrmProperties } from '../../../
|
|
2
|
+
import { useCrmProperties } from '../../../crm/hooks/useCrmProperties';
|
|
3
3
|
// Mock the logger module
|
|
4
4
|
jest.mock('../../../logger', () => ({
|
|
5
5
|
logger: {
|
|
@@ -10,9 +10,9 @@ jest.mock('../../../logger', () => ({
|
|
|
10
10
|
},
|
|
11
11
|
}));
|
|
12
12
|
// Mock the fetchCrmProperties module
|
|
13
|
-
jest.mock('../../../
|
|
13
|
+
jest.mock('../../../crm/utils/fetchCrmProperties');
|
|
14
14
|
const mockFetchCrmProperties = jest.fn();
|
|
15
|
-
import * as fetchCrmPropertiesModule from '../../../
|
|
15
|
+
import * as fetchCrmPropertiesModule from '../../../crm/utils/fetchCrmProperties';
|
|
16
16
|
fetchCrmPropertiesModule.fetchCrmProperties = mockFetchCrmProperties;
|
|
17
17
|
describe('useCrmProperties', () => {
|
|
18
18
|
let originalError;
|
|
@@ -239,4 +239,18 @@ describe('useCrmProperties', () => {
|
|
|
239
239
|
expect(mockCleanup1).toHaveBeenCalledTimes(1);
|
|
240
240
|
});
|
|
241
241
|
});
|
|
242
|
+
it('should handle non-array propertyNames without crashing during stabilization', async () => {
|
|
243
|
+
const errorMessage = 'Properties must be an array of strings';
|
|
244
|
+
mockFetchCrmProperties.mockRejectedValue(new Error(errorMessage));
|
|
245
|
+
const nonArrayPropertyNames = 2;
|
|
246
|
+
const { result } = renderHook(() =>
|
|
247
|
+
// @ts-expect-error - we are deliberately testing a bad type
|
|
248
|
+
useCrmProperties(nonArrayPropertyNames));
|
|
249
|
+
await waitFor(() => {
|
|
250
|
+
expect(result.current.error).toBeInstanceOf(Error);
|
|
251
|
+
expect(result.current.error?.message).toBe(errorMessage);
|
|
252
|
+
expect(result.current.isLoading).toBe(false);
|
|
253
|
+
});
|
|
254
|
+
expect(mockFetchCrmProperties).toHaveBeenCalledWith(2, expect.any(Function), {});
|
|
255
|
+
});
|
|
242
256
|
});
|
|
@@ -8,7 +8,7 @@ Object.defineProperty(global, 'self', {
|
|
|
8
8
|
value: mockSelf,
|
|
9
9
|
writable: true,
|
|
10
10
|
});
|
|
11
|
-
import { fetchAssociations, calculatePaginationFlags, } from '../../../
|
|
11
|
+
import { fetchAssociations, calculatePaginationFlags, } from '../../../crm/utils/fetchAssociations';
|
|
12
12
|
describe('fetchAssociations', () => {
|
|
13
13
|
// Helper functions
|
|
14
14
|
const createMockResponse = (data, overrides = {}) => ({
|
|
@@ -8,7 +8,7 @@ Object.defineProperty(global, 'self', {
|
|
|
8
8
|
value: mockSelf,
|
|
9
9
|
writable: true,
|
|
10
10
|
});
|
|
11
|
-
import { fetchCrmProperties } from '../../../
|
|
11
|
+
import { fetchCrmProperties } from '../../../crm/utils/fetchCrmProperties';
|
|
12
12
|
const DEFAULT_OPTIONS = {};
|
|
13
13
|
describe('fetchCrmProperties', () => {
|
|
14
14
|
beforeEach(() => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { expectAssignable } from 'tsd';
|
|
2
|
+
// Test app home extension point
|
|
3
|
+
expectAssignable({
|
|
4
|
+
actions: {
|
|
5
|
+
addAlert: () => { },
|
|
6
|
+
copyTextToClipboard: async () => { },
|
|
7
|
+
closeOverlay: () => { },
|
|
8
|
+
reloadPage: () => { },
|
|
9
|
+
openIframeModal: () => { },
|
|
10
|
+
},
|
|
11
|
+
context: {
|
|
12
|
+
user: {
|
|
13
|
+
id: 123,
|
|
14
|
+
emails: ['test@example.com'],
|
|
15
|
+
email: 'test@example.com',
|
|
16
|
+
firstName: 'John',
|
|
17
|
+
lastName: 'Doe',
|
|
18
|
+
roles: [],
|
|
19
|
+
teams: [],
|
|
20
|
+
permissions: [],
|
|
21
|
+
},
|
|
22
|
+
portal: {
|
|
23
|
+
id: 456,
|
|
24
|
+
timezone: 'America/New_York',
|
|
25
|
+
},
|
|
26
|
+
location: 'home',
|
|
27
|
+
},
|
|
28
|
+
customComponents: {},
|
|
29
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type FetchAssociationsRequest, type AssociationResult } from '../
|
|
2
|
-
import { type FetchCrmPropertiesOptions } from '../
|
|
1
|
+
import { type FetchAssociationsRequest, type AssociationResult } from '../utils/fetchAssociations';
|
|
2
|
+
import { type FetchCrmPropertiesOptions } from '../utils/fetchCrmProperties';
|
|
3
3
|
export interface UseAssociationsOptions {
|
|
4
4
|
propertiesToFormat?: 'all' | string[];
|
|
5
5
|
formattingOptions?: FetchCrmPropertiesOptions['formattingOptions'];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useReducer, useMemo, useRef, useCallback } from 'react';
|
|
2
2
|
import { logger } from '../../logger';
|
|
3
|
-
import { fetchAssociations, DEFAULT_PAGE_SIZE, calculatePaginationFlags, } from '../
|
|
3
|
+
import { fetchAssociations, DEFAULT_PAGE_SIZE, calculatePaginationFlags, } from '../utils/fetchAssociations';
|
|
4
4
|
function createInitialState(pageSize) {
|
|
5
5
|
return {
|
|
6
6
|
results: [],
|
|
@@ -81,7 +81,7 @@ function associationsReducer(state, action) {
|
|
|
81
81
|
}
|
|
82
82
|
const DEFAULT_OPTIONS = {};
|
|
83
83
|
export function useAssociations(config, options = DEFAULT_OPTIONS) {
|
|
84
|
-
const pageSize = config
|
|
84
|
+
const pageSize = config?.pageLength ?? DEFAULT_PAGE_SIZE;
|
|
85
85
|
const [state, dispatch] = useReducer(associationsReducer, useMemo(() => createInitialState(pageSize), [pageSize]));
|
|
86
86
|
// Log experimental warning once on mount
|
|
87
87
|
useEffect(() => {
|
|
@@ -141,8 +141,8 @@ export function useAssociations(config, options = DEFAULT_OPTIONS) {
|
|
|
141
141
|
dispatch({ type: 'FETCH_START' });
|
|
142
142
|
// Build request using current offset token
|
|
143
143
|
const request = {
|
|
144
|
-
toObjectType: stableConfig
|
|
145
|
-
properties: stableConfig
|
|
144
|
+
toObjectType: stableConfig?.toObjectType,
|
|
145
|
+
properties: stableConfig?.properties,
|
|
146
146
|
pageLength: pageSize,
|
|
147
147
|
offset: state.currentOffset,
|
|
148
148
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useEffect, useReducer, useMemo, useRef } from 'react';
|
|
2
2
|
import { logger } from '../../logger';
|
|
3
|
-
import { fetchCrmProperties, } from '../
|
|
3
|
+
import { fetchCrmProperties, } from '../utils/fetchCrmProperties';
|
|
4
4
|
const initialState = {
|
|
5
5
|
properties: {},
|
|
6
6
|
error: null,
|
|
@@ -56,6 +56,9 @@ export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
|
|
|
56
56
|
const lastOptionsRef = useRef();
|
|
57
57
|
const lastOptionsKeyRef = useRef();
|
|
58
58
|
const stablePropertyNames = useMemo(() => {
|
|
59
|
+
if (!Array.isArray(propertyNames)) {
|
|
60
|
+
return propertyNames;
|
|
61
|
+
}
|
|
59
62
|
const sortedNames = [...propertyNames].sort();
|
|
60
63
|
const propertyNamesKey = JSON.stringify(sortedNames);
|
|
61
64
|
if (propertyNamesKey === lastPropertyNamesKeyRef.current) {
|
package/dist/crm/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions } from './components';
|
|
2
2
|
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, };
|
|
3
|
+
export { useCrmProperties } from './hooks/useCrmProperties';
|
|
4
|
+
export { useAssociations } from './hooks/useAssociations';
|
package/dist/crm/index.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, } from './components';
|
|
2
2
|
export { CrmPropertyList, CrmAssociationTable, CrmDataHighlight, CrmReport, CrmAssociationPivot, CrmAssociationPropertyList, CrmAssociationStageTracker, CrmSimpleDeadline, CrmStageTracker, CrmStatistics, CrmActionButton, CrmActionLink, CrmCardActions, };
|
|
3
|
+
export { useCrmProperties } from './hooks/useCrmProperties';
|
|
4
|
+
export { useAssociations } from './hooks/useAssociations';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type * as types from '../types';
|
|
2
2
|
import type * as experimentalTypes from './types';
|
|
3
|
-
export { useCrmProperties } from '
|
|
4
|
-
export { useAssociations } from '
|
|
3
|
+
export { useCrmProperties } from '../crm/hooks/useCrmProperties';
|
|
4
|
+
export { useAssociations } from '../crm/hooks/useAssociations';
|
|
5
5
|
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
6
6
|
declare const Iframe: "Iframe" & {
|
|
7
7
|
readonly type?: "Iframe" | undefined;
|
|
@@ -78,22 +78,4 @@ declare const FileInput: "FileInput" & {
|
|
|
78
78
|
readonly props?: experimentalTypes.FileInputProps | undefined;
|
|
79
79
|
readonly children?: true | undefined;
|
|
80
80
|
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"FileInput", experimentalTypes.FileInputProps, true>>;
|
|
81
|
-
|
|
82
|
-
declare const HeaderActions: "HeaderActions" & {
|
|
83
|
-
readonly type?: "HeaderActions" | undefined;
|
|
84
|
-
readonly props?: experimentalTypes.HeaderActionsProps | undefined;
|
|
85
|
-
readonly children?: true | undefined;
|
|
86
|
-
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"HeaderActions", experimentalTypes.HeaderActionsProps, true>>;
|
|
87
|
-
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
88
|
-
declare const PrimaryHeaderActionButton: "PrimaryHeaderActionButton" & {
|
|
89
|
-
readonly type?: "PrimaryHeaderActionButton" | undefined;
|
|
90
|
-
readonly props?: experimentalTypes.HeaderActionButtonProps | undefined;
|
|
91
|
-
readonly children?: true | undefined;
|
|
92
|
-
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"PrimaryHeaderActionButton", experimentalTypes.HeaderActionButtonProps, true>>;
|
|
93
|
-
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
94
|
-
declare const SecondaryHeaderActionButton: "SecondaryHeaderActionButton" & {
|
|
95
|
-
readonly type?: "SecondaryHeaderActionButton" | undefined;
|
|
96
|
-
readonly props?: experimentalTypes.HeaderActionButtonProps | undefined;
|
|
97
|
-
readonly children?: true | undefined;
|
|
98
|
-
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"SecondaryHeaderActionButton", experimentalTypes.HeaderActionButtonProps, true>>;
|
|
99
|
-
export { Iframe, MediaObject, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, HeaderActions, PrimaryHeaderActionButton, SecondaryHeaderActionButton, };
|
|
81
|
+
export { Iframe, MediaObject, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRemoteReactComponent } from '@remote-ui/react';
|
|
2
|
-
export { useCrmProperties } from '
|
|
3
|
-
export { useAssociations } from '
|
|
2
|
+
export { useCrmProperties } from '../crm/hooks/useCrmProperties';
|
|
3
|
+
export { useAssociations } from '../crm/hooks/useAssociations';
|
|
4
4
|
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
5
5
|
const Iframe = createRemoteReactComponent('Iframe');
|
|
6
6
|
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
@@ -35,14 +35,4 @@ const ExpandableText = createRemoteReactComponent('ExpandableText');
|
|
|
35
35
|
*/
|
|
36
36
|
const Popover = createRemoteReactComponent('Popover');
|
|
37
37
|
const FileInput = createRemoteReactComponent('FileInput');
|
|
38
|
-
|
|
39
|
-
const HeaderActions = createRemoteReactComponent('HeaderActions');
|
|
40
|
-
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
41
|
-
const PrimaryHeaderActionButton = createRemoteReactComponent('PrimaryHeaderActionButton', {
|
|
42
|
-
fragmentProps: ['overlay'],
|
|
43
|
-
});
|
|
44
|
-
/** @experimental This component is experimental. Avoid using it in production due to potential breaking changes. Your feedback is valuable for improvements. Stay tuned for updates. */
|
|
45
|
-
const SecondaryHeaderActionButton = createRemoteReactComponent('SecondaryHeaderActionButton', {
|
|
46
|
-
fragmentProps: ['overlay'],
|
|
47
|
-
});
|
|
48
|
-
export { Iframe, MediaObject, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, HeaderActions, PrimaryHeaderActionButton, SecondaryHeaderActionButton, };
|
|
38
|
+
export { Iframe, MediaObject, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, };
|
|
@@ -238,29 +238,8 @@ export interface BaseInputProps<T = string, V = string> {
|
|
|
238
238
|
*/
|
|
239
239
|
onFocus?: (value: V) => void;
|
|
240
240
|
}
|
|
241
|
+
export {};
|
|
241
242
|
/**
|
|
242
243
|
* @ignore
|
|
243
244
|
* @experimental do not use in production
|
|
244
245
|
*/
|
|
245
|
-
/**
|
|
246
|
-
* @ignore
|
|
247
|
-
* @experimental do not use in production
|
|
248
|
-
*/
|
|
249
|
-
export interface HeaderActionsProps {
|
|
250
|
-
children: ReactNode;
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* @ignore
|
|
254
|
-
* @experimental do not use in production
|
|
255
|
-
*/
|
|
256
|
-
export interface HeaderActionButtonProps {
|
|
257
|
-
onClick?: ReactionsHandler<ExtensionEvent>;
|
|
258
|
-
href?: string | {
|
|
259
|
-
url: string;
|
|
260
|
-
external?: boolean;
|
|
261
|
-
};
|
|
262
|
-
disabled?: boolean;
|
|
263
|
-
children: ReactNode;
|
|
264
|
-
overlay?: RemoteFragment;
|
|
265
|
-
}
|
|
266
|
-
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type * as types from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* The `HeaderActions` component renders a container for action buttons in the app home header. It accepts `PrimaryHeaderActionButton` and `SecondaryHeaderActionButton` as children.
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
export declare const HeaderActions: "HeaderActions" & {
|
|
7
|
+
readonly type?: "HeaderActions" | undefined;
|
|
8
|
+
readonly props?: types.HeaderActionsProps | undefined;
|
|
9
|
+
readonly children?: true | undefined;
|
|
10
|
+
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"HeaderActions", types.HeaderActionsProps, true>>;
|
|
11
|
+
/**
|
|
12
|
+
* The `PrimaryHeaderActionButton` component renders a primary action button in the app home header. This button is styled as the main call-to-action and only one should be used per `HeaderActions` container.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export declare const PrimaryHeaderActionButton: "PrimaryHeaderActionButton" & {
|
|
16
|
+
readonly type?: "PrimaryHeaderActionButton" | undefined;
|
|
17
|
+
readonly props?: types.HeaderActionButtonProps | undefined;
|
|
18
|
+
readonly children?: true | undefined;
|
|
19
|
+
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"PrimaryHeaderActionButton", types.HeaderActionButtonProps, true>>;
|
|
20
|
+
/**
|
|
21
|
+
* The `SecondaryHeaderActionButton` component renders a secondary action button in the app home header. Multiple secondary actions can be used and they will be grouped appropriately in the header.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
export declare const SecondaryHeaderActionButton: "SecondaryHeaderActionButton" & {
|
|
25
|
+
readonly type?: "SecondaryHeaderActionButton" | undefined;
|
|
26
|
+
readonly props?: types.HeaderActionButtonProps | undefined;
|
|
27
|
+
readonly children?: true | undefined;
|
|
28
|
+
} & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"SecondaryHeaderActionButton", types.HeaderActionButtonProps, true>>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRemoteReactComponent } from '@remote-ui/react';
|
|
2
|
+
/**
|
|
3
|
+
* The `HeaderActions` component renders a container for action buttons in the app home header. It accepts `PrimaryHeaderActionButton` and `SecondaryHeaderActionButton` as children.
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
export const HeaderActions = createRemoteReactComponent('HeaderActions');
|
|
7
|
+
/**
|
|
8
|
+
* The `PrimaryHeaderActionButton` component renders a primary action button in the app home header. This button is styled as the main call-to-action and only one should be used per `HeaderActions` container.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export const PrimaryHeaderActionButton = createRemoteReactComponent('PrimaryHeaderActionButton', {
|
|
12
|
+
fragmentProps: ['overlay'],
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* The `SecondaryHeaderActionButton` component renders a secondary action button in the app home header. Multiple secondary actions can be used and they will be grouped appropriately in the header.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
export const SecondaryHeaderActionButton = createRemoteReactComponent('SecondaryHeaderActionButton', {
|
|
19
|
+
fragmentProps: ['overlay'],
|
|
20
|
+
});
|
package/dist/types.d.ts
CHANGED
|
@@ -239,6 +239,7 @@ export interface UiePlatformActions {
|
|
|
239
239
|
copyTextToClipboard: Clipboard['writeText'];
|
|
240
240
|
closeOverlay: CloseOverlayAction;
|
|
241
241
|
reloadPage: ReloadPageAction;
|
|
242
|
+
openIframeModal: OpenIframeModalAction;
|
|
242
243
|
}
|
|
243
244
|
/**
|
|
244
245
|
* The props type for {@link !components.Accordion}.
|
|
@@ -309,6 +310,42 @@ export interface AlertProps {
|
|
|
309
310
|
*/
|
|
310
311
|
variant?: 'info' | 'warning' | 'success' | 'error' | 'danger' | 'tip';
|
|
311
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* The props type for {@link !components.HeaderActions}.
|
|
315
|
+
*
|
|
316
|
+
* @category Component Props
|
|
317
|
+
*/
|
|
318
|
+
export interface HeaderActionsProps {
|
|
319
|
+
/**
|
|
320
|
+
* Sets the content that will render inside the HeaderActions. This prop is passed implicitly by providing sub-components.
|
|
321
|
+
*/
|
|
322
|
+
children: ReactNode;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* The props type for {@link !components.HeaderActions}.
|
|
326
|
+
*
|
|
327
|
+
* @category Component Props
|
|
328
|
+
*/
|
|
329
|
+
export interface HeaderActionButtonProps extends OverlayComponentProps {
|
|
330
|
+
/**
|
|
331
|
+
* A function that will be invoked when the button is clicked. Do not use this function for submitting a form; use Form's `onSubmit` function instead.
|
|
332
|
+
*
|
|
333
|
+
* @event
|
|
334
|
+
*/
|
|
335
|
+
onClick?: ReactionsHandler<ExtensionEvent>;
|
|
336
|
+
/**
|
|
337
|
+
* A URL that will be opened when the button is clicked. If the value is a URL external to `hubspot.com` it will be opened in a new tab.
|
|
338
|
+
*/
|
|
339
|
+
href?: HrefProp;
|
|
340
|
+
/**
|
|
341
|
+
* Determines whether or not the button should be disabled.
|
|
342
|
+
*/
|
|
343
|
+
disabled?: boolean;
|
|
344
|
+
/**
|
|
345
|
+
* Sets the content that will render inside the HeaderActionButton. This prop is passed implicitly by providing sub-components.
|
|
346
|
+
*/
|
|
347
|
+
children: ReactNode;
|
|
348
|
+
}
|
|
312
349
|
/**
|
|
313
350
|
* The props type for {@link !components.ButtonRow}.
|
|
314
351
|
*
|
|
@@ -2569,10 +2606,12 @@ export interface AppContext {
|
|
|
2569
2606
|
appName?: string;
|
|
2570
2607
|
cardTitle?: string;
|
|
2571
2608
|
}
|
|
2609
|
+
type ProfileVariableValue = string | number | bigint | boolean;
|
|
2572
2610
|
/** @ignore */
|
|
2573
2611
|
export interface BaseContext {
|
|
2574
2612
|
user: UserContext;
|
|
2575
2613
|
portal: PortalContext;
|
|
2614
|
+
variables?: Record<string, ProfileVariableValue>;
|
|
2576
2615
|
}
|
|
2577
2616
|
/** @ignore */
|
|
2578
2617
|
export interface CrmContext extends BaseContext {
|
|
@@ -2923,7 +2962,7 @@ export interface SettingsExtensionPoint extends ExtensionPointContract {
|
|
|
2923
2962
|
}
|
|
2924
2963
|
/** @ignore */
|
|
2925
2964
|
export interface AppHomeExtensionPoint extends ExtensionPointContract {
|
|
2926
|
-
actions: AppHomeActions;
|
|
2965
|
+
actions: AppHomeActions & UiePlatformActions;
|
|
2927
2966
|
context: AppHomeContext;
|
|
2928
2967
|
}
|
|
2929
2968
|
export interface ExampleCrmComponentProps {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/ui-extensions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"watch": "npm run clean && tsc --watch",
|
|
12
12
|
"prepare": "npm run build",
|
|
13
13
|
"lint": "echo 'No linter configured for @hubspot/ui-extensions'",
|
|
14
|
-
"test": "jest",
|
|
15
|
-
"jest": "jest --watch"
|
|
14
|
+
"test": "jest && tsd",
|
|
15
|
+
"jest": "jest --watch",
|
|
16
|
+
"test:types": "tsd"
|
|
16
17
|
},
|
|
17
18
|
"files": [
|
|
18
19
|
"dist"
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
"exports": {
|
|
24
25
|
".": "./dist/index.js",
|
|
25
26
|
"./crm": "./dist/crm/index.js",
|
|
27
|
+
"./pages/home": "./dist/pages/home/components.js",
|
|
26
28
|
"./experimental": "./dist/experimental/index.js",
|
|
27
29
|
"./experimental/testing": "./dist/experimental/testing/index.js",
|
|
28
30
|
"./experimental/testing/jest-matchers": "./dist/experimental/testing/jest/matchers/index.js"
|
|
@@ -64,7 +66,11 @@
|
|
|
64
66
|
"react-dom": "^18.2.0",
|
|
65
67
|
"react-reconciler": "^0.29.0",
|
|
66
68
|
"ts-jest": "^29.1.1",
|
|
69
|
+
"tsd": "^0.33.0",
|
|
67
70
|
"typescript": "5.0.4"
|
|
68
71
|
},
|
|
69
|
-
"
|
|
72
|
+
"tsd": {
|
|
73
|
+
"directory": "src/__tests__/test-d"
|
|
74
|
+
},
|
|
75
|
+
"gitHead": "34ce86d7cfaa1f163bf67838bbb56c054d0f72cc"
|
|
70
76
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|