@hubspot/ui-extensions 0.9.3 → 0.9.5

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,176 @@
1
+ import { useEffect, useReducer, useMemo, useRef, useCallback } from 'react';
2
+ import { logger } from '../../logger';
3
+ import { fetchAssociations, DEFAULT_PAGE_SIZE, pageToOffset, calculatePaginationFlags, } from '../crm/fetchAssociations';
4
+ function createInitialState(pageSize) {
5
+ return {
6
+ results: [],
7
+ error: null,
8
+ isLoading: true,
9
+ currentPage: 1,
10
+ pageSize,
11
+ hasMore: false,
12
+ };
13
+ }
14
+ function associationsReducer(state, action) {
15
+ switch (action.type) {
16
+ case 'FETCH_START':
17
+ return {
18
+ ...state,
19
+ isLoading: true,
20
+ error: null,
21
+ };
22
+ case 'FETCH_SUCCESS':
23
+ return {
24
+ ...state,
25
+ isLoading: false,
26
+ results: action.payload.results,
27
+ hasMore: action.payload.hasMore,
28
+ error: null,
29
+ };
30
+ case 'FETCH_ERROR':
31
+ return {
32
+ ...state,
33
+ isLoading: false,
34
+ error: action.payload,
35
+ results: [],
36
+ hasMore: false,
37
+ };
38
+ case 'NEXT_PAGE':
39
+ return {
40
+ ...state,
41
+ currentPage: state.currentPage + 1,
42
+ };
43
+ case 'PREVIOUS_PAGE':
44
+ return {
45
+ ...state,
46
+ currentPage: Math.max(1, state.currentPage - 1),
47
+ };
48
+ case 'RESET':
49
+ return {
50
+ ...state,
51
+ currentPage: 1,
52
+ results: [],
53
+ hasMore: false,
54
+ error: null,
55
+ };
56
+ default:
57
+ return state;
58
+ }
59
+ }
60
+ const DEFAULT_OPTIONS = {};
61
+ export function useAssociations(config, options = DEFAULT_OPTIONS) {
62
+ const pageSize = config.pageLength ?? DEFAULT_PAGE_SIZE;
63
+ const [state, dispatch] = useReducer(associationsReducer, useMemo(() => createInitialState(pageSize), [pageSize]));
64
+ // Log experimental warning once on mount
65
+ useEffect(() => {
66
+ logger.warn('useAssociations is an experimental hook and might change or be removed in the future.');
67
+ }, []);
68
+ /**
69
+ * HOOK OPTIMIZATION:
70
+ *
71
+ * Create stable references for config and options to prevent unnecessary re-renders and API calls.
72
+ * Then, external developers can pass inline objects without worrying about memoization
73
+ * We handle the deep equality comparison ourselves, and return the same object reference when content is equivalent.
74
+ */
75
+ const lastConfigRef = useRef();
76
+ const lastConfigKeyRef = useRef();
77
+ const lastOptionsRef = useRef();
78
+ const lastOptionsKeyRef = useRef();
79
+ const stableConfig = useMemo(() => {
80
+ const configKey = JSON.stringify(config);
81
+ if (configKey === lastConfigKeyRef.current) {
82
+ return lastConfigRef.current;
83
+ }
84
+ lastConfigKeyRef.current = configKey;
85
+ lastConfigRef.current = config;
86
+ return config;
87
+ }, [config]);
88
+ const stableOptions = useMemo(() => {
89
+ const optionsKey = JSON.stringify(options);
90
+ if (optionsKey === lastOptionsKeyRef.current) {
91
+ return lastOptionsRef.current;
92
+ }
93
+ lastOptionsKeyRef.current = optionsKey;
94
+ lastOptionsRef.current = options;
95
+ return options;
96
+ }, [options]);
97
+ // Pagination actions
98
+ const nextPage = useCallback(() => {
99
+ const paginationFlags = calculatePaginationFlags(state.currentPage, state.hasMore);
100
+ if (paginationFlags.hasNextPage) {
101
+ dispatch({ type: 'NEXT_PAGE' });
102
+ }
103
+ }, [state.currentPage, state.hasMore]);
104
+ const previousPage = useCallback(() => {
105
+ const paginationFlags = calculatePaginationFlags(state.currentPage, state.hasMore);
106
+ if (paginationFlags.hasPreviousPage) {
107
+ dispatch({ type: 'PREVIOUS_PAGE' });
108
+ }
109
+ }, [state.currentPage, state.hasMore]);
110
+ const reset = useCallback(() => {
111
+ dispatch({ type: 'RESET' });
112
+ }, []);
113
+ // Fetch the associations
114
+ useEffect(() => {
115
+ let cancelled = false;
116
+ let cleanup = null;
117
+ const fetchData = async () => {
118
+ try {
119
+ dispatch({ type: 'FETCH_START' });
120
+ // Build request using current page and pagination utilities
121
+ const request = {
122
+ toObjectType: stableConfig.toObjectType,
123
+ properties: stableConfig.properties,
124
+ pageLength: pageSize,
125
+ offset: pageToOffset(state.currentPage, pageSize),
126
+ };
127
+ const result = await fetchAssociations(request, {
128
+ propertiesToFormat: stableOptions.propertiesToFormat,
129
+ formattingOptions: stableOptions.formattingOptions,
130
+ });
131
+ if (!cancelled) {
132
+ dispatch({
133
+ type: 'FETCH_SUCCESS',
134
+ payload: {
135
+ results: result.data.results,
136
+ hasMore: result.data.hasMore,
137
+ },
138
+ });
139
+ cleanup = result.cleanup;
140
+ }
141
+ }
142
+ catch (err) {
143
+ if (!cancelled) {
144
+ const errorData = err instanceof Error
145
+ ? err
146
+ : new Error('Failed to fetch associations');
147
+ dispatch({ type: 'FETCH_ERROR', payload: errorData });
148
+ }
149
+ }
150
+ };
151
+ fetchData();
152
+ return () => {
153
+ cancelled = true;
154
+ // Call cleanup function to release resources
155
+ if (cleanup) {
156
+ cleanup();
157
+ }
158
+ };
159
+ }, [stableConfig, stableOptions, state.currentPage, pageSize]);
160
+ // Calculate pagination flags
161
+ const paginationFlags = calculatePaginationFlags(state.currentPage, state.hasMore);
162
+ return {
163
+ results: state.results,
164
+ error: state.error,
165
+ isLoading: state.isLoading,
166
+ pagination: {
167
+ hasNextPage: paginationFlags.hasNextPage,
168
+ hasPreviousPage: paginationFlags.hasPreviousPage,
169
+ currentPage: state.currentPage,
170
+ pageSize: state.pageSize,
171
+ nextPage,
172
+ previousPage,
173
+ reset,
174
+ },
175
+ };
176
+ }
@@ -1,6 +1,37 @@
1
- import { useEffect, useState, useMemo, useRef } from 'react';
1
+ import { useEffect, useReducer, useMemo, useRef } from 'react';
2
2
  import { logger } from '../../logger';
