@popmelt.com/core 0.17.0 → 0.18.1
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/README.md +65 -0
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/adapter-react-three-fiber.d.mts +36 -0
- package/dist/adapter-react-three-fiber.mjs +2 -0
- package/dist/adapter-three.d.mts +2 -0
- package/dist/adapter-three.mjs +1 -1
- package/dist/bridge-entry.mjs +51 -51
- package/dist/chunk-J3UIBBU2.mjs +2 -0
- package/dist/{chunk-D5CD4PIZ.mjs → chunk-P2Y3NJ7A.mjs} +1 -1
- package/dist/cli.mjs +70 -70
- package/dist/index.d.mts +10 -6
- package/dist/index.mjs +40 -40
- package/dist/media.d.mts +3 -2
- package/dist/plugin-astro.mjs +1 -1
- package/dist/plugin-vite.mjs +1 -1
- package/dist/{server-XGSUCWFZ.mjs → server-VX66FOQO.mjs} +52 -52
- package/dist/server.mjs +52 -52
- package/dist/subjects-CeqtFged.d.mts +412 -0
- package/dist/video-adapter-Gq8saCDn.d.mts +339 -0
- package/package.json +14 -4
- package/dist/video-adapter-cDwq4uNP.d.mts +0 -666
package/README.md
CHANGED
|
@@ -243,6 +243,71 @@ If the toolbar opens but cannot reach an AI, check that:
|
|
|
243
243
|
- The framework plugin or config wrapper is installed
|
|
244
244
|
- The development server was restarted after installation
|
|
245
245
|
|
|
246
|
+
## React Three Fiber
|
|
247
|
+
|
|
248
|
+
Popmelt can target objects rendered by React Three Fiber while Core continues to
|
|
249
|
+
own the familiar hover, annotation, and thread presentation. Install the R3F
|
|
250
|
+
peers alongside Core:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
npm install @popmelt.com/core @react-three/fiber three
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Keep `PopmeltProvider` outside the canvas and mount `PopmeltThreeAdapter` inside
|
|
257
|
+
it. The adapter renders nothing; it registers the current scene, camera, and
|
|
258
|
+
renderer with the nearest provider.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import { Canvas } from '@react-three/fiber';
|
|
262
|
+
import { PopmeltProvider } from '@popmelt.com/core';
|
|
263
|
+
import { PopmeltThreeAdapter } from '@popmelt.com/core/react-three-fiber';
|
|
264
|
+
|
|
265
|
+
export function ProductPreview() {
|
|
266
|
+
return (
|
|
267
|
+
<PopmeltProvider>
|
|
268
|
+
<Canvas>
|
|
269
|
+
<PopmeltThreeAdapter />
|
|
270
|
+
<ProductScene />
|
|
271
|
+
</Canvas>
|
|
272
|
+
</PopmeltProvider>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Named objects receive readable labels automatically. Add stable application
|
|
278
|
+
identity when object names or scene ordering may change:
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
<mesh
|
|
282
|
+
name="Bottle"
|
|
283
|
+
userData={{ popmeltId: 'hero-bottle', popmeltLabel: 'Hero bottle' }}
|
|
284
|
+
>
|
|
285
|
+
{/* geometry and material */}
|
|
286
|
+
</mesh>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Use a distinct `id` for each adapter when a page owns multiple canvases. Pass
|
|
290
|
+
`root` to target only one scene subtree, `captureFrame={false}` to omit renderer
|
|
291
|
+
screenshots, or `select`, `key`, `label`, and `describe` to adapt an application's
|
|
292
|
+
scene semantics.
|
|
293
|
+
|
|
294
|
+
For integrations that need the registered adapter instance, use the hook inside
|
|
295
|
+
the canvas instead of the component:
|
|
296
|
+
|
|
297
|
+
```tsx
|
|
298
|
+
import { usePopmeltThreeAdapter } from '@popmelt.com/core/react-three-fiber';
|
|
299
|
+
|
|
300
|
+
function ProductPopmeltAdapter() {
|
|
301
|
+
const adapter = usePopmeltThreeAdapter({ id: 'product-preview' });
|
|
302
|
+
// Optional application-specific coordination with adapter.
|
|
303
|
+
void adapter;
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The component is the recommended default; the hook exposes the same lifecycle
|
|
309
|
+
for advanced composition.
|
|
310
|
+
|
|
246
311
|
## Media annotation
|
|
247
312
|
|
|
248
313
|
Manual image and video annotation are enabled by default in `PopmeltProvider`,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Camera, Object3D, Raycaster } from 'three';
|
|
2
|
+
import { P as PopmeltSubjectAdapter } from './subjects-CeqtFged.mjs';
|
|
3
|
+
|
|
4
|
+
type ThreeSubjectAdapterOptions = {
|
|
5
|
+
/** Unique adapter identity when a page owns more than one Three.js surface. */
|
|
6
|
+
id?: string;
|
|
7
|
+
canvas: HTMLCanvasElement;
|
|
8
|
+
camera: Camera;
|
|
9
|
+
scene: Object3D;
|
|
10
|
+
raycaster?: Raycaster;
|
|
11
|
+
/** Select a meaningful parent from the raw intersected render object. */
|
|
12
|
+
select?: (object: Object3D) => Object3D | null;
|
|
13
|
+
/** Override durable identity. Explicit application IDs are preferred. */
|
|
14
|
+
key?: (object: Object3D) => string | null | undefined;
|
|
15
|
+
label?: (object: Object3D) => string;
|
|
16
|
+
/** Add application-specific provenance or source hints to the model context. */
|
|
17
|
+
describe?: (object: Object3D) => Record<string, string | undefined>;
|
|
18
|
+
/** Capture the renderer's current frame for DOM-cloned screenshots. */
|
|
19
|
+
captureFrame?: () => string | null | Promise<string | null>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type PopmeltThreeAdapterOptions = Omit<ThreeSubjectAdapterOptions, 'canvas' | 'camera' | 'scene' | 'captureFrame'> & {
|
|
23
|
+
/** Scene root Popmelt should target. Defaults to the complete R3F scene. */
|
|
24
|
+
root?: Object3D;
|
|
25
|
+
/** Override frame capture, or set false to omit renderer screenshots. */
|
|
26
|
+
captureFrame?: ThreeSubjectAdapterOptions['captureFrame'] | false;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Register an R3F-owned Three.js scene with the nearest PopmeltProvider.
|
|
30
|
+
* Must run inside Canvas so React Three Fiber's renderer state is available.
|
|
31
|
+
*/
|
|
32
|
+
declare function usePopmeltThreeAdapter(options?: PopmeltThreeAdapterOptions): PopmeltSubjectAdapter;
|
|
33
|
+
/** Declarative, zero-render integration for use inside an R3F Canvas. */
|
|
34
|
+
declare function PopmeltThreeAdapter(props: PopmeltThreeAdapterOptions): null;
|
|
35
|
+
|
|
36
|
+
export { PopmeltThreeAdapter, type PopmeltThreeAdapterOptions, usePopmeltThreeAdapter };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";import{b as g}from"./chunk-J3UIBBU2.mjs";import{useThree as M}from"@react-three/fiber";import{useEffect as C,useMemo as E}from"react";import{Box3 as x,Raycaster as D,Vector2 as T,Vector3 as P}from"three";function h(e){return[e.x,e.y,e.z].map(r=>Number(r.toFixed(4))).join(", ")}function y(e){let r=e.material;return r&&(Array.isArray(r)?r:[r]).map(n=>n.name?.trim()||n.type).filter(Boolean).join(", ")||void 0}function j(e,r,s){let c=e.domElement.width,n=e.domElement.height;if(c<=0||n<=0)return null;let l=e.getRenderTarget(),t=e.xr.enabled;try{return e.xr.enabled=!1,e.setRenderTarget(null),e.render(r,s),e.domElement.toDataURL("image/png")}catch{return null}finally{e.setRenderTarget(l),e.xr.enabled=t}}function A(e){let c=(e.parent?.children??[]).filter(t=>t.type===e.type&&t.name===e.name),n=Math.max(0,c.indexOf(e)),l=e.name.trim()||e.type;return`${encodeURIComponent(l)}[${n}]`}function f(e){let r=[],s=e;for(;s?.parent;)r.push(A(s)),s=s.parent;return r.reverse().join("/")}function v(e){let r=e.userData.popmeltId;return typeof r=="string"&&r.trim()?r.trim():f(e)}function S(e){let r=e.userData.popmeltLabel;return typeof r=="string"&&r.trim()?r.trim():e.name.trim()||e.type}function F(e){let r=e;for(;r.parent;){let s=r.name.trim(),c=s.match(/^(.*)_(?:alpha|normal|material)(?:_\d+)+$/i),n=r.parent;for(;n.parent&&!n.name.trim();)n=n.parent;let l=n.name.trim();if(!l||!s.startsWith(`${l}_`)&&!c)break;r=n}return r}function R(e,r,s){let c=new x().setFromObject(e,!0);if(c.isEmpty())return null;let n=s.getBoundingClientRect(),l=[];for(let p of[c.min.x,c.max.x])for(let d of[c.min.y,c.max.y])for(let b of[c.min.z,c.max.z])l.push(new P(p,d,b).project(r));let t=l.map(p=>n.left+(p.x+1)/2*n.width),a=l.map(p=>n.top+(1-p.y)/2*n.height),i=Math.max(n.left,Math.min(...t)),o=Math.min(n.right,Math.max(...t)),m=Math.max(n.top,Math.min(...a)),u=Math.min(n.bottom,Math.max(...a));return o<=i||u<=m?null:{left:i,top:m,width:o-i,height:u-m}}function O(e){let r=e.raycaster??new D,s=new T,c=t=>e.key?.(t)??v(t),n=(t,a)=>{let i=c(t);if(!i)return null;let o=R(t,e.camera,e.canvas);return o?{key:i,label:e.label?.(t)??S(t),sourceElement:e.canvas,bounds:o,context:f(t),data:{renderer:"Three.js",objectType:t.type,...t.name?{objectName:t.name}:{},scenePath:f(t),...a&&a!==t?{renderObjectName:a.name.trim()||a.type,renderObjectType:a.type,renderScenePath:f(a)}:{},position:h(t.position),rotation:h(t.rotation),scale:h(t.scale),visible:String(t.visible),...y(t)?{material:y(t)}:{},...Object.fromEntries(Object.entries(e.describe?.(t)??{}).filter(m=>typeof m[1]=="string"&&m[1].length>0))}}:null},l=t=>{let a=null;return e.scene.traverse(i=>{!a&&c(i)===t&&(a=i)}),a};return{id:e.id?.trim()||"three",hitTest({x:t,y:a}){let i=e.canvas.getBoundingClientRect();if(t<i.left||t>i.right||a<i.top||a>i.bottom)return null;s.set((t-i.left)/i.width*2-1,-((a-i.top)/i.height)*2+1),r.setFromCamera(s,e.camera);for(let o of r.intersectObject(e.scene,!0)){let m=e.select?e.select(o.object):F(o.object);if(!m||!m.visible)continue;let u=n(m,o.object);if(u)return u}return null},resolve(t){let a=l(t);return a?n(a):null},...e.captureFrame?{async captureSurfaces(){let t=await e.captureFrame?.();return t?[{element:e.canvas,dataUrl:t}]:[]}}:{}}}function w(e={}){let{registerSubjectAdapter:r}=g(),{gl:s,camera:c,scene:n}=M(),{root:l=n,captureFrame:t,describe:a,id:i,key:o,label:m,raycaster:u,select:p}=e,d=E(()=>O({id:i,canvas:s.domElement,camera:c,scene:l,raycaster:u,select:p,key:o,label:m,describe:b=>({framework:"@react-three/fiber",...a?.(b)}),...t===!1?{}:{captureFrame:t??(()=>j(s,n,c))}}),[c,t,a,s,i,o,m,u,l,n,p]);return C(()=>r(d),[d,r]),d}function U(e){return w(e),null}export{U as PopmeltThreeAdapter,w as usePopmeltThreeAdapter};
|
package/dist/adapter-three.d.mts
CHANGED
|
@@ -152,6 +152,8 @@ type PopmeltSubjectAdapter = {
|
|
|
152
152
|
};
|
|
153
153
|
|
|
154
154
|
type ThreeSubjectAdapterOptions = {
|
|
155
|
+
/** Unique adapter identity when a page owns more than one Three.js surface. */
|
|
156
|
+
id?: string;
|
|
155
157
|
canvas: HTMLCanvasElement;
|
|
156
158
|
camera: Camera;
|
|
157
159
|
scene: Object3D;
|
package/dist/adapter-three.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Box3 as y,Raycaster as x,Vector2 as O,Vector3 as j}from"three";function b(e){return[e.x,e.y,e.z].map(n=>Number(n.toFixed(4))).join(", ")}function
|
|
1
|
+
import{Box3 as y,Raycaster as x,Vector2 as O,Vector3 as j}from"three";function b(e){return[e.x,e.y,e.z].map(n=>Number(n.toFixed(4))).join(", ")}function d(e){let n=e.material;return n&&(Array.isArray(n)?n:[n]).map(r=>r.name?.trim()||r.type).filter(Boolean).join(", ")||void 0}function M(e,n,c){let s=e.domElement.width,r=e.domElement.height;if(s<=0||r<=0)return null;let l=e.getRenderTarget(),t=e.xr.enabled;try{return e.xr.enabled=!1,e.setRenderTarget(null),e.render(n,c),e.domElement.toDataURL("image/png")}catch{return null}finally{e.setRenderTarget(l),e.xr.enabled=t}}function D(e){let s=(e.parent?.children??[]).filter(t=>t.type===e.type&&t.name===e.name),r=Math.max(0,s.indexOf(e)),l=e.name.trim()||e.type;return`${encodeURIComponent(l)}[${r}]`}function f(e){let n=[],c=e;for(;c?.parent;)n.push(D(c)),c=c.parent;return n.reverse().join("/")}function v(e){let n=e.userData.popmeltId;return typeof n=="string"&&n.trim()?n.trim():f(e)}function T(e){let n=e.userData.popmeltLabel;return typeof n=="string"&&n.trim()?n.trim():e.name.trim()||e.type}function R(e){let n=e;for(;n.parent;){let c=n.name.trim(),s=c.match(/^(.*)_(?:alpha|normal|material)(?:_\d+)+$/i),r=n.parent;for(;r.parent&&!r.name.trim();)r=r.parent;let l=r.name.trim();if(!l||!c.startsWith(`${l}_`)&&!s)break;n=r}return n}function P(e,n,c){let s=new y().setFromObject(e,!0);if(s.isEmpty())return null;let r=c.getBoundingClientRect(),l=[];for(let p of[s.min.x,s.max.x])for(let h of[s.min.y,s.max.y])for(let g of[s.min.z,s.max.z])l.push(new j(p,h,g).project(n));let t=l.map(p=>r.left+(p.x+1)/2*r.width),a=l.map(p=>r.top+(1-p.y)/2*r.height),i=Math.max(r.left,Math.min(...t)),u=Math.min(r.right,Math.max(...t)),m=Math.max(r.top,Math.min(...a)),o=Math.min(r.bottom,Math.max(...a));return u<=i||o<=m?null:{left:i,top:m,width:u-i,height:o-m}}function C(e){let n=e.raycaster??new x,c=new O,s=t=>e.key?.(t)??v(t),r=(t,a)=>{let i=s(t);if(!i)return null;let u=P(t,e.camera,e.canvas);return u?{key:i,label:e.label?.(t)??T(t),sourceElement:e.canvas,bounds:u,context:f(t),data:{renderer:"Three.js",objectType:t.type,...t.name?{objectName:t.name}:{},scenePath:f(t),...a&&a!==t?{renderObjectName:a.name.trim()||a.type,renderObjectType:a.type,renderScenePath:f(a)}:{},position:b(t.position),rotation:b(t.rotation),scale:b(t.scale),visible:String(t.visible),...d(t)?{material:d(t)}:{},...Object.fromEntries(Object.entries(e.describe?.(t)??{}).filter(m=>typeof m[1]=="string"&&m[1].length>0))}}:null},l=t=>{let a=null;return e.scene.traverse(i=>{!a&&s(i)===t&&(a=i)}),a};return{id:e.id?.trim()||"three",hitTest({x:t,y:a}){let i=e.canvas.getBoundingClientRect();if(t<i.left||t>i.right||a<i.top||a>i.bottom)return null;c.set((t-i.left)/i.width*2-1,-((a-i.top)/i.height)*2+1),n.setFromCamera(c,e.camera);for(let u of n.intersectObject(e.scene,!0)){let m=e.select?e.select(u.object):R(u.object);if(!m||!m.visible)continue;let o=r(m,u.object);if(o)return o}return null},resolve(t){let a=l(t);return a?r(a):null},...e.captureFrame?{async captureSurfaces(){let t=await e.captureFrame?.();return t?[{element:e.canvas,dataUrl:t}]:[]}}:{}}}export{M as captureThreeRendererFrame,C as createThreeSubjectAdapter,R as selectThreeNamedPrimitiveParent,f as threeObjectPath};
|