@designcrowd/library.brand-page 6.0.1 → 6.0.2

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 (33) hide show
  1. package/lib/src/{CreatedOnBrandCrowd-de-de-BPP1Wtpt.js → CreatedOnBrandCrowd-de-de-Zptj2O2O.js} +1 -1
  2. package/lib/src/{CreatedOnBrandCrowd-en-us-BlfpQiIg.js → CreatedOnBrandCrowd-en-us-Bxmo2Ps9.js} +1 -1
  3. package/lib/src/{CreatedOnBrandCrowd-es-es-Tldy_pIo.js → CreatedOnBrandCrowd-es-es-uytkzFdZ.js} +1 -1
  4. package/lib/src/{CreatedOnBrandCrowd-fr-fr-CHmb3VQE.js → CreatedOnBrandCrowd-fr-ca-26tDXsvZ.js} +1 -1
  5. package/lib/src/{CreatedOnBrandCrowd-fr-ca-CHmb3VQE.js → CreatedOnBrandCrowd-fr-fr-26tDXsvZ.js} +1 -1
  6. package/lib/src/{CreatedOnBrandCrowd-pt-pt-XbU3eK3Z.js → CreatedOnBrandCrowd-pt-br-DuNRkCU5.js} +1 -1
  7. package/lib/src/{CreatedOnBrandCrowd-pt-br-XbU3eK3Z.js → CreatedOnBrandCrowd-pt-pt-DuNRkCU5.js} +1 -1
  8. package/lib/src/{CreatedOnDcom-de-de-BVMFbVbI.js → CreatedOnDcom-de-de-D_aekURi.js} +1 -1
  9. package/lib/src/{CreatedOnDcom-en-us--kaKb1kI.js → CreatedOnDcom-en-us-CD3RyS8m.js} +1 -1
  10. package/lib/src/{CreatedOnDcom-es-es-XXVLpF2I.js → CreatedOnDcom-es-es-BXCP18xT.js} +1 -1
  11. package/lib/src/{CreatedOnDcom-fr-ca-D-7vtMZ5.js → CreatedOnDcom-fr-ca-BN04YN4o.js} +1 -1
  12. package/lib/src/{CreatedOnDcom-fr-fr-CM9oQk77.js → CreatedOnDcom-fr-fr-B8-sowys.js} +1 -1
  13. package/lib/src/{CreatedOnDcom-pt-br-VVgu3BEa.js → CreatedOnDcom-pt-br-C0MTfZ_l.js} +1 -1
  14. package/lib/src/{CreatedOnDcom-pt-pt-CWhA8Vla.js → CreatedOnDcom-pt-pt-BamTt9zq.js} +1 -1
  15. package/lib/src/brand-page-maker/components/admin-background-settings/ShapePositionSlider.mixin.d.ts +1 -1
  16. package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +2 -0
  17. package/lib/src/clients/ai-assistant-client.d.ts +7 -0
  18. package/lib/src/index.d.ts +4 -0
  19. package/lib/src/index.mjs +107 -104
  20. package/lib/src/{lib-yEV1yYI5.js → lib-dQieWjFg.js} +5484 -5470
  21. package/lib/src/lib.js +10 -0
  22. package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +13 -0
  23. package/lib/src/metadata-builder/builders/reorder-pages-builder.js +49 -0
  24. package/lib/src/utils/build-asset-manifest.d.ts +4 -0
  25. package/lib/src/utils/build-asset-manifest.js +8 -0
  26. package/lib/src/utils/minify-brand-page-metadata.js +1 -9
  27. package/package.json +2 -2
  28. package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +2 -0
  29. package/src/clients/ai-assistant-client.ts +7 -0
  30. package/src/lib.ts +12 -0
  31. package/src/metadata-builder/builders/reorder-pages-builder.ts +80 -0
  32. package/src/utils/build-asset-manifest.ts +12 -0
  33. package/src/utils/minify-brand-page-metadata.ts +5 -13