3
3
  import { fetchCrmProperties, } from '../crm/fetchCrmProperties';
4
+ const initialState = {
5
+ properties: {},
6
+ error: null,
7
+ isLoading: true,
8
+ };
9
+ function crmPropertiesReducer(state, action) {
10
+ switch (action.type) {
11
+ case 'FETCH_START':
12
+ return {
13
+ ...state,
14
+ isLoading: true,
15
+ error: null,
16
+ };
17
+ case 'FETCH_SUCCESS':
18
+ return {
19
+ ...state,
20
+ isLoading: false,
21
+ properties: action.payload,
22
+ error: null,
23
+ };
24
+ case 'FETCH_ERROR':
25
+ return {
26
+ ...state,
27
+ isLoading: false,
28
+ error: action.payload,
29
+ properties: {},
30
+ };
31
+ default:
32
+ return state;
33
+ }
34
+ }
4
35
  const DEFAULT_OPTIONS = {};
5
36
  /**
6
37
  * A hook for using and managing CRM properties.
@@ -8,9 +39,7 @@ const DEFAULT_OPTIONS = {};
8
39
  * @experimental This hook is experimental and might change or be removed in future versions.
9
40
  */
10
41
  export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
11
- const [properties, setProperties] = useState({});
12
- const [isLoading, setIsLoading] = useState(true);
13
- const [error, setError] = useState(null);
42
+ const [state, dispatch] = useReducer(crmPropertiesReducer, initialState);
14
43
  // Log experimental warning once on mount
