@vendure/dashboard 3.4.3-master-202509230228 → 3.4.3-master-202509240228

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.
Files changed (28) hide show
  1. package/package.json +4 -4
  2. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +2 -2
  3. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-types.ts +5 -0
  4. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +124 -0
  5. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history.tsx +91 -59
  6. package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +176 -0
  7. package/src/app/routes/_authenticated/_customers/components/customer-history/index.ts +4 -2
  8. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +2 -0
  9. package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +98 -0
  10. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +9 -7
  11. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-types.ts +5 -0
  12. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +173 -0
  13. package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +64 -408
  14. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +4 -0
  15. package/src/lib/components/shared/history-timeline/history-note-entry.tsx +65 -0
  16. package/src/lib/components/shared/history-timeline/history-timeline-with-grouping.tsx +141 -0
  17. package/src/lib/components/shared/history-timeline/use-history-note-editor.ts +26 -0
  18. package/src/lib/framework/extension-api/define-dashboard-extension.ts +5 -0
  19. package/src/lib/framework/extension-api/extension-api-types.ts +7 -0
  20. package/src/lib/framework/extension-api/logic/history-entries.ts +24 -0
  21. package/src/lib/framework/extension-api/logic/index.ts +1 -0
  22. package/src/lib/framework/extension-api/types/history-entries.ts +120 -0
  23. package/src/lib/framework/extension-api/types/index.ts +1 -0
  24. package/src/lib/framework/history-entry/history-entry-extensions.ts +11 -0
  25. package/src/lib/framework/history-entry/history-entry.tsx +129 -0
  26. package/src/lib/framework/registry/registry-types.ts +2 -0
  27. package/src/lib/index.ts +5 -1
  28. package/src/lib/components/shared/history-timeline/history-entry.tsx +0 -188