package/lib/src/lib.js CHANGED
@@ -31,6 +31,16 @@ export * as brandPageUtils from './brand-page/utils';
31
31
  export { getOptimalLogoSize, calculateOptimizedLogoDimensions, applyLogoImageBase64UrlToBrandPageTemplateModel, recalculateLogoContentDimensions, recalculateHeaderLogoSizes, } from './brand-page/utils/logo.util';
32
32
  export { sanitizeRTEHtml } from './brand-page-maker/utils';
33
33
  export { getPageSlugFromPageTitle } from './brand-page-maker/utils/slug.util';
34
+ // AI-pipeline preview (longclaw per-turn snapshots): web-renderer's
35
+ // /preview/ai-pipeline render page + manifest server route apply the agent's
36
+ // tool calls to a brand-page metadata snapshot server-side and resolve the
37
+ // target page by slug. These three symbols are otherwise internal to the
38
+ // metadata-builder / route utils.
39
+ export { executeToolCallsAsync } from './metadata-builder/ai-metadata-executor';
40
+ export { findNavItemByPageSlug } from './brand-page/utils/route.util';
41
+ // Tiptap-JSON RTE -> HTML (same converter the metadata builders use). Lets the
42
+ // preview render the agent's raw Tiptap fields, which the renderer expects as HTML.
43
+ export { tiptapJsonToHtml } from './metadata-builder/helpers/rte.helpers';
34
44
  // stores
35
45
  export { useBrandPageMakerStore, useBrandPageMakerUserStore, useUiStore, useBrandPageContainerStore, useEventManagerStore, useLocalisedRouteStore, useVideoStore, useRouteStore, } from './brand-page-maker/stores';
36
46
  export { useShopConfigStore } from './shared/ecommerce-settings/store/shop-settings-store';