15
44
  useEffect(() => {
16
45
  logger.warn('useCrmProperties is an experimental hook and might change or be removed in the future.');
@@ -51,11 +80,14 @@ export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
51
80
  let cleanup = null;
52
81
  const fetchData = async () => {
53
82
  try {
54
- setIsLoading(true);
55
- setError(null);
56
- const result = await fetchCrmProperties(stablePropertyNames, setProperties, stableOptions);
83
+ dispatch({ type: 'FETCH_START' });
84
+ const result = await fetchCrmProperties(stablePropertyNames, (data) => {
85
+ if (!cancelled) {
86
+ dispatch({ type: 'FETCH_SUCCESS', payload: data });
87
+ }
88
+ }, stableOptions);
57
89
  if (!cancelled) {
58
- setProperties(result.data);
90
+ dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
59
91
  cleanup = result.cleanup;
60
92
  }
61
93
  }
@@ -64,13 +96,7 @@ export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
64
96
  const errorData = err instanceof Error
65
97
  ? err
66
98
  : new Error('Failed to fetch CRM properties');
67
- setError(errorData);
68
- setProperties({});
69
- }
70
- }
71
- finally {
72
- if (!cancelled) {
73
- setIsLoading(false);
99
+ dispatch({ type: 'FETCH_ERROR', payload: errorData });
74
100
  }
75
101
  }
76
102
  };
@@ -83,9 +109,5 @@ export function useCrmProperties(propertyNames, options = DEFAULT_OPTIONS) {
83
109
  }
84
110
  };
85
111
  }, [stablePropertyNames, stableOptions]);
86
- return {
87
- properties,
88
- error,
89
- isLoading,
90
- };
112
+ return state;
91
113
  }
@@ -1,6 +1,7 @@
1
1
  import type * as types from '../types';
2
2
  import type * as experimentalTypes from './types';
3
3
  export { useCrmProperties } from './hooks/useCrmProperties';