@@ -0,0 +1,141 @@
1
+ import { Button } from '@/vdb/components/ui/button.js';
2
+ import { HistoryEntryItem } from '@/vdb/framework/extension-api/types/history-entries.js';
3
+ import { getCustomHistoryEntryForType } from '@/vdb/framework/history-entry/history-entry-extensions.js';
4
+ import { ChevronDown, ChevronUp } from 'lucide-react';
5
+ import { ReactNode, useState } from 'react';
6
+ import { CustomerHistoryCustomerDetail } from '../../../../app/routes/_authenticated/_customers/components/customer-history/customer-history-types.js';
7
+ import { OrderHistoryOrderDetail } from '../../../../app/routes/_authenticated/_orders/components/order-history/order-history-types.js';
8
+ import { HistoryTimeline } from './history-timeline.js';
9
+
10
+ interface HistoryTimelineWithGroupingProps {
11
+ historyEntries: HistoryEntryItem[];
12
+ entity: OrderHistoryOrderDetail | CustomerHistoryCustomerDetail;
13
+ isPrimaryEvent: (entry: HistoryEntryItem) => boolean;
14
+ renderEntryContent: (entry: HistoryEntryItem) => ReactNode;
15
+ children?: ReactNode;
16
+ }
17
+
18
+ type EntryWithIndex = {
19
+ entry: HistoryEntryItem;
20
+ index: number;
21
+ };
22
+
23
+ export function HistoryTimelineWithGrouping({
24
+ historyEntries,
25
+ entity,
26
+ isPrimaryEvent,
27
+ renderEntryContent,
28
+ children,
29
+ }: Readonly<HistoryTimelineWithGroupingProps>) {
30
+ const [expandedGroups, setExpandedGroups] = useState<Set<number>>(new Set());
31
+
32
+ // Group consecutive secondary events
33
+ const groupedEntries: Array<
34
+ | ({ type: 'primary' } & EntryWithIndex)
35
+ | {
36
+ type: 'secondary-group';
37
+ entries: Array<EntryWithIndex>;
38
+ startIndex: number;
39
+ }
40
+ > = [];
41
+ let currentGroup: Array<EntryWithIndex> = [];
42
+
43
+ for (let i = 0; i < historyEntries.length; i++) {
44
+ const entry = historyEntries[i];
45
+ const isSecondary = !isPrimaryEvent(entry);
46
+
47
+ if (isSecondary) {
48
+ currentGroup.push({ entry, index: i });
49
+ } else {
50
+ // If we have accumulated secondary events, add them as a group
51
+ if (currentGroup.length > 0) {
52
+ groupedEntries.push({
53
+ type: 'secondary-group',
54
+ entries: currentGroup,
55
+ startIndex: currentGroup[0].index,
56
+ });
57
+ currentGroup = [];
58
+ }
59
+ // Add the primary event
60
+ groupedEntries.push({ type: 'primary', entry, index: i });
61
+ }
62
+ }
63
+
64
+ // Don't forget the last group if it exists
65
+ if (currentGroup.length > 0) {
66
+ groupedEntries.push({
67
+ type: 'secondary-group',
68
+ entries: currentGroup,
69
+ startIndex: currentGroup[0].index,
70
+ });
71
+ }
72
+
73
+ const renderEntry = (entry: HistoryEntryItem) => {
74
+ const CustomType = getCustomHistoryEntryForType(entry.type);
75
+ if (CustomType) {
76
+ return <CustomType entry={entry} entity={entity} />;
77
+ } else {
78
+ return renderEntryContent(entry);
79
+ }
80
+ };
81
+
82
+ const toggleGroup = (groupIndex: number) => {
83
+ const newExpanded = new Set(expandedGroups);
84
+ if (newExpanded.has(groupIndex)) {
85
+ newExpanded.delete(groupIndex);
86
+ } else {
87
+ newExpanded.add(groupIndex);
88
+ }
89
+ setExpandedGroups(newExpanded);
90
+ };
91
+
92
+ return (
93
+ <div className="">
94
+ {children && <div className="mb-4">{children}</div>}
95
+ <HistoryTimeline>
96
+ {groupedEntries.map((group, groupIndex) => {
97
+ if (group.type === 'primary') {
98
+ const entry = group.entry;
99
+ return <div key={entry.id}>{renderEntry(entry)}</div>;
100
+ } else {
101
+ // Secondary group
102
+ const shouldCollapse = group.entries.length > 2;
103
+ const isExpanded = expandedGroups.has(groupIndex);
104
+ const visibleEntries =
105
+ shouldCollapse && !isExpanded ? group.entries.slice(0, 2) : group.entries;
106
+
107
+ return (
108
+ <div key={`group-${groupIndex}`}>
109
+ {visibleEntries.map(({ entry }) => (
110
+ <div key={entry.id}>{renderEntry(entry)}</div>
111
+ ))}
112
+ {shouldCollapse && (
113
+ <div className="flex justify-center py-2">
114
+ <Button
115
+ variant="ghost"
116
+ size="sm"
117
+ onClick={() => toggleGroup(groupIndex)}
118
+ className="text-muted-foreground hover:text-foreground h-6 text-xs"
119
+ >
120
+ {isExpanded ? (
121
+ <>
122
+ <ChevronUp className="w-3 h-3 mr-1" />
123
+ Show less
124
+ </>
125
+ ) : (
126
+ <>
127
+ <ChevronDown className="w-3 h-3 mr-1" />
128
+ Show all ({group.entries.length - 2})
129
+ </>
130
+ )}
131
+ </Button>
132
+ </div>
133
+ )}
134
+ </div>
135
+ );
136
+ }
137
+ })}
138
+ </HistoryTimeline>
139
+ </div>
140
+ );
141
+ }
@@ -0,0 +1,26 @@
1
+ import { useState } from 'react';
2
+
3
+ export function useHistoryNoteEditor() {
4
+ const [noteEditorOpen, setNoteEditorOpen] = useState(false);
5
+ const [noteState, setNoteState] = useState<{
6
+ noteId: string;
7
+ note: string;
8
+ isPrivate: boolean;
9
+ }>({
10
+ noteId: '',
11
+ note: '',
12
+ isPrivate: true,
13
+ });
14
+
15
+ const handleEditNote = (noteId: string, note: string, isPrivate: boolean) => {
16
+ setNoteState({ noteId, note, isPrivate });
17
+ setNoteEditorOpen(true);
18
+ };
19
+
20
+ return {
21
+ noteEditorOpen,
22
+ setNoteEditorOpen,
23
+ noteState,
24
+ handleEditNote,
25
+ };
26
+ }
@@ -6,6 +6,7 @@ import {
6
6
  registerDataTableExtensions,
7
7
  registerDetailFormExtensions,
8
8
  registerFormComponentExtensions,
9
+ registerHistoryEntryComponents,
9
10
  registerLayoutExtensions,
10
11
  registerLoginExtensions,
11
12
  registerNavigationExtensions,
@@ -40,6 +41,7 @@ export function executeDashboardExtensionCallbacks() {
40
41
  * - Data tables
41
42
  * - Detail forms
42
43
  * - Login
44
+ * - Custom history entries
43
45
  *
44
46
  * @example
45
47
  * ```tsx
@@ -83,6 +85,9 @@ export function defineDashboardExtension(extension: DashboardExtension) {
83
85
  // Register login extensions
84
86
  registerLoginExtensions(extension.login);
85
87
 
88
+ // Register custom history entry components
89
+ registerHistoryEntryComponents(extension.historyEntries);
90
+
86
91
  // Execute extension source change callbacks
87
92
  const callbacks = globalRegistry.get('extensionSourceChangeCallbacks');
88
93
  if (callbacks.size) {
@@ -5,6 +5,7 @@ import {
5
5
  DashboardCustomFormComponents,
6
6
  DashboardDataTableExtensionDefinition,
7
7
  DashboardDetailFormExtensionDefinition,
8
+ DashboardHistoryEntryComponent,
8
9
  DashboardLoginExtensions,
9
10
  DashboardNavSectionDefinition,
10
11
  DashboardPageBlockDefinition,
@@ -82,4 +83,10 @@ export interface DashboardExtension {
82
83
  * Allows you to customize the login page with custom components.
83
84
  */
84
85
  login?: DashboardLoginExtensions;
86
+ /**
87
+ * @description
88
+ * Allows a custom component to be used to render a history entry item
89
+ * in the Order or Customer history lists.
90
+ */
91
+ historyEntries?: DashboardHistoryEntryComponent[];
85
92
  }
@@ -0,0 +1,24 @@
1
+ import { DashboardHistoryEntryComponent } from '@/vdb/framework/extension-api/types/index.js';
2
+
3
+ import { globalRegistry } from '../../registry/global-registry.js';
4
+
5
+ export function registerHistoryEntryComponents(
6
+ historyEntryComponents: DashboardHistoryEntryComponent[] = [],
7
+ ) {
8
+ if (historyEntryComponents.length === 0) {
9
+ return;
10
+ }
11
+ globalRegistry.set('historyEntries', entryMap => {
12
+ for (const entry of historyEntryComponents) {
13
+ const existingEntry = entryMap.get(entry.type);
14
+ if (existingEntry) {
15
+ // eslint-disable-next-line no-console
16
+ console.warn(
17
+ `The history entry type ${entry.type} already has a custom component registered (${String(existingEntry)}`,
18
+ );
19
+ }
20
+ entryMap.set(entry.type, entry.component);
21
+ }
22
+ return entryMap;
23
+ });
24
+ }
@@ -3,6 +3,7 @@ export * from './alerts.js';
3
3
  export * from './data-table.js';
4
4
  export * from './detail-forms.js';
5
5
  export * from './form-components.js';
6
+ export * from './history-entries.js';
6
7
  export * from './layout.js';
7
8
  export * from './login.js';
8
9
  export * from './navigation.js';
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+
3
+ import { CustomerHistoryCustomerDetail } from '../../../../app/routes/_authenticated/_customers/components/customer-history/customer-history-types.js';
4
+ import { OrderHistoryOrderDetail } from '../../../../app/routes/_authenticated/_orders/components/order-history/order-history-types.js';
5
+
6
+ /**
7
+ * @description
8
+ * This object contains the information about the history entry.
9
+ *
10
+ * @docsCategory extensions-api
11
+ * @docsPage HistoryEntries
12
+ * @since 3.4.3
13
+ */
14
+ export interface HistoryEntryItem {
15
+ id: string;
16
+ /**
17
+ * @description
18
+ * The `HistoryEntryType`, such as `ORDER_STATE_TRANSITION`.
19
+ */
20
+ type: string;
21
+ createdAt: string;
22
+ /**
23
+ * @description
24
+ * Whether this entry is visible to customers via the Shop API
25
+ */
26
+ isPublic: boolean;
27
+ /**
28
+ * @description
29
+ * If an Administrator created this entry, their details will
30
+ * be available here.
31
+ */
32
+ administrator?: {
33
+ id: string;
34
+ firstName: string;
35
+ lastName: string;
36
+ } | null;
37
+ /**
38
+ * @description
39
+ * The entry payload data. This will be an object, which is different
40
+ * for each type of history entry.
41
+ *
42
+ * For example, the `CUSTOMER_ADDED_TO_GROUP` data looks like this:
43
+ * ```json
44
+ * {
45
+ * groupName: 'Some Group',
46
+ * }
47
+ * ```
48
+ *
49
+ * and the `ORDER_STATE_TRANSITION` data looks like this:
50
+ * ```json
51
+ * {
52
+ * from: 'ArrangingPayment',
53
+ * to: 'PaymentSettled',
54
+ * }
55
+ * ```
56
+ */
57
+ data: any;
58
+ }
59
+
60
+ /**
61
+ * @description
62
+ * A definition of a custom component that will be used to render the given
63
+ * type of history entry.
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * import { defineDashboardExtension, HistoryEntry } from '\@vendure/dashboard';
68
+ * import { IdCard } from 'lucide-react';
69
+ *
70
+ * defineDashboardExtension({
71
+ * historyEntries: [
72
+ * {
73
+ * type: 'CUSTOMER_TAX_ID_APPROVAL',
74
+ * component: ({ entry, entity }) => {
75
+ * return (
76
+ * <HistoryEntry
77
+ * entry={entry}
78
+ * title={'Tax ID verified'}
79
+ * timelineIconClassName={'bg-success text-success-foreground'}
80
+ * timelineIcon={<IdCard />}
81
+ * >
82
+ * <div className="text-xs">Approval reference: {entry.data.ref}</div>
83
+ * </HistoryEntry>
84
+ * );
85
+ * },
86
+ * },
87
+ * ],
88
+ * });
89
+ * ```
90
+ *
91
+ * @docsCategory extensions-api
92
+ * @docsPage HistoryEntries
93
+ * @since 3.4.3
94
+ * @docsWeight 0
95
+ */
96
+ export interface DashboardHistoryEntryComponent {
97
+ /**
98
+ * @description
99
+ * The `type` should correspond to a valid `HistoryEntryType`, such as
100
+ *
101
+ * - `CUSTOMER_REGISTERED`
102
+ * - `ORDER_STATE_TRANSITION`
103
+ * - some custom type - see the {@link HistoryService} docs for a guide on
104
+ * how to define custom history entry types.
105
+ */
106
+ type: string;
107
+ /**
108
+ * @description
109
+ * The component which is used to render the timeline entry. It should use the
110
+ * {@link HistoryEntry} component and pass the appropriate props to configure
111
+ * how it will be displayed.
112
+ *
113
+ * The `entity` prop will be a subset of the Order object for Order history entries,
114
+ * or a subset of the Customer object for customer history entries.
115
+ */
116
+ component: React.ComponentType<{
117
+ entry: HistoryEntryItem;
118
+ entity: OrderHistoryOrderDetail | CustomerHistoryCustomerDetail;
119
+ }>;
120
+ }
@@ -3,6 +3,7 @@ export * from './alerts.js';
3
3
  export * from './data-table.js';
4
4
  export * from './detail-forms.js';
5
5
  export * from './form-components.js';
6
+ export * from './history-entries.js';
6
7
  export * from './layout.js';
7
8
  export * from './login.js';
8
9
  export * from './navigation.js';
@@ -0,0 +1,11 @@
1
+ import { DashboardHistoryEntryComponent } from '@/vdb/framework/extension-api/types/index.js';
2
+
3
+ import { globalRegistry } from '../registry/global-registry.js';
4
+
5
+ globalRegistry.register('historyEntries', new Map<string, DashboardHistoryEntryComponent['component']>());
6
+
7
+ export function getCustomHistoryEntryForType(
8
+ type: string,
9
+ ): DashboardHistoryEntryComponent['component'] | undefined {
10
+ return globalRegistry.get('historyEntries').get(type);
11
+ }
@@ -0,0 +1,129 @@
1
+ import { HistoryEntryItem } from '@/vdb/framework/extension-api/types/index.js';
2
+ import { cn } from '@/vdb/lib/utils.js';
3
+ import React from 'react';
4
+ import { HistoryEntryDate } from '../../components/shared/history-timeline/history-entry-date.js';
5
+
6
+ /**
7
+ * @description
8
+ * The props for the {@link HistoryEntry} component.
9
+ *
10
+ * @docsCategory extensions-api
11
+ * @docsPage HistoryEntries
12
+ * @since 3.4.3
13
+ */
14
+ export interface HistoryEntryProps {
15
+ /**
16
+ * @description
17
+ * The entry itself, which will get passed down to your custom component
18
+ */
19
+ entry: HistoryEntryItem;
20
+ /**
21
+ * @description
22
+ * The title of the entry
23
+ */
24
+ title: string | React.ReactNode;
25
+ /**
26
+ * @description
27
+ * An icon which is used to represent the entry. Note that this will only
28
+ * display if `isPrimary` is `true`.
29
+ */
30
+ timelineIcon?: React.ReactNode;
31
+ /**
32
+ * @description
33
+ * Optional tailwind classes to apply to the icon. For instance
34
+ *
35
+ * ```ts
36
+ * const success = 'bg-success text-success-foreground';
37
+ * const destructive = 'bg-danger text-danger-foreground';
38
+ * ```
39
+ */
40
+ timelineIconClassName?: string;
41
+ /**
42
+ * @description
43
+ * The name to display of "who did the action". For instance:
44
+ *
45
+ * ```ts
46
+ * const getActorName = (entry: HistoryEntryItem) => {
47
+ * if (entry.administrator) {
48
+ * return `${entry.administrator.firstName} ${entry.administrator.lastName}`;
49
+ * } else if (entity?.customer) {
50
+ * return `${entity.customer.firstName} ${entity.customer.lastName}`;
51
+ * }
52
+ * return '';
53
+ * };
54
+ * ```
55
+ */
56
+ actorName?: string;
57
+ children: React.ReactNode;
58
+ /**
59
+ * @description
60
+ * When set to `true`, the timeline entry will feature the specified icon and will not
61
+ * be collapsible.
62
+ */
63
+ isPrimary?: boolean;
64
+ }
65
+
66
+ /**
67
+ * @description
68
+ * A component which is used to display a history entry in the order/customer history timeline.
69
+ *
70
+ * @docsCategory extensions-api
71
+ * @docsPage HistoryEntries
72
+ * @since 3.4.3
73
+ */
74
+ export function HistoryEntry({
75
+ entry,
76
+ timelineIcon,
77
+ timelineIconClassName,
78
+ actorName,
79
+ title,
80
+ children,
81
+ isPrimary = true,
82
+ }: Readonly<HistoryEntryProps>) {
83
+ return (
84
+ <div key={entry.id} className="relative group">
85
+ <div
86
+ className={`flex gap-3 p-3 rounded-lg hover:bg-muted/30 transition-colors ${!isPrimary ? 'opacity-90' : ''}`}
87
+ >
88
+ <div className={cn(`relative z-10 flex-shrink-0`, isPrimary ? 'ml-0' : 'ml-2 mt-1')}>
89
+ <div
90
+ className={`rounded-full flex items-center justify-center ${isPrimary ? 'h-6 w-6' : 'h-2 w-2 border'} ${timelineIconClassName ?? ''} ${isPrimary ? 'shadow-sm' : 'shadow-none'}`}
91
+ >
92
+ <div className={isPrimary ? 'text-current scale-80' : 'text-current scale-0'}>
93
+ {timelineIcon ?? ''}
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <div className="flex-1 min-w-0">
99
+ <div className="flex items-start justify-between">
100
+ <div className="flex-1 min-w-0">
101
+ <h4
102
+ className={`text-sm ${isPrimary ? 'font-medium text-foreground' : 'font-normal text-muted-foreground'}`}
103
+ >
104
+ {title}
105
+ </h4>
106
+ <div className="mt-1">{children}</div>
107
+ </div>
108
+
109
+ <div className="flex items-center gap-2 ml-4 flex-shrink-0">
110
+ <div className="text-right">
111
+ <HistoryEntryDate
112
+ date={entry.createdAt}
113
+ className={`text-xs cursor-help ${isPrimary ? 'text-muted-foreground' : 'text-muted-foreground/70'}`}
114
+ />
115
+ {actorName && (
116
+ <div
117
+ className={`text-xs ${isPrimary ? 'text-muted-foreground' : 'text-muted-foreground/70'}`}
118
+ >
119
+ {actorName}
120
+ </div>
121
+ )}
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </div>
128
+ );
129
+ }
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  BulkAction,
3
3
  DashboardActionBarItem,
4
+ DashboardHistoryEntryComponent,
4
5
  DashboardLoginExtensions,
5
6
  DashboardPageBlockDefinition,
6
7
  DashboardWidgetDefinition,
@@ -26,4 +27,5 @@ export interface GlobalRegistryContents {
26
27
  listQueryDocumentRegistry: Map<string, DocumentNode[]>;
27
28
  detailQueryDocumentRegistry: Map<string, DocumentNode[]>;
28
29
  loginExtensions: DashboardLoginExtensions;
30
+ historyEntries: Map<string, DashboardHistoryEntryComponent['component']>;
29
31
  }
package/src/lib/index.ts CHANGED
@@ -96,10 +96,10 @@ export * from './components/shared/facet-value-chip.js';
96
96
  export * from './components/shared/facet-value-selector.js';
97
97
  export * from './components/shared/form-field-wrapper.js';
98
98
  export * from './components/shared/history-timeline/history-entry-date.js';
99
- export * from './components/shared/history-timeline/history-entry.js';
100
99
  export * from './components/shared/history-timeline/history-note-checkbox.js';
101
100
  export * from './components/shared/history-timeline/history-note-editor.js';
102
101
  export * from './components/shared/history-timeline/history-note-input.js';
102
+ export * from './components/shared/history-timeline/history-timeline-with-grouping.js';
103
103
  export * from './components/shared/history-timeline/history-timeline.js';
104
104
  export * from './components/shared/icon-mark.js';
105
105
  export * from './components/shared/language-selector.js';
@@ -198,6 +198,7 @@ export * from './framework/extension-api/logic/alerts.js';
198
198
  export * from './framework/extension-api/logic/data-table.js';
199
199
  export * from './framework/extension-api/logic/detail-forms.js';
200
200
  export * from './framework/extension-api/logic/form-components.js';
201
+ export * from './framework/extension-api/logic/history-entries.js';
201
202
  export * from './framework/extension-api/logic/layout.js';
202
203
  export * from './framework/extension-api/logic/login.js';
203
204
  export * from './framework/extension-api/logic/navigation.js';
@@ -206,6 +207,7 @@ export * from './framework/extension-api/types/alerts.js';
206
207
  export * from './framework/extension-api/types/data-table.js';
207
208
  export * from './framework/extension-api/types/detail-forms.js';
208
209
  export * from './framework/extension-api/types/form-components.js';
210
+ export * from './framework/extension-api/types/history-entries.js';
209
211
  export * from './framework/extension-api/types/layout.js';
210
212
  export * from './framework/extension-api/types/login.js';
211
213
  export * from './framework/extension-api/types/navigation.js';
@@ -222,6 +224,8 @@ export * from './framework/form-engine/overridden-form-component.js';
222
224
  export * from './framework/form-engine/use-generated-form.js';
223
225
  export * from './framework/form-engine/utils.js';
224
226
  export * from './framework/form-engine/value-transformers.js';
227
+ export * from './framework/history-entry/history-entry-extensions.js';
228
+ export * from './framework/history-entry/history-entry.js';
225
229
  export * from './framework/layout-engine/dev-mode-button.js';
226
230
  export * from './framework/layout-engine/layout-extensions.js';
227
231
  export * from './framework/layout-engine/location-wrapper.js';