@@ -0,0 +1,13 @@
1
+ import type { BrandPageModel } from '../../brand-page/models';
2
+ import { BaseMetadataBuilder, type BuilderResult, type MetadataBuilderRequest } from '../models';
3
+ import type { Logger } from '../logger';
4
+ export interface ReorderPagesPayload {
5
+ pageOrder: string[];
6
+ }
7
+ export declare class ReorderPagesBuilder extends BaseMetadataBuilder<ReorderPagesPayload> {
8
+ constructor(request: MetadataBuilderRequest<ReorderPagesPayload>, logger?: Logger);
9
+ validateAsync(): Promise<{
10
+ errors: string[];
11
+ }>;
12
+ buildAsync(model: BrandPageModel): Promise<BuilderResult>;
13
+ }
@@ -0,0 +1,49 @@
1
+ import { BaseMetadataBuilder, } from '../models';
2
+ export class ReorderPagesBuilder extends BaseMetadataBuilder {
3
+ constructor(request, logger) {
4
+ super(request, logger);
5
+ }
6
+ async validateAsync() {
7
+ const errors = [];
8
+ const payload = this.request.payload;
9
+ if (!payload?.pageOrder?.length) {
10
+ errors.push('page_order is required for reorder_pages');
11
+ }
12
+ return { errors };
13
+ }
14
+ async buildAsync(model) {
15
+ this.log('Build called');
16
+ const validation = await this.validateAsync();
17
+ if (validation.errors.length) {
18
+ return { request: this.request, model, errors: validation.errors };
19
+ }
20
+ const { pageOrder } = this.request.payload;
21
+ // Build pageId → routeId lookup from nav.routes
22
+ const pageIdToRouteId = new Map();
23
+ for (const route of model.nav.routes) {
24
+ pageIdToRouteId.set(route.pageId, route.id);
25
+ }
26
+ // Build new nav.orders from the flat page_order (array of pageIds)
27
+ const newOrders = [];
28
+ const seenRouteIds = new Set();
29
+ for (const pageId of pageOrder) {
30
+ const routeId = pageIdToRouteId.get(pageId);
31
+ if (!routeId)
32
+ continue;
33
+ newOrders.push({ routeId, subRoutes: [] });
34
+ seenRouteIds.add(routeId);
35
+ }
36
+ // Safety: append any routes not mentioned (don't lose pages)
37
+ for (const route of model.nav.routes) {
38
+ const routeId = pageIdToRouteId.get(route.pageId);
39
+ if (routeId && !seenRouteIds.has(routeId)) {
40
+ newOrders.push({ routeId, subRoutes: [] });
41
+ }
42
+ }
43
+ model.nav.orders = newOrders;
44
+ this.log({
45
+ message: `Reordered pages: ${pageOrder.join(', ')}`,
46
+ });
47
+ return { request: this.request, model };
48
+ }
49
+ }
@@ -14,6 +14,10 @@ export interface AssetEntry {
14
14
  * 2. Fall back to logoImageBase64Url if logoImage is unavailable.
15
15
  */
16
16
  export declare function resolveLogoData(logoImage: LogoImageModel | undefined, logoImageBase64Url: string | undefined): string | undefined;
17
+ /**
18
+ * Look up an asset key from the manifest by matching the data content.
19
+ */
20
+ export declare function findAssetKey(assets: AssetEntry[] | undefined, data: string | undefined): string | undefined;
17
21
  /**
18
22
  * Build an asset manifest from the brand page model.
19
23
  *
@@ -23,6 +23,14 @@ export function resolveLogoData(logoImage, logoImageBase64Url) {
23
23
  // Fallback to base64 if available
24
24
  return logoImageBase64Url || undefined;
25
25
  }
26
+ /**
27
+ * Look up an asset key from the manifest by matching the data content.
28
+ */
29
+ export function findAssetKey(assets, data) {
30
+ if (!data || !assets)
31
+ return undefined;
32
+ return assets.find((a) => a.data === data)?.key;
33
+ }
26
34
  /**
27
35
  * Hash a string using SHA-256 and return the first 16 hex characters.
28
36
  * Uses the Web Crypto API (available in browsers and modern runtimes).
@@ -1,7 +1,7 @@
1
1
  import { BRAND_PAGE_TYPES, } from '../brand-page/models';
2
2
  import { hasRTEContent } from '../brand-page-maker/utils';
3
3
  import { useExternalRichTextEditor } from '../brand-page-maker/composables/rich-text-editor/useRichTextEditor';
4
- import { resolveLogoData } from './build-asset-manifest';
4
+ import { findAssetKey, resolveLogoData, } from './build-asset-manifest';
5
5
  const BUTTON_TYPES = [
6
6
  'general-link',
7
7
  'website',
@@ -78,14 +78,6 @@ const includeBackgroundStyle = (value) => {
78
78
  return null;
79
79
  return { backgroundStyle: { backgroundColor: bg } };
80
80
  };
81
- /**
82
- * Look up an asset key from the manifest by matching the data content.
83
- */
84
- const findAssetKey = (assets, data) => {
85
- if (!data || !assets)
86
- return undefined;
87
- return assets.find((a) => a.data === data)?.key;
88
- };
89
81
  const minifyContent = (content, editor, assets) => {
90
82
  const base = {
91
83
  id: content.id,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@designcrowd/library.brand-page",
3
3
  "description": "A collection of Maker/Designer applications",
4
- "version": "6.0.1",
4
+ "version": "6.0.2",
5
5
  "author": "Design.com Eng",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -248,4 +248,4 @@
248
248
  "public"
249
249
  ]
250
250
  }
251
- }
251
+ }
@@ -19,6 +19,7 @@ import {
19
19
  } from '../../../clients/websocket-gateway-client';
20
20
  import { minifyBrandPageMetadata } from '../../../utils/minify-brand-page-metadata';
21
21
  import { buildAssetManifest } from '../../../utils/build-asset-manifest';
22
+ import cloneDeep from 'lodash.clonedeep';
22
23
  import { usePageNavigationStore } from '../../../shared/page-navigation/store/page-navigation-store';
23
24
  import { navigateToPageByPageId } from '../../routing';