4
+ export { useAssociations } from './hooks/useAssociations';
4
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. */
5
6
  declare const Iframe: "Iframe" & {
6
7
  readonly type?: "Iframe" | undefined;
@@ -83,18 +84,28 @@ declare const FileInput: "FileInput" & {
83
84
  readonly props?: experimentalTypes.FileInputProps | undefined;
84
85
  readonly children?: true | undefined;
85
86
  } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"FileInput", experimentalTypes.FileInputProps, true>>;
86
- /**
87
- * The TimeInput component renders an input field where a user can select a time.
88
- */
89
- declare const TimeInput: "TimeInput" & {
90
- readonly type?: "TimeInput" | undefined;
91
- readonly props?: experimentalTypes.TimeInputProps | undefined;
92
- readonly children?: true | undefined;
93
- } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"TimeInput", experimentalTypes.TimeInputProps, true>>;
94
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. */
95
88
  declare const CurrencyInput: "CurrencyInput" & {
96
89
  readonly type?: "CurrencyInput" | undefined;
97
90
  readonly props?: experimentalTypes.CurrencyInputProps | undefined;
98
91
  readonly children?: true | undefined;
99
92
  } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"CurrencyInput", experimentalTypes.CurrencyInputProps, true>>;
100
- export { Iframe, MediaObject, Inline, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, TimeInput, CurrencyInput, };
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 HeaderActions: "HeaderActions" & {
95
+ readonly type?: "HeaderActions" | undefined;
96
+ readonly props?: experimentalTypes.HeaderActionsProps | undefined;
97
+ readonly children?: true | undefined;
98
+ } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"HeaderActions", experimentalTypes.HeaderActionsProps, true>>;
99
+ /** @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. */
100
+ declare const PrimaryHeaderActionButton: "PrimaryHeaderActionButton" & {
101
+ readonly type?: "PrimaryHeaderActionButton" | undefined;
102
+ readonly props?: experimentalTypes.HeaderActionButtonProps | undefined;
103
+ readonly children?: true | undefined;
104
+ } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"PrimaryHeaderActionButton", experimentalTypes.HeaderActionButtonProps, true>>;
105
+ /** @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. */
106
+ declare const SecondaryHeaderActionButton: "SecondaryHeaderActionButton" & {
107
+ readonly type?: "SecondaryHeaderActionButton" | undefined;
108
+ readonly props?: experimentalTypes.HeaderActionButtonProps | undefined;
109
+ readonly children?: true | undefined;
110
+ } & import("@remote-ui/react").ReactComponentTypeFromRemoteComponentType<import("@remote-ui/types").RemoteComponentType<"SecondaryHeaderActionButton", experimentalTypes.HeaderActionButtonProps, true>>;
111
+ export { Iframe, MediaObject, Inline, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, CurrencyInput, HeaderActions, PrimaryHeaderActionButton, SecondaryHeaderActionButton, };
@@ -1,5 +1,6 @@
1
1
  import { createRemoteReactComponent } from '@remote-ui/react';
2
2
  export { useCrmProperties } from './hooks/useCrmProperties';
3
+ export { useAssociations } from './hooks/useAssociations';
3
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. */
4
5
  const Iframe = createRemoteReactComponent('Iframe');
5
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. */
@@ -36,10 +37,16 @@ const ExpandableText = createRemoteReactComponent('ExpandableText');
36
37
  */
37
38
  const Popover = createRemoteReactComponent('Popover');
38
39
  const FileInput = createRemoteReactComponent('FileInput');
39
- /**
40
- * The TimeInput component renders an input field where a user can select a time.
41
- */
42
- const TimeInput = createRemoteReactComponent('TimeInput');
43
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. */
44
41
  const CurrencyInput = createRemoteReactComponent('CurrencyInput');
45
- export { Iframe, MediaObject, Inline, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, TimeInput, CurrencyInput, };
42
+ /** @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. */
43
+ const HeaderActions = createRemoteReactComponent('HeaderActions');
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 PrimaryHeaderActionButton = createRemoteReactComponent('PrimaryHeaderActionButton', {
46
+ fragmentProps: ['overlay'],
47
+ });
48
+ /** @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. */
49
+ const SecondaryHeaderActionButton = createRemoteReactComponent('SecondaryHeaderActionButton', {
50
+ fragmentProps: ['overlay'],
51
+ });
52
+ export { Iframe, MediaObject, Inline, Stack2, Center, SimpleGrid, GridItem, Grid, SettingsView, ExpandableText, Popover, FileInput, CurrencyInput, HeaderActions, PrimaryHeaderActionButton, SecondaryHeaderActionButton, };
@@ -168,16 +168,6 @@ export interface FileInputProps {
168
168
  name: string;
169
169
  onChange: (event: any) => void;
170
170
  }
171
- /**
172
- * @ignore
173
- * @experimental do not use in production
174
- */
175
- export interface BaseTime {
176
- /** The hour for the time (0 to 23) in 24-hour format (e.g. 0 = 12:00 AM, 9 = 9:00 AM, 15 = 3:00 PM). */
177
- hours: number;
178
- /** The minutes for the time (0 to 59). */
179
- minutes: number;
180
- }
181
171
  /**
182
172
  * Generic collection of props for all inputs (experimental version)
183
173
  * @internal
@@ -258,50 +248,6 @@ export interface BaseInputProps<T = string, V = string> {
258
248
  */
259
249
  onFocus?: (value: V) => void;
260
250
  }
