@alpaca-headless/alpaca-headless-nextjs 1.0.4621 → 1.0.4623

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.
@@ -1,35 +1,18 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState, } from "react";
3
+ import React, { Fragment, useCallback, useEffect, useState, } from "react";
4
4
  export function MultiComponentEditor({ children, component, placeholderName, thumbZoom, thumbWidth, thumbHeight, onSelectedComponentChange, }) {
5
- var _a, _b, _c;
5
+ var _a, _b;
6
6
  const [selectedId, setSelectedId] = useState(null);
7
- const thumbnailContainerRef = useRef(null);
8
7
  const placeholder = component.placeholders.find((x) => x.name === placeholderName);
9
- const components = useMemo(() => { var _a; return (_a = placeholder === null || placeholder === void 0 ? void 0 : placeholder.components) !== null && _a !== void 0 ? _a : null; }, [placeholder]);
8
+ if (!placeholder)
9
+ return;
10
+ const components = placeholder.components;
11
+ if (!components)
12
+ return;
10
13
  const handleMessage = useCallback((event) => {
11
- var _a, _b, _c, _d;
12
- const data = event.data;
13
- if (!data || !components)
14
- return;
15
- if (data.type === "componentsSelected") {
16
- setSelectedId((_b = (_a = data.componentIds) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null);
17
- return;
18
- }
19
- // Parhelia (editing-bridge) selects the surrounding component as a
20
- // whole, so only ids that resolve to one of our items may change the
21
- // selection — everything else would snap back to the first item.
22
- if (data.family === "parhelia/editing-bridge" &&
23
- data.name === "setSelection") {
24
- const ids = (_d = (_c = data.payload) === null || _c === void 0 ? void 0 : _c.componentIds) !== null && _d !== void 0 ? _d : [];
25
- const matches = components.filter((c) => ids.some((id) => matchesComponent(id, c)));
26
- if (matches.length === 1) {
27
- setSelectedId(matches[0].id);
28
- }
29
- else if (matches.length > 1) {
30
- console.warn("[MultiComponentEditor] ambiguous setSelection: %d components matched ids %o, selecting first", matches.length, ids);
31
- setSelectedId(matches[0].id);
32
- }
14
+ if (event.data.type === "componentsSelected") {
15
+ setSelectedId(event.data.componentIds[0]);
33
16
  }
34
17
  }, [components]);
35
18
  useEffect(() => {
@@ -37,35 +20,11 @@ export function MultiComponentEditor({ children, component, placeholderName, thu
37
20
  return () => {
38
21
  window.removeEventListener("message", handleMessage);
39
22
  };
40
- }, [handleMessage]);
41
- // Parhelia's interaction overlay swallows click and pointerup before they
42
- // reach the thumbnails (its pointer capture retargets the release event),
43
- // but pointerdown still hits the DOM — select thumbnails with a native
44
- // capture listener so switching works in both editors.
45
- useEffect(() => {
46
- const container = thumbnailContainerRef.current;
47
- if (!container)
48
- return;
49
- const handlePointerDown = (event) => {
50
- var _a;
51
- if (event.button !== 0)
52
- return;
53
- const thumb = (_a = event.target) === null || _a === void 0 ? void 0 : _a.closest("[data-mce-component-id]");
54
- const id = thumb === null || thumb === void 0 ? void 0 : thumb.getAttribute("data-mce-component-id");
55
- if (id) {
56
- setSelectedId(id);
57
- selectComponents([id]);
58
- }
59
- };
60
- container.addEventListener("pointerdown", handlePointerDown, true);
61
- return () => {
62
- container.removeEventListener("pointerdown", handlePointerDown, true);
63
- };
64
23
  }, []);
65
- const selectedIndex = (_a = components === null || components === void 0 ? void 0 : components.findIndex((x) => x.id === selectedId)) !== null && _a !== void 0 ? _a : -1;
24
+ const selectedIndex = components.findIndex((x) => x.id === selectedId);
66
25
  const resolvedIndex = selectedIndex < 0 ? 0 : selectedIndex;
67
- const resolvedComponent = (_b = components === null || components === void 0 ? void 0 : components[resolvedIndex]) !== null && _b !== void 0 ? _b : null;
68
- const resolvedId = (_c = resolvedComponent === null || resolvedComponent === void 0 ? void 0 : resolvedComponent.id) !== null && _c !== void 0 ? _c : null;
26
+ const resolvedComponent = (_a = components[resolvedIndex]) !== null && _a !== void 0 ? _a : null;
27
+ const resolvedId = (_b = resolvedComponent === null || resolvedComponent === void 0 ? void 0 : resolvedComponent.id) !== null && _b !== void 0 ? _b : null;
69
28
  useEffect(() => {
70
29
  if (resolvedId !== null && selectedId !== resolvedId) {
71
30
  setSelectedId(resolvedId);
@@ -77,11 +36,9 @@ export function MultiComponentEditor({ children, component, placeholderName, thu
77
36
  selectedIndex: resolvedIndex,
78
37
  });
79
38
  }, [resolvedId, resolvedIndex, onSelectedComponentChange]);
80
- if (!placeholder || !components)
81
- return;
82
39
  const childrenArray = React.Children.toArray(children);
83
40
  const filteredChildren = childrenArray.filter((child) => child.type !== "script");
84
- return (_jsxs(_Fragment, { children: [filteredChildren[resolvedIndex], _jsxs("div", { className: "a-editor-mce", ref: thumbnailContainerRef, children: [_jsx("script", { "data-placeholder-start": placeholder.key, "data-orientation": "horizontal" }), filteredChildren.map((x, index) => thumbnail(x, index)), _jsx("script", { "data-placeholder-end": placeholder.key })] })] }));
41
+ return (_jsxs(_Fragment, { children: [filteredChildren[resolvedIndex], _jsxs("div", { className: "a-editor-mce", children: [_jsx("script", { "data-placeholder-start": placeholder.key, "data-orientation": "horizontal" }), filteredChildren.map((x, index) => thumbnail(x, index)), _jsx("script", { "data-placeholder-end": placeholder.key })] })] }));
85
42
  function thumbnail(x, index) {
86
43
  var _a, _b, _c, _d, _e, _f, _g;
87
44
  const style = {};
@@ -91,31 +48,14 @@ export function MultiComponentEditor({ children, component, placeholderName, thu
91
48
  if (thumbWidth) {
92
49
  style.width = thumbWidth;
93
50
  }
94
- // Mid-transition renders (RSC refetch, fresh inserts) can deliver child
95
- // elements whose nesting doesn't match yet — render an empty tile for
96
- // that frame instead of crashing into the placeholder error boundary.
97
51
  const componentArray = (_c = (_b = (_a = x.props) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.props) === null || _c === void 0 ? void 0 : _c.children;
98
- const thumbnailContent = Array.isArray(componentArray)
99
- ? componentArray.slice(1, -1)
100
- : null;
101
52
  const component = components[index];
102
53
  return (_jsxs(Fragment, { children: [_jsxs("div", { className: "a-editor-mce-thumbnail" +
103
- (index === resolvedIndex ? " a-editor-mce-thumbnail--selected" : ""), style: style, "data-mce-component-id": component.id, children: [_jsx("script", { "data-component-start": component.id, "data-itemid": ((_e = (_d = component._editor) === null || _d === void 0 ? void 0 : _d.linkedComponentItem) === null || _e === void 0 ? void 0 : _e.id) || component.id, "data-layoutid": (_g = (_f = component._editor) === null || _f === void 0 ? void 0 : _f.hostingPageItem) === null || _g === void 0 ? void 0 : _g.id }), _jsx("div", { style: { pointerEvents: "none", zoom: thumbZoom || 0.25 }, children: thumbnailContent }), _jsx("script", { "data-component-end": component.id })] }), _jsx("div", { "data-dropzone": component.id })] }, index));
54
+ (index === resolvedIndex ? " a-editor-mce-thumbnail--selected" : ""), style: style, onClick: () => {
55
+ selectComponents([components[index].id]);
56
+ }, children: [_jsx("script", { "data-component-start": component.id, "data-itemid": ((_e = (_d = component._editor) === null || _d === void 0 ? void 0 : _d.linkedComponentItem) === null || _e === void 0 ? void 0 : _e.id) || component.id, "data-layoutid": (_g = (_f = component._editor) === null || _f === void 0 ? void 0 : _f.hostingPageItem) === null || _g === void 0 ? void 0 : _g.id }), _jsx("div", { style: { pointerEvents: "none", zoom: thumbZoom || 0.25 }, children: componentArray.slice(1, -1) }), _jsx("script", { "data-component-end": component.id })] }), _jsx("div", { "data-dropzone": components[index].id })] }, index));
104
57
  }
105
58
  }
106
- function matchesComponent(id, component) {
107
- var _a, _b;
108
- const normalized = normalizeId(id);
109
- if (!normalized)
110
- return false;
111
- return (normalized === normalizeId(component.id) ||
112
- normalized === normalizeId((_b = (_a = component._editor) === null || _a === void 0 ? void 0 : _a.linkedComponentItem) === null || _b === void 0 ? void 0 : _b.id));
113
- }
114
- function normalizeId(id) {
115
- // Like Editor/packages/core/src/editor/utils.ts#stripGuid, but also removes
116
- // dashes to handle Parhelia's editing-bridge id format variations.
117
- return id ? id.replace(/[{}-]/g, "").toLowerCase() : null;
118
- }
119
59
  function selectComponents(componentIds) {
120
60
  var _a;
121
61
  (_a = window.top) === null || _a === void 0 ? void 0 : _a.window.postMessage({ componentIds, type: "componentsSelected" }, "*");
@@ -1,21 +1,29 @@
1
1
  import axios from "axios";
2
+ // import { HttpsProxyAgent } from "https-proxy-agent";
2
3
  import { NextResponse } from "next/server";
3
- async function GET(req, target) {
4
+ async function GET(req, target
5
+ //{ proxy }: { proxy?: string }
6
+ ) {
4
7
  const reqUrl = new URL(req.url);
5
8
  const url = target + reqUrl.pathname + "?" + reqUrl.searchParams.toString();
6
9
  const headers = {
7
10
  Authorization: req.headers.get("Authorization") || "",
8
11
  Cookie: req.headers.get("Cookie") || "",
9
12
  };
13
+ // const agent = proxy ? new HttpsProxyAgent(proxy) : undefined;
10
14
  const externalResponse = await axios.get(url, {
11
15
  headers: headers,
16
+ // httpAgent: agent,
17
+ // httpsAgent: agent,
12
18
  responseType: "stream",
13
19
  });
14
20
  return new NextResponse(nodeReadableToReadableStream(externalResponse.data), {
15
21
  status: externalResponse.status,
16
22
  });
17
23
  }
18
- async function POST(req) {
24
+ async function POST(req
25
+ //{ proxy }: { proxy?: string }
26
+ ) {
19
27
  const reqUrl = new URL(req.url);
20
28
  const body = await req.text();
21
29
  const url = process.env.EDITOR_SERVICE_URL +
@@ -27,8 +35,11 @@ async function POST(req) {
27
35
  Authorization: req.headers.get("Authorization") || "",
28
36
  Cookie: req.headers.get("Cookie") || "",
29
37
  };
38
+ // const agent = proxy ? new HttpsProxyAgent(proxy) : undefined;
30
39
  const externalResponse = await axios.post(url, body, {
31
40
  headers: headers,
41
+ // httpAgent: agent,
42
+ // httpsAgent: agent,
32
43
  responseType: "stream",
33
44
  });
34
45
  const responseHeaders = getResponseHeaders(externalResponse);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alpaca-headless/alpaca-headless-nextjs",
3
- "version": "1.0.4621",
3
+ "version": "1.0.4623",
4
4
  "type": "module",
5
5
  "description": "Alpaca Headless",
6
6
  "main": "dist/index.js",
@@ -44,15 +44,17 @@
44
44
  },
45
45
  "homepage": "https://github.com/yourusername/your-module-name#readme",
46
46
  "devDependencies": {
47
- "@types/node": "^25.5.0",
48
- "@types/react": "19.2.14",
49
- "eslint": "^9.39.4",
47
+ "@types/node": "^20.14.2",
48
+ "@types/react": "19.2.2",
49
+ "@types/react-dom": "19.2.2",
50
+ "eslint": "^9.22.0",
50
51
  "eslint-config-next": "16.2.6",
51
- "typescript": "5.9.3"
52
+ "typescript": "^5"
52
53
  },
53
54
  "dependencies": {
54
- "@alpaca-headless/alpaca-headless": "^1.0.4621",
55
+ "@alpaca-headless/alpaca-headless": "^1.0.4623",
55
56
  "axios": "^1.16.1",
57
+ "https-proxy-agent": "^7.0.4",
56
58
  "next": "16.2.6",
57
59
  "react": "19.2.4",
58
60
  "react-dom": "19.2.4",
@@ -7,8 +7,6 @@ import React, {
7
7
  ReactNode,
8
8
  useCallback,
9
9
  useEffect,
10
- useMemo,
11
- useRef,
12
10
  useState,
13
11
  } from "react";
14
12
 
@@ -35,46 +33,17 @@ export function MultiComponentEditor({
35
33
  onSelectedComponentChange,
36
34
  }: MultiComponentEditorProps) {
37
35
  const [selectedId, setSelectedId] = useState<string | null>(null);
38
- const thumbnailContainerRef = useRef<HTMLDivElement | null>(null);
39
36
  const placeholder = component.placeholders.find(
40
37
  (x) => x.name === placeholderName
41
38
  );
42
- const components = useMemo(
43
- () => placeholder?.components ?? null,
44
- [placeholder]
45
- );
39
+ if (!placeholder) return;
40
+ const components = placeholder.components;
41
+ if (!components) return;
46
42
 
47
43
  const handleMessage = useCallback(
48
44
  (event: MessageEvent) => {
49
- const data = event.data;
50
- if (!data || !components) return;
51
-
52
- if (data.type === "componentsSelected") {
53
- setSelectedId(data.componentIds?.[0] ?? null);
54
- return;
55
- }
56
-
57
- // Parhelia (editing-bridge) selects the surrounding component as a
58
- // whole, so only ids that resolve to one of our items may change the
59
- // selection — everything else would snap back to the first item.
60
- if (
61
- data.family === "parhelia/editing-bridge" &&
62
- data.name === "setSelection"
63
- ) {
64
- const ids: string[] = data.payload?.componentIds ?? [];
65
- const matches = components.filter((c: ComponentData) =>
66
- ids.some((id) => matchesComponent(id, c))
67
- );
68
- if (matches.length === 1) {
69
- setSelectedId(matches[0].id);
70
- } else if (matches.length > 1) {
71
- console.warn(
72
- "[MultiComponentEditor] ambiguous setSelection: %d components matched ids %o, selecting first",
73
- matches.length,
74
- ids
75
- );
76
- setSelectedId(matches[0].id);
77
- }
45
+ if (event.data.type === "componentsSelected") {
46
+ setSelectedId(event.data.componentIds[0]);
78
47
  }
79
48
  },
80
49
  [components]
@@ -86,38 +55,13 @@ export function MultiComponentEditor({
86
55
  return () => {
87
56
  window.removeEventListener("message", handleMessage);
88
57
  };
89
- }, [handleMessage]);
90
-
91
- // Parhelia's interaction overlay swallows click and pointerup before they
92
- // reach the thumbnails (its pointer capture retargets the release event),
93
- // but pointerdown still hits the DOM — select thumbnails with a native
94
- // capture listener so switching works in both editors.
95
- useEffect(() => {
96
- const container = thumbnailContainerRef.current;
97
- if (!container) return;
98
-
99
- const handlePointerDown = (event: PointerEvent) => {
100
- if (event.button !== 0) return;
101
- const thumb = (event.target as Element | null)?.closest(
102
- "[data-mce-component-id]"
103
- );
104
- const id = thumb?.getAttribute("data-mce-component-id");
105
- if (id) {
106
- setSelectedId(id);
107
- selectComponents([id]);
108
- }
109
- };
110
-
111
- container.addEventListener("pointerdown", handlePointerDown, true);
112
- return () => {
113
- container.removeEventListener("pointerdown", handlePointerDown, true);
114
- };
115
58
  }, []);
116
59
 
117
- const selectedIndex =
118
- components?.findIndex((x: ComponentData) => x.id === selectedId) ?? -1;
60
+ const selectedIndex = components.findIndex(
61
+ (x: ComponentData) => x.id === selectedId
62
+ );
119
63
  const resolvedIndex = selectedIndex < 0 ? 0 : selectedIndex;
120
- const resolvedComponent = components?.[resolvedIndex] ?? null;
64
+ const resolvedComponent = components[resolvedIndex] ?? null;
121
65
  const resolvedId = resolvedComponent?.id ?? null;
122
66
 
123
67
  useEffect(() => {
@@ -133,8 +77,6 @@ export function MultiComponentEditor({
133
77
  });
134
78
  }, [resolvedId, resolvedIndex, onSelectedComponentChange]);
135
79
 
136
- if (!placeholder || !components) return;
137
-
138
80
  const childrenArray = React.Children.toArray(children) as ReactElement[];
139
81
 
140
82
  const filteredChildren = childrenArray.filter(
@@ -144,7 +86,7 @@ export function MultiComponentEditor({
144
86
  return (
145
87
  <>
146
88
  {filteredChildren[resolvedIndex]}
147
- <div className="a-editor-mce" ref={thumbnailContainerRef}>
89
+ <div className="a-editor-mce">
148
90
  <script
149
91
  data-placeholder-start={placeholder.key}
150
92
  data-orientation="horizontal"
@@ -170,13 +112,7 @@ export function MultiComponentEditor({
170
112
  style.width = thumbWidth;
171
113
  }
172
114
 
173
- // Mid-transition renders (RSC refetch, fresh inserts) can deliver child
174
- // elements whose nesting doesn't match yet — render an empty tile for
175
- // that frame instead of crashing into the placeholder error boundary.
176
115
  const componentArray = (x as any).props?.children?.props?.children;
177
- const thumbnailContent = Array.isArray(componentArray)
178
- ? componentArray.slice(1, -1)
179
- : null;
180
116
 
181
117
  const component = components![index];
182
118
 
@@ -188,7 +124,9 @@ export function MultiComponentEditor({
188
124
  (index === resolvedIndex ? " a-editor-mce-thumbnail--selected" : "")
189
125
  }
190
126
  style={style}
191
- data-mce-component-id={component.id}
127
+ onClick={() => {
128
+ selectComponents([components![index].id]);
129
+ }}
192
130
  >
193
131
  <script
194
132
  data-component-start={component.id}
@@ -198,31 +136,16 @@ export function MultiComponentEditor({
198
136
  data-layoutid={component._editor?.hostingPageItem?.id}
199
137
  />
200
138
  <div style={{ pointerEvents: "none", zoom: thumbZoom || 0.25 }}>
201
- {thumbnailContent}
139
+ {componentArray.slice(1, -1)}
202
140
  </div>
203
141
  <script data-component-end={component.id} />
204
142
  </div>
205
- <div data-dropzone={component.id}></div>
143
+ <div data-dropzone={components[index].id}></div>
206
144
  </Fragment>
207
145
  );
208
146
  }
209
147
  }
210
148
 
211
- function matchesComponent(id: string, component: ComponentData) {
212
- const normalized = normalizeId(id);
213
- if (!normalized) return false;
214
- return (
215
- normalized === normalizeId(component.id) ||
216
- normalized === normalizeId(component._editor?.linkedComponentItem?.id)
217
- );
218
- }
219
-
220
- function normalizeId(id: string | undefined | null) {
221
- // Like Editor/packages/core/src/editor/utils.ts#stripGuid, but also removes
222
- // dashes to handle Parhelia's editing-bridge id format variations.
223
- return id ? id.replace(/[{}-]/g, "").toLowerCase() : null;
224
- }
225
-
226
149
  function selectComponents(componentIds: string[]) {
227
150
  window.top?.window.postMessage(
228
151
  { componentIds, type: "componentsSelected" },
@@ -1,9 +1,11 @@
1
1
  import axios from "axios";
2
+ // import { HttpsProxyAgent } from "https-proxy-agent";
2
3
  import { NextResponse } from "next/server";
3
4
 
4
5
  async function GET(
5
6
  req: Request,
6
7
  target: string
8
+ //{ proxy }: { proxy?: string }
7
9
  ) {
8
10
  const reqUrl = new URL(req.url);
9
11
 
@@ -15,8 +17,12 @@ async function GET(
15
17
  Cookie: req.headers.get("Cookie") || "",
16
18
  };
17
19
 
20
+ // const agent = proxy ? new HttpsProxyAgent(proxy) : undefined;
21
+
18
22
  const externalResponse = await axios.get(url, {
19
23
  headers: headers,
24
+ // httpAgent: agent,
25
+ // httpsAgent: agent,
20
26
  responseType: "stream",
21
27
  });
22
28
 
@@ -25,7 +31,10 @@ async function GET(
25
31
  });
26
32
  }
27
33
 
28
- async function POST(req: Request) {
34
+ async function POST(
35
+ req: Request
36
+ //{ proxy }: { proxy?: string }
37
+ ) {
29
38
  const reqUrl = new URL(req.url);
30
39
  const body = await req.text();
31
40
 
@@ -41,8 +50,12 @@ async function POST(req: Request) {
41
50
  Cookie: req.headers.get("Cookie") || "",
42
51
  };
43
52
 
53
+ // const agent = proxy ? new HttpsProxyAgent(proxy) : undefined;
54
+
44
55
  const externalResponse = await axios.post(url, body, {
45
56
  headers: headers,
57
+ // httpAgent: agent,
58
+ // httpsAgent: agent,
46
59
  responseType: "stream",
47
60
  });
48
61
 
package/tsconfig.json CHANGED
@@ -5,7 +5,6 @@
5
5
  "moduleResolution": "bundler",
6
6
  "jsx": "react-jsx",
7
7
  "declaration": true,
8
- "rootDir": "./src",
9
8
  "outDir": "./dist",
10
9
  "strict": true,
11
10
  "lib": ["dom", "dom.iterable", "es2021"],
@@ -1 +0,0 @@
1
- {"root":["./src/editorintegration.tsx","./src/editorintegrationclient.tsx","./src/handlebasicauthroute.ts","./src/index.ts","./src/useexposerefreshfunction.ts","./src/client-components/multicomponenteditor.tsx","./src/client-components/index.ts","./src/middleware/handlerequest.ts","./src/middleware/index.ts","./src/proxy/index.ts"],"version":"5.9.3"}