24
25
  import {
@@ -268,6 +269,7 @@ export function useAiWebsiteBuilderChat(): UseAiChatResult {
268
269
 
269
270
  const websiteContext = {
270
271
  metadata: minifyBrandPageMetadata(brandPageData, assets),
272
+ metadataFull: cloneDeep(brandPageData),
271
273
  ...(assets.length > 0 && { assets }),
272
274
  websiteTemplateToken: containerStore.designTemplateToken,
273
275
  ...(containerStore.designDraftToken && {
@@ -2,6 +2,7 @@ import axios, { type AxiosError } from 'axios';
2
2
  import { useBrandPageContainerStore } from '../brand-page-maker/stores/brandpage-container/brand-page-container-store';
3
3
  import type { MinifiedBrandPageMetadata } from '../utils/minify-brand-page-metadata';
4
4
  import type { AssetEntry } from '../utils/build-asset-manifest';
5
+ import type { BrandPageModel } from '../brand-page/models';
5
6
 
6
7
  export interface ActiveContext {
7
8
  currentPageId: string;
@@ -14,6 +15,12 @@ export interface LogoContext {
14
15
 
15
16
  export interface WebsiteContext {
16
17
  metadata: MinifiedBrandPageMetadata;
18
+ /**
19
+ * Full structural metadata (logos externalized to `logoAssetKey`, no base64,
20
+ * no field-stripping) — persisted for the preview render only. The LLM uses
21
+ * `metadata` (minified); the preview renderer uses this for full fidelity.
22
+ */
23
+ metadataFull?: BrandPageModel;
17
24
  assets?: AssetEntry[];
18
25
  activeContext?: ActiveContext;
19
26
  businessName?: string;
package/src/lib.ts CHANGED
@@ -87,6 +87,18 @@ export {
87
87
  export { sanitizeRTEHtml } from './brand-page-maker/utils';
88
88
  export { getPageSlugFromPageTitle } from './brand-page-maker/utils/slug.util';
89
89
 
90
+ // AI-pipeline preview (longclaw per-turn snapshots): web-renderer's
91
+ // /preview/ai-pipeline render page + manifest server route apply the agent's
92
+ // tool calls to a brand-page metadata snapshot server-side and resolve the
93
+ // target page by slug. These three symbols are otherwise internal to the
94
+ // metadata-builder / route utils.
95
+ export { executeToolCallsAsync } from './metadata-builder/ai-metadata-executor';
96
+ export type { ParsedToolCall } from './metadata-builder/parsers/ai-toolcall-parser';
97
+ export { findNavItemByPageSlug } from './brand-page/utils/route.util';
98
+ // Tiptap-JSON RTE -> HTML (same converter the metadata builders use). Lets the
99
+ // preview render the agent's raw Tiptap fields, which the renderer expects as HTML.
100
+ export { tiptapJsonToHtml } from './metadata-builder/helpers/rte.helpers';
101
+
90
102
  // stores
91
103
  export {
92
104
  useBrandPageMakerStore,
@@ -0,0 +1,80 @@
1
+ import type { BrandPageModel, NavOrder } from '../../brand-page/models';
2
+ import {
3
+ BaseMetadataBuilder,
4
+ type BuilderResult,
5
+ type MetadataBuilderRequest,
6
+ } from '../models';
7
+ import type { Logger } from '../logger';
8
+
9
+ export interface ReorderPagesPayload {
10
+ pageOrder: string[];
11
+ }
12
+
13
+ export class ReorderPagesBuilder extends BaseMetadataBuilder<ReorderPagesPayload> {
14
+ constructor(
15
+ request: MetadataBuilderRequest<ReorderPagesPayload>,
16
+ logger?: Logger,
17
+ ) {
18
+ super(request, logger);
19
+ }
20
+
21
+ async validateAsync(): Promise<{ errors: string[] }> {
22
+ const errors: string[] = [];
23
+ const payload = this.request.payload;
24
+
25
+ if (!payload?.pageOrder?.length) {
26
+ errors.push('page_order is required for reorder_pages');
27
+ }
28
+
29
+ return { errors };
30
+ }
31
+
32
+ async buildAsync(model: BrandPageModel): Promise<BuilderResult> {
33
+ this.log('Build called');
34
+
35
+ const validation = await this.validateAsync();
36
+
37
+ if (validation.errors.length) {
38
+ return { request: this.request, model, errors: validation.errors };
39
+ }
40
+
41
+ const { pageOrder } = this.request.payload!;
42
+
43
+ // Build pageId → routeId lookup from nav.routes
44
+ const pageIdToRouteId = new Map<string, string>();
45
+
46
+ for (const route of model.nav.routes) {
47
+ pageIdToRouteId.set(route.pageId, route.id);
48
+ }
49
+
50
+ // Build new nav.orders from the flat page_order (array of pageIds)
51
+ const newOrders: NavOrder[] = [];
52
+ const seenRouteIds = new Set<string>();
53
+
54
+ for (const pageId of pageOrder) {
55
+ const routeId = pageIdToRouteId.get(pageId);
56
+
57
+ if (!routeId) continue;
58
+
59
+ newOrders.push({ routeId, subRoutes: [] });
60
+ seenRouteIds.add(routeId);
61
+ }
62
+
63
+ // Safety: append any routes not mentioned (don't lose pages)
64
+ for (const route of model.nav.routes) {
65
+ const routeId = pageIdToRouteId.get(route.pageId);
66
+
67
+ if (routeId && !seenRouteIds.has(routeId)) {
68
+ newOrders.push({ routeId, subRoutes: [] });
69
+ }
70
+ }
71
+
72
+ model.nav.orders = newOrders;
73
+
74
+ this.log({
75
+ message: `Reordered pages: ${pageOrder.join(', ')}`,
76
+ });
77
+
78
+ return { request: this.request, model };
79
+ }
80
+ }
@@ -41,6 +41,18 @@ export function resolveLogoData(
41
41
  return logoImageBase64Url || undefined;
42
42
  }
43
43
 
44
+ /**
45
+ * Look up an asset key from the manifest by matching the data content.
46
+ */
47
+ export function findAssetKey(
48
+ assets: AssetEntry[] | undefined,
49
+ data: string | undefined,
50
+ ): string | undefined {
51
+ if (!data || !assets) return undefined;
52
+
53
+ return assets.find((a) => a.data === data)?.key;
54
+ }
55
+
44
56
  /**
45
57
  * Hash a string using SHA-256 and return the first 16 hex characters.
46
58
  * Uses the Web Crypto API (available in browsers and modern runtimes).
@@ -13,7 +13,11 @@ import type { TextStyleDeclaration } from '../brand-page/models/styles.model';
13
13
  import { hasRTEContent } from '../brand-page-maker/utils';
14
14
  import { useExternalRichTextEditor } from '../brand-page-maker/composables/rich-text-editor/useRichTextEditor';
15
15
  import type { Editor, JSONContent } from '@tiptap/vue-3';
16
- import { type AssetEntry, resolveLogoData } from './build-asset-manifest';
16
+ import {
17
+ type AssetEntry,
18
+ findAssetKey,
19
+ resolveLogoData,
20
+ } from './build-asset-manifest';
17
21
 
18
22
  type MinifiedFooterSocialLink = { imageUrl: string; url: string };
19
23
 
@@ -188,18 +192,6 @@ const includeBackgroundStyle = (
188
192
  return { backgroundStyle: { backgroundColor: bg } };
189
193
  };
190
194
 
191
- /**
192
- * Look up an asset key from the manifest by matching the data content.
193
- */
194
- const findAssetKey = (
195
- assets: AssetEntry[] | undefined,
196
- data: string | undefined,
197
- ): string | undefined => {
198
- if (!data || !assets) return undefined;
199
-
200
- return assets.find((a) => a.data === data)?.key;
201
- };
202
-
203
195
  const minifyContent = (
204
196
  content: Content,
205
197
  editor: Editor,