261
- /**
262
- * @ignore
263
- * @experimental do not use in production
264
- *
265
- * The values used to invoke events on the TimeInput component
266
- */
267
- export interface TimeInputEventsPayload extends BaseTime {
268
- }
269
- /**
270
- * @internal
271
- * @ignore
272
- * */
273
- type BaseTimeInputForTime = Omit<BaseInputProps<BaseTime | null, TimeInputEventsPayload>, 'onInput' | 'placeholder' | 'onChange'>;
274
- /**
275
- * @ignore
276
- * @experimental do not use in production
277
- */
278
- export interface TimeInputProps extends BaseTimeInputForTime {
279
- /**
280
- * A callback function that is invoked when the value is changed.
281
- *
282
- * @event
283
- */
284
- onChange?: (value: TimeInputEventsPayload) => void;
285
- /**
286
- * Sets the earliest time that will be valid.
287
- */
288
- min?: BaseTime;
289
- /**
290
- * Sets the latest time that will be valid.
291
- */
292
- max?: BaseTime;
293
- /**
294
- * Sets the interval (in minutes) between the dropdown options.
295
- *
296
- * @defaultValue `30`
297
- */
298
- interval?: number;
299
- /**
300
- * Sets the timezone that the component will display alongside times in the TimePicker. This will not adjust the available valid inputs.
301
- *
302
- */
303
- timezone?: 'userTz' | 'portalTz';
304
- }
305
251
  /**
306
252
  * @ignore
307
253
  * @experimental do not use in production
@@ -331,4 +277,25 @@ export interface CurrencyInputProps extends BaseInputForNumber {
331
277
  */
332
278
  max?: number;
333
279
  }
280
+ /**
281
+ * @ignore
282
+ * @experimental do not use in production
283
+ */
284
+ export interface HeaderActionsProps {
285
+ children: ReactNode;
286
+ }
287
+ /**
288
+ * @ignore
289
+ * @experimental do not use in production
290
+ */
291
+ export interface HeaderActionButtonProps {
292
+ onClick?: ReactionsHandler<ExtensionEvent>;
293
+ href?: string | {
294
+ url: string;
295
+ external?: boolean;
296
+ };
297
+ disabled?: boolean;
298
+ children: ReactNode;
299
+ overlay?: RemoteFragment;
300
+ }
334
301
  export {};
package/dist/types.d.ts CHANGED
@@ -231,6 +231,10 @@ export interface SettingsActions {
231
231
  addAlert: AddAlertAction;
232
232
  }
233
233
  /** @ignore */
234
+ export interface AppHomeActions {
235
+ addAlert: AddAlertAction;
236
+ }
237
+ /** @ignore */
234
238
  export interface UiePlatformActions {
235
239
  copyTextToClipboard: Clipboard['writeText'];
236
240
  closeOverlay: CloseOverlayAction;
@@ -1182,6 +1186,59 @@ export interface DateInputProps extends BaseDateInputForDate {
1182
1186
  */
1183
1187
  todayButtonLabel?: string;
1184
1188
  }
1189
+ /**
1190
+ * Object that represents times.
1191
+ */
1192
+ export interface BaseTime {
1193
+ /** The hour for the time (0 to 23) in 24-hour format (e.g. 0 = 12:00 AM, 9 = 9:00 AM, 15 = 3:00 PM). */
1194
+ hours: number;
1195
+ /** The minutes for the time (0 to 59). */
1196
+ minutes: number;
1197
+ }
1198
+ /**
1199
+ * @ignore
1200
+ *
1201
+ * The values used to invoke events on the TimeInput component
1202
+ */
1203
+ export interface TimeInputEventsPayload extends BaseTime {
1204
+ }
1205
+ /**
1206
+ * @internal
1207
+ * @ignore
1208
+ * */
1209
+ type BaseTimeInputForTime = Omit<BaseInputProps<BaseTime | null, TimeInputEventsPayload>, 'onInput' | 'placeholder' | 'onChange'>;
1210
+ /**
1211
+ * The props type for {@link !components.TimeInput}.
1212
+ *
1213
+ * @category Component Props
1214
+ */
1215
+ export interface TimeInputProps extends BaseTimeInputForTime {
1216
+ /**
1217
+ * A callback function that is invoked when the value is changed.
1218
+ *
1219
+ * @event
1220
+ */
1221
+ onChange?: (value: TimeInputEventsPayload) => void;
1222
+ /**
1223
+ * Sets the earliest time that will be valid.
1224
+ */
1225
+ min?: BaseTime;
1226
+ /**
1227
+ * Sets the latest time that will be valid.
1228
+ */
1229
+ max?: BaseTime;
1230
+ /**
1231
+ * Sets the interval (in minutes) between the dropdown options.
1232
+ *
1233
+ * @defaultValue `30`
1234
+ */
1235
+ interval?: number;
1236
+ /**
1237
+ * Sets the timezone that the component will display alongside times in the TimeInput. This will not modify the available valid inputs.
1238
+ *
1239
+ */
1240
+ timezone?: 'userTz' | 'portalTz';
1241
+ }
1185
1242
  /**
1186
1243
  * The props type for {@link !components.SearchInput}.
1187
1244
  *
@@ -2461,6 +2518,10 @@ export interface SettingsContext extends BaseContext {
2461
2518
  location: 'settings';
2462
2519
  }
2463
2520
  /** @ignore */
2521
+ export interface AppHomeContext extends BaseContext {
2522
+ location: 'home';
2523
+ }
2524
+ /** @ignore */
2464
2525
  export interface GenericContext extends BaseContext {
2465
2526
  location: 'uie.playground.middle';
2466
2527
  }
@@ -2793,6 +2854,11 @@ export interface SettingsExtensionPoint extends ExtensionPointContract {
2793
2854
  actions: SettingsActions & UiePlatformActions;
2794
2855
  context: SettingsContext;
2795
2856
  }
2857
+ /** @ignore */
2858
+ export interface AppHomeExtensionPoint extends ExtensionPointContract {
2859
+ actions: AppHomeActions;
2860
+ context: AppHomeContext;
2861
+ }
2796
2862
  export interface ExampleCrmComponentProps {
2797
2863
  name: string;
2798
2864
  size: 'sm' | 'md' | 'lg';
@@ -2808,7 +2874,7 @@ interface RemotePlaygroundExtensionPoint extends ExtensionPointContract {
2808
2874
  ExampleCrmComponent: ComponentType<ExampleCrmComponentProps>;
2809
2875
  };
2810
2876
  }
2811
- export declare const EXTENSION_POINT_LOCATIONS: readonly ["crm.preview", "crm.record.sidebar", "crm.record.tab", "helpdesk.sidebar", "uie.playground.middle", "settings"];
2877
+ export declare const EXTENSION_POINT_LOCATIONS: readonly ["crm.preview", "crm.record.sidebar", "crm.record.tab", "helpdesk.sidebar", "uie.playground.middle", "settings", "home"];
2812
2878
  export type ExtensionPointLocation = TypesOfReadOnlyArray<typeof EXTENSION_POINT_LOCATIONS>;
2813
2879
  /** @ignore */
2814
2880
  interface LocationToExtensionPoint {
@@ -2818,6 +2884,7 @@ interface LocationToExtensionPoint {
2818
2884
  'crm.record.sidebar': CrmSidebarExtensionPoint;
2819
2885
  'helpdesk.sidebar': StandardCrmExtensionPoint;
2820
2886
  settings: SettingsExtensionPoint;
2887
+ home: AppHomeExtensionPoint;
2821
2888
  }
2822
2889
  /**
2823
2890
  * While this resolves to the same result as LocationToExtensionPoint, it ensures that every location
package/dist/types.js CHANGED
@@ -235,6 +235,7 @@ export const EXTENSION_POINT_LOCATIONS = [
235
235
  'helpdesk.sidebar',
236
236
  'uie.playground.middle',
237
237
  'settings',
238
+ 'home',
238
239
  ];
239
240
  /**
240
241
  * @category Serverless
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -66,5 +66,5 @@
66
66
  "ts-jest": "^29.1.1",
67
67
  "typescript": "5.0.4"
68
68
  },
69
- "gitHead": "a5c7f8d19d0dc16b44e9235d3e12dacc2cc14fdf"
69
+ "gitHead": "8344193a13ab5874924b02d67413dad052558ecf"
70
70
  }