@jamesyong42/infinite-canvas 1.1.0 → 1.2.0
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 +105 -8
- package/dist/SelectionRenderer-CR2PBQwx.d.cts +105 -0
- package/dist/SelectionRenderer-CR2PBQwx.d.cts.map +1 -0
- package/dist/SelectionRenderer-DlsBstAq.d.mts +105 -0
- package/dist/SelectionRenderer-DlsBstAq.d.mts.map +1 -0
- package/dist/WebGLWidgetLayer-BBMuwzHq.cjs +3560 -0
- package/dist/WebGLWidgetLayer-BBMuwzHq.cjs.map +1 -0
- package/dist/WebGLWidgetLayer-C3p1tnpm.mjs +3375 -0
- package/dist/WebGLWidgetLayer-C3p1tnpm.mjs.map +1 -0
- package/dist/advanced.cjs +110 -166
- package/dist/advanced.cjs.map +1 -1
- package/dist/advanced.d.cts +58 -42
- package/dist/advanced.d.cts.map +1 -0
- package/dist/advanced.d.mts +99 -0
- package/dist/advanced.d.mts.map +1 -0
- package/dist/advanced.mjs +105 -0
- package/dist/advanced.mjs.map +1 -0
- package/dist/devtools.cjs +378 -352
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.d.cts +15 -11
- package/dist/devtools.d.cts.map +1 -0
- package/dist/devtools.d.mts +23 -0
- package/dist/devtools.d.mts.map +1 -0
- package/dist/devtools.mjs +652 -0
- package/dist/devtools.mjs.map +1 -0
- package/dist/engine-BfbvWXSk.d.mts +982 -0
- package/dist/engine-BfbvWXSk.d.mts.map +1 -0
- package/dist/engine-CCjuFMC-.d.cts +982 -0
- package/dist/engine-CCjuFMC-.d.cts.map +1 -0
- package/dist/hooks-BwY7rRHg.mjs +425 -0
- package/dist/hooks-BwY7rRHg.mjs.map +1 -0
- package/dist/hooks-DHShH86C.cjs +707 -0
- package/dist/hooks-DHShH86C.cjs.map +1 -0
- package/dist/index.cjs +909 -824
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -74
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +258 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +855 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +44 -17
- package/dist/SelectionRenderer-DRtwHWJ0.d.cts +0 -102
- package/dist/SelectionRenderer-rGYPadnn.d.ts +0 -102
- package/dist/advanced.d.ts +0 -83
- package/dist/advanced.js +0 -125
- package/dist/advanced.js.map +0 -1
- package/dist/chunk-2KBYGER3.cjs +0 -336
- package/dist/chunk-2KBYGER3.cjs.map +0 -1
- package/dist/chunk-FUPKRQB2.cjs +0 -3025
- package/dist/chunk-FUPKRQB2.cjs.map +0 -1
- package/dist/chunk-NILAZG6O.js +0 -292
- package/dist/chunk-NILAZG6O.js.map +0 -1
- package/dist/chunk-W2ZNA7HP.js +0 -2977
- package/dist/chunk-W2ZNA7HP.js.map +0 -1
- package/dist/devtools.d.ts +0 -19
- package/dist/devtools.js +0 -626
- package/dist/devtools.js.map +0 -1
- package/dist/engine-DqgJ82tq.d.cts +0 -805
- package/dist/engine-DqgJ82tq.d.ts +0 -805
- package/dist/index.d.ts +0 -151
- package/dist/index.js +0 -604
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -17,6 +17,7 @@ Build Figma-style infinite canvases in React -- drag, resize, snap, zoom, nested
|
|
|
17
17
|
- **Undo / redo** -- Command buffer with grouped operations (an entire drag is one undo step)
|
|
18
18
|
- **Hierarchical navigation** -- Enter and exit nested containers with camera state preservation
|
|
19
19
|
- **ECS architecture** -- Extensible via custom components, tags, and systems with topologically-sorted scheduling
|
|
20
|
+
- **Card widgets** -- iOS-style preset-sized tiles (small / medium / large / xl) with rounded corners, soft shadows, and lift-on-drag animation; DOM or R3F/PBR flavors via `createCardWidget` / `createGeometryCardWidget`
|
|
20
21
|
- **Performance** -- SDF shaders for grid and selection chrome, RBush spatial indexing, viewport culling, per-system profiling
|
|
21
22
|
- **Live ECS editor** -- Drop-in `<EcsDevtools>` panel for spawning, inspecting, and editing components and tags at runtime
|
|
22
23
|
- **Dark mode** -- Full dark mode support across canvas, widgets, and UI chrome
|
|
@@ -215,6 +216,97 @@ Spawning is uniform: `engine.spawn(id, options)`. If `id` matches an archetype,
|
|
|
215
216
|
| `parent` | Parent entity id for nesting. |
|
|
216
217
|
| `rotation` | Initial rotation in radians. |
|
|
217
218
|
|
|
219
|
+
The `interactive` field on `Archetype` accepts a boolean or an object. Pass `{ selectable, draggable, resizable, selectionFrame }` (any subset) when you want finer control. Cards that move, select, but never resize and render their own chrome: `{ selectable: true, draggable: true, resizable: false, selectionFrame: false }`. Omitted keys default to `false`, except `selectionFrame` which follows `selectable` (an entity you can select gets a frame unless you opt out).
|
|
220
|
+
|
|
221
|
+
## Card Widgets
|
|
222
|
+
|
|
223
|
+
**Card widgets** are fixed-size, non-resizable widgets that sit on an iOS-style preset grid. They ship with rounded corners, a soft drop shadow, a hairline ring, and a subtle lift animation while dragging. Use them when you want dashboard-style tiles rather than free-form resizable surfaces.
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
import { createCardWidget } from '@jamesyong42/infinite-canvas';
|
|
227
|
+
import { z } from 'zod';
|
|
228
|
+
|
|
229
|
+
const schema = z.object({ label: z.string().default('Hi') });
|
|
230
|
+
|
|
231
|
+
export const Greeting = createCardWidget<{ label: string }>({
|
|
232
|
+
type: 'greeting-card',
|
|
233
|
+
size: 'small', // 'small' | 'medium' | 'large' | 'xl'
|
|
234
|
+
schema,
|
|
235
|
+
defaultData: { label: 'Hi' },
|
|
236
|
+
render: ({ data }) => (
|
|
237
|
+
<div className="flex h-full w-full items-center justify-center bg-white">
|
|
238
|
+
{data.label}
|
|
239
|
+
</div>
|
|
240
|
+
),
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Register both the widget and the matching archetype.
|
|
244
|
+
const engine = createLayoutEngine({
|
|
245
|
+
widgets: [Greeting.widget],
|
|
246
|
+
archetypes: [Greeting.archetype],
|
|
247
|
+
});
|
|
248
|
+
engine.spawn('greeting-card', { at: { x: 50, y: 50 } });
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Preset sizes (default, matching iOS widget conventions on a 19 px grid):
|
|
252
|
+
|
|
253
|
+
| Preset | Width × Height |
|
|
254
|
+
|--------|----------------|
|
|
255
|
+
| `small` | 155 × 155 |
|
|
256
|
+
| `medium` | 329 × 155 |
|
|
257
|
+
| `large` | 329 × 345 |
|
|
258
|
+
| `xl` | 329 × 535 |
|
|
259
|
+
|
|
260
|
+
Override per-engine via `createLayoutEngine({ cardPresets: { presets: { small: { width: 200, height: 200 } }, gap: 24 } })`. Omitted presets keep their defaults.
|
|
261
|
+
|
|
262
|
+
Under the hood: the returned widget wraps your `render` in `<CardFrame>` (exported for manual composition), the archetype is non-resizable, and it bundles a `Card` component. A built-in `cardSystem` stamps `Transform2D.width/height` from `Card.preset` each tick — to change a card's size at runtime, update the preset: `engine.set(id, Card, { preset: 'large' })`. Reading the `Dragging` tag from the frame drives the lift affordance; you can read it elsewhere too via `useTag(entityId, Dragging)`.
|
|
263
|
+
|
|
264
|
+
Cards also opt out of the engine-drawn selection + hover outline (`selectionFrame: false` in their archetype) — the iOS rounded chrome in `<CardFrame>` is the card's visual contract, so the standard blue frame would fight it. If you need a selected/hover affordance inside a card, read `useIsSelected(entityId)` / `useTag(entityId, /* Hovered tag */)` from within `render` and style accordingly.
|
|
265
|
+
|
|
266
|
+
### 3D Card Widgets
|
|
267
|
+
|
|
268
|
+
`createGeometryCardWidget` is the R3F counterpart — same preset sizes, non-resizable archetype, and drag-lift behavior, but the widget body is a three.js scene instead of DOM content. The helper pairs cleanly with PBR materials.
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
import { createGeometryCardWidget } from '@jamesyong42/infinite-canvas';
|
|
272
|
+
import { useFrame } from '@react-three/fiber';
|
|
273
|
+
import { useRef } from 'react';
|
|
274
|
+
import type { Mesh } from 'three';
|
|
275
|
+
import { z } from 'zod';
|
|
276
|
+
|
|
277
|
+
const schema = z.object({ color: z.string().default('#F5B8D0') });
|
|
278
|
+
|
|
279
|
+
export const Sphere = createGeometryCardWidget<{ color: string }>({
|
|
280
|
+
type: 'sphere',
|
|
281
|
+
size: 'small',
|
|
282
|
+
schema,
|
|
283
|
+
defaultData: { color: '#F5B8D0' },
|
|
284
|
+
background: 'card', // or 'transparent' — the geometry floats over the canvas
|
|
285
|
+
geometry: ({ data, width }) => {
|
|
286
|
+
const ref = useRef<Mesh>(null);
|
|
287
|
+
useFrame((_, dt) => { if (ref.current) ref.current.rotation.y += dt * 0.3; });
|
|
288
|
+
return (
|
|
289
|
+
<group>
|
|
290
|
+
<pointLight position={[80, 80, 120]} intensity={160} distance={300} decay={1.4} />
|
|
291
|
+
<ambientLight intensity={0.3} />
|
|
292
|
+
<mesh ref={ref}>
|
|
293
|
+
<sphereGeometry args={[width * 0.32, 48, 48]} />
|
|
294
|
+
<meshStandardMaterial color={data.color} roughness={0.35} />
|
|
295
|
+
</mesh>
|
|
296
|
+
</group>
|
|
297
|
+
);
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
`background` options:
|
|
303
|
+
|
|
304
|
+
- `'card'` (default) — a rounded iOS-style card mesh sits behind the geometry in the same widget group.
|
|
305
|
+
- `'transparent'` — no back plane; the geometry floats over whatever's behind the widget.
|
|
306
|
+
- `{ color, roughness?, metalness? }` — card back with custom PBR parameters for tinted or glossy variants.
|
|
307
|
+
|
|
308
|
+
**Lighting caveat.** All R3F widgets share a single `<Canvas>`, so lights and `envMap`s you declare inside one widget's render function affect every other 3D widget. Keep per-widget lights `pointLight`s with `distance` scoped to the widget's size, or add one shared `<Environment>` at the app level (if you control the R3F canvas). The helper itself adds no lights — declare what you need inside your `geometry` component.
|
|
309
|
+
|
|
218
310
|
## WebGL Widgets (R3F)
|
|
219
311
|
|
|
220
312
|
Define an `R3FWidget<T>` with `surface: 'webgl'` to render 3D content via React Three Fiber. R3F widget views receive `{ entityId, width, height }` and render in local coordinates (origin at widget centre):
|
|
@@ -525,20 +617,25 @@ z:3 UI chrome
|
|
|
525
617
|
| `InteractionRole` | Interaction behavior (drag, select, resize, etc.) |
|
|
526
618
|
| `HandleSet` | Child handle entity references |
|
|
527
619
|
| `CursorHint` | Cursor style on hover/active |
|
|
620
|
+
| `Card` | Marks an iOS-style card; carries the preset (`small`/`medium`/`large`/`xl`) |
|
|
528
621
|
|
|
529
622
|
### ECS Tags
|
|
530
623
|
|
|
531
|
-
`Selectable` `Draggable` `Resizable` `Locked` `Selected` `Active` `Visible`
|
|
624
|
+
`Selectable` `Draggable` `Resizable` `SelectionFrame` `Locked` `Selected` `Dragging` `Active` `Visible`
|
|
625
|
+
|
|
626
|
+
- `Dragging` — transient state tag (parallels `Selected`): added when the drag dead zone is crossed, removed on pointer up or cancel. Read via `useTag(entityId, Dragging)` to drive drag-time affordances.
|
|
627
|
+
- `SelectionFrame` — opts an entity into the engine-drawn selection + hover outline. Granted automatically to Selectable entities via the archetype's `interactive` caps; widgets that render their own chrome (e.g. cards) opt out.
|
|
532
628
|
|
|
533
629
|
### Systems (execution order)
|
|
534
630
|
|
|
535
|
-
1. `
|
|
536
|
-
2. `
|
|
537
|
-
3. `
|
|
538
|
-
4. `
|
|
539
|
-
5. `
|
|
540
|
-
6. `
|
|
541
|
-
7. `
|
|
631
|
+
1. `card` -- Stamp Transform2D size from Card preset
|
|
632
|
+
2. `transformPropagate` -- Propagate transforms down hierarchy, compute WorldBounds
|
|
633
|
+
3. `handleSync` -- Synchronize resize handle entities with parent widgets
|
|
634
|
+
4. `hitboxWorldBounds` -- Compute world-space hitbox bounds
|
|
635
|
+
5. `navigationFilter` -- Filter entities to active navigation layer
|
|
636
|
+
6. `cull` -- Mark viewport-visible entities
|
|
637
|
+
7. `breakpoint` -- Compute responsive breakpoints
|
|
638
|
+
8. `sort` -- Z-index ordering
|
|
542
639
|
|
|
543
640
|
## Performance Profiling
|
|
544
641
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { F as DomWidgetProps, L as R3FWidgetProps, b as EqualSpacingIndicator, n as LayoutEngine, x as SnapGuide } from "./engine-CCjuFMC-.cjs";
|
|
2
|
+
import { EntityId } from "@jamesyong42/reactive-ecs";
|
|
3
|
+
import * as _$react from "react";
|
|
4
|
+
import * as THREE from "three";
|
|
5
|
+
|
|
6
|
+
//#region src/react/context.d.ts
|
|
7
|
+
declare const EngineProvider: _$react.Provider<LayoutEngine | null>;
|
|
8
|
+
declare const ContainerRefProvider: _$react.Provider<_$react.RefObject<HTMLDivElement | null> | null>;
|
|
9
|
+
declare function useContainerRef(): React.RefObject<HTMLDivElement | null> | null;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the LayoutEngine instance from the nearest InfiniteCanvas context.
|
|
12
|
+
* Throws if used outside an InfiniteCanvas provider.
|
|
13
|
+
*/
|
|
14
|
+
declare function useLayoutEngine(): LayoutEngine;
|
|
15
|
+
/**
|
|
16
|
+
* Discriminated resolution of a widget by type. The surface determines which
|
|
17
|
+
* layer renders the component and with what prop shape.
|
|
18
|
+
*/
|
|
19
|
+
type ResolvedWidget = {
|
|
20
|
+
surface: 'dom';
|
|
21
|
+
component: React.ComponentType<DomWidgetProps>;
|
|
22
|
+
} | {
|
|
23
|
+
surface: 'webgl';
|
|
24
|
+
component: React.ComponentType<R3FWidgetProps>;
|
|
25
|
+
};
|
|
26
|
+
type WidgetResolver = (entityId: EntityId, widgetType: string) => ResolvedWidget | null;
|
|
27
|
+
declare const WidgetResolverProvider: _$react.Provider<WidgetResolver | null>;
|
|
28
|
+
declare function useWidgetResolver(): WidgetResolver | null;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/react/webgl/GridRenderer.d.ts
|
|
31
|
+
interface GridConfig {
|
|
32
|
+
/** World-unit spacings for up to 3 grid levels [fine, medium, coarse]. */
|
|
33
|
+
spacings: [number, number, number];
|
|
34
|
+
/** Dot RGB color as [r, g, b] in 0–1 range. */
|
|
35
|
+
dotColor: [number, number, number];
|
|
36
|
+
/** Base dot opacity multiplier (0–1). */
|
|
37
|
+
dotAlpha: number;
|
|
38
|
+
/** CSS-pixel range where a grid level fades in: [start, end]. */
|
|
39
|
+
fadeIn: [number, number];
|
|
40
|
+
/** CSS-pixel range where a grid level fades out: [start, end]. */
|
|
41
|
+
fadeOut: [number, number];
|
|
42
|
+
/** Dot radius range in CSS pixels [min, max]. Scaled by DPR internally. */
|
|
43
|
+
dotRadius: [number, number];
|
|
44
|
+
/** Per-level opacity weight: level i gets (base + i * step). */
|
|
45
|
+
levelWeight: [number, number];
|
|
46
|
+
}
|
|
47
|
+
declare const DEFAULT_GRID_CONFIG: GridConfig;
|
|
48
|
+
declare class GridRenderer {
|
|
49
|
+
private renderer;
|
|
50
|
+
private scene;
|
|
51
|
+
private camera;
|
|
52
|
+
private material;
|
|
53
|
+
private mesh;
|
|
54
|
+
constructor(canvas: HTMLCanvasElement);
|
|
55
|
+
/** Apply a (partial) grid config. Only provided fields are updated. */
|
|
56
|
+
setConfig(config: Partial<GridConfig>): void;
|
|
57
|
+
setSize(width: number, height: number, dpr?: number): void;
|
|
58
|
+
render(cameraX: number, cameraY: number, zoom: number): void;
|
|
59
|
+
dispose(): void;
|
|
60
|
+
/** Expose for future WebGL widget rendering */
|
|
61
|
+
getWebGLRenderer(): THREE.WebGLRenderer;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/react/webgl/SelectionRenderer.d.ts
|
|
65
|
+
interface SelectionConfig {
|
|
66
|
+
/** Selection outline color [r,g,b] 0-1. Default: Figma blue. */
|
|
67
|
+
outlineColor: [number, number, number];
|
|
68
|
+
/** Selection outline width in screen px. */
|
|
69
|
+
outlineWidth: number;
|
|
70
|
+
/** Hover outline color [r,g,b] 0-1. */
|
|
71
|
+
hoverColor: [number, number, number];
|
|
72
|
+
/** Hover outline width in screen px. */
|
|
73
|
+
hoverWidth: number;
|
|
74
|
+
/** Handle size in screen px. */
|
|
75
|
+
handleSize: number;
|
|
76
|
+
/** Handle fill color [r,g,b] 0-1 (white). */
|
|
77
|
+
handleFill: [number, number, number];
|
|
78
|
+
/** Handle border color [r,g,b] 0-1 (same as outline). */
|
|
79
|
+
handleBorder: [number, number, number];
|
|
80
|
+
/** Handle border width in screen px. */
|
|
81
|
+
handleBorderWidth: number;
|
|
82
|
+
/** Group bbox dash length in screen px (0 = solid). */
|
|
83
|
+
groupDash: number;
|
|
84
|
+
}
|
|
85
|
+
declare const DEFAULT_SELECTION_CONFIG: SelectionConfig;
|
|
86
|
+
interface SelectionBounds {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
width: number;
|
|
90
|
+
height: number;
|
|
91
|
+
}
|
|
92
|
+
declare class SelectionRenderer {
|
|
93
|
+
private material;
|
|
94
|
+
private mesh;
|
|
95
|
+
private scene;
|
|
96
|
+
private camera;
|
|
97
|
+
constructor();
|
|
98
|
+
setConfig(config: Partial<SelectionConfig>): void;
|
|
99
|
+
setSize(resolution: THREE.Vector2, dpr: number): void;
|
|
100
|
+
render(renderer: THREE.WebGLRenderer, cameraX: number, cameraY: number, zoom: number, selected: SelectionBounds[], hovered: SelectionBounds | null, guides?: SnapGuide[], spacings?: EqualSpacingIndicator[]): void;
|
|
101
|
+
dispose(): void;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { DEFAULT_GRID_CONFIG as a, ContainerRefProvider as c, WidgetResolverProvider as d, useContainerRef as f, SelectionRenderer as i, EngineProvider as l, useWidgetResolver as m, SelectionBounds as n, GridConfig as o, useLayoutEngine as p, SelectionConfig as r, GridRenderer as s, DEFAULT_SELECTION_CONFIG as t, ResolvedWidget as u };
|
|
105
|
+
//# sourceMappingURL=SelectionRenderer-CR2PBQwx.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionRenderer-CR2PBQwx.d.cts","names":[],"sources":["../src/react/context.ts","../src/react/webgl/GridRenderer.ts","../src/react/webgl/SelectionRenderer.ts"],"mappings":";;;;;;cASa,cAAA,EAAc,OAAA,CAAA,QAAA,CAAA,YAAA;AAAA,cAOd,oBAAA,EAAoB,OAAA,CAAA,QAAA,CAAA,OAAA,CAAA,SAAA,CAAA,cAAA;AAAA,iBAEjB,eAAA,CAAA,GAAmB,KAAA,CAAM,SAAA,CAAU,cAAA;AATnD;;;;AAAA,iBAiBgB,eAAA,CAAA,GAAmB,YAAA;;;;;KAgBvB,cAAA;EACP,OAAA;EAAgB,SAAA,EAAW,KAAA,CAAM,aAAA,CAAc,cAAA;AAAA;EAC/C,OAAA;EAAkB,SAAA,EAAW,KAAA,CAAM,aAAA,CAAc,cAAA;AAAA;AAAA,KAE1C,cAAA,IAAkB,QAAA,EAAU,QAAA,EAAU,UAAA,aAAuB,cAAA;AAAA,cAI5D,sBAAA,EAAsB,OAAA,CAAA,QAAA,CAAA,cAAA;AAAA,iBAEnB,iBAAA,CAAA,GAAqB,cAAA;;;UChDpB,UAAA;;EAEhB,QAAA;;EAEA,QAAA;EDCY;ECCZ,QAAA;;EAEA,MAAA;EDH0B;ECK1B,OAAA;EDE+D;ECA/D,SAAA;EDAgC;ECEhC,WAAA;AAAA;AAAA,cAGY,mBAAA,EAAqB,UAAA;AAAA,cAoFrB,YAAA;EAAA,QACJ,QAAA;EAAA,QACA,KAAA;EAAA,QACA,MAAA;EAAA,QACA,QAAA;EAAA,QACA,IAAA;cAEI,MAAA,EAAQ,iBAAA;ED9FU;EC8I9B,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,UAAA;EAW1B,OAAA,CAAQ,KAAA,UAAe,MAAA,UAAgB,GAAA;EAQvC,MAAA,CAAO,OAAA,UAAiB,OAAA,UAAiB,IAAA;EAOzC,OAAA,CAAA;EDxKkD;EC+KlD,gBAAA,CAAA,GAAoB,KAAA,CAAM,aAAA;AAAA;;;UC3LV,eAAA;;EAEhB,YAAA;;EAEA,YAAA;EFDmD;EEGnD,UAAA;EFH0B;EEK1B,UAAA;EFEY;EEAZ,UAAA;;EAEA,UAAA;EFFgC;EEIhC,YAAA;EFJgC;EEMhC,iBAAA;EFNgC;EEQhC,SAAA;AAAA;AAAA,cAGY,wBAAA,EAA0B,eAAA;AAAA,UActB,eAAA;EAChB,CAAA;EACA,CAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,cAoOY,iBAAA;EAAA,QACJ,QAAA;EAAA,QACA,IAAA;EAAA,QACA,KAAA;EAAA,QACA,MAAA;;EAsDR,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,eAAA;EAc1B,OAAA,CAAQ,UAAA,EAAY,KAAA,CAAM,OAAA,EAAS,GAAA;EAKnC,MAAA,CACC,QAAA,EAAU,KAAA,CAAM,aAAA,EAChB,OAAA,UACA,OAAA,UACA,IAAA,UACA,QAAA,EAAU,eAAA,IACV,OAAA,EAAS,eAAA,SACT,MAAA,GAAQ,SAAA,IACR,QAAA,GAAU,qBAAA;EAiFX,OAAA,CAAA;AAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { F as DomWidgetProps, L as R3FWidgetProps, b as EqualSpacingIndicator, n as LayoutEngine, x as SnapGuide } from "./engine-BfbvWXSk.mjs";
|
|
2
|
+
import { EntityId } from "@jamesyong42/reactive-ecs";
|
|
3
|
+
import * as _$react from "react";
|
|
4
|
+
import * as THREE from "three";
|
|
5
|
+
|
|
6
|
+
//#region src/react/context.d.ts
|
|
7
|
+
declare const EngineProvider: _$react.Provider<LayoutEngine | null>;
|
|
8
|
+
declare const ContainerRefProvider: _$react.Provider<_$react.RefObject<HTMLDivElement | null> | null>;
|
|
9
|
+
declare function useContainerRef(): React.RefObject<HTMLDivElement | null> | null;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the LayoutEngine instance from the nearest InfiniteCanvas context.
|
|
12
|
+
* Throws if used outside an InfiniteCanvas provider.
|
|
13
|
+
*/
|
|
14
|
+
declare function useLayoutEngine(): LayoutEngine;
|
|
15
|
+
/**
|
|
16
|
+
* Discriminated resolution of a widget by type. The surface determines which
|
|
17
|
+
* layer renders the component and with what prop shape.
|
|
18
|
+
*/
|
|
19
|
+
type ResolvedWidget = {
|
|
20
|
+
surface: 'dom';
|
|
21
|
+
component: React.ComponentType<DomWidgetProps>;
|
|
22
|
+
} | {
|
|
23
|
+
surface: 'webgl';
|
|
24
|
+
component: React.ComponentType<R3FWidgetProps>;
|
|
25
|
+
};
|
|
26
|
+
type WidgetResolver = (entityId: EntityId, widgetType: string) => ResolvedWidget | null;
|
|
27
|
+
declare const WidgetResolverProvider: _$react.Provider<WidgetResolver | null>;
|
|
28
|
+
declare function useWidgetResolver(): WidgetResolver | null;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/react/webgl/GridRenderer.d.ts
|
|
31
|
+
interface GridConfig {
|
|
32
|
+
/** World-unit spacings for up to 3 grid levels [fine, medium, coarse]. */
|
|
33
|
+
spacings: [number, number, number];
|
|
34
|
+
/** Dot RGB color as [r, g, b] in 0–1 range. */
|
|
35
|
+
dotColor: [number, number, number];
|
|
36
|
+
/** Base dot opacity multiplier (0–1). */
|
|
37
|
+
dotAlpha: number;
|
|
38
|
+
/** CSS-pixel range where a grid level fades in: [start, end]. */
|
|
39
|
+
fadeIn: [number, number];
|
|
40
|
+
/** CSS-pixel range where a grid level fades out: [start, end]. */
|
|
41
|
+
fadeOut: [number, number];
|
|
42
|
+
/** Dot radius range in CSS pixels [min, max]. Scaled by DPR internally. */
|
|
43
|
+
dotRadius: [number, number];
|
|
44
|
+
/** Per-level opacity weight: level i gets (base + i * step). */
|
|
45
|
+
levelWeight: [number, number];
|
|
46
|
+
}
|
|
47
|
+
declare const DEFAULT_GRID_CONFIG: GridConfig;
|
|
48
|
+
declare class GridRenderer {
|
|
49
|
+
private renderer;
|
|
50
|
+
private scene;
|
|
51
|
+
private camera;
|
|
52
|
+
private material;
|
|
53
|
+
private mesh;
|
|
54
|
+
constructor(canvas: HTMLCanvasElement);
|
|
55
|
+
/** Apply a (partial) grid config. Only provided fields are updated. */
|
|
56
|
+
setConfig(config: Partial<GridConfig>): void;
|
|
57
|
+
setSize(width: number, height: number, dpr?: number): void;
|
|
58
|
+
render(cameraX: number, cameraY: number, zoom: number): void;
|
|
59
|
+
dispose(): void;
|
|
60
|
+
/** Expose for future WebGL widget rendering */
|
|
61
|
+
getWebGLRenderer(): THREE.WebGLRenderer;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/react/webgl/SelectionRenderer.d.ts
|
|
65
|
+
interface SelectionConfig {
|
|
66
|
+
/** Selection outline color [r,g,b] 0-1. Default: Figma blue. */
|
|
67
|
+
outlineColor: [number, number, number];
|
|
68
|
+
/** Selection outline width in screen px. */
|
|
69
|
+
outlineWidth: number;
|
|
70
|
+
/** Hover outline color [r,g,b] 0-1. */
|
|
71
|
+
hoverColor: [number, number, number];
|
|
72
|
+
/** Hover outline width in screen px. */
|
|
73
|
+
hoverWidth: number;
|
|
74
|
+
/** Handle size in screen px. */
|
|
75
|
+
handleSize: number;
|
|
76
|
+
/** Handle fill color [r,g,b] 0-1 (white). */
|
|
77
|
+
handleFill: [number, number, number];
|
|
78
|
+
/** Handle border color [r,g,b] 0-1 (same as outline). */
|
|
79
|
+
handleBorder: [number, number, number];
|
|
80
|
+
/** Handle border width in screen px. */
|
|
81
|
+
handleBorderWidth: number;
|
|
82
|
+
/** Group bbox dash length in screen px (0 = solid). */
|
|
83
|
+
groupDash: number;
|
|
84
|
+
}
|
|
85
|
+
declare const DEFAULT_SELECTION_CONFIG: SelectionConfig;
|
|
86
|
+
interface SelectionBounds {
|
|
87
|
+
x: number;
|
|
88
|
+
y: number;
|
|
89
|
+
width: number;
|
|
90
|
+
height: number;
|
|
91
|
+
}
|
|
92
|
+
declare class SelectionRenderer {
|
|
93
|
+
private material;
|
|
94
|
+
private mesh;
|
|
95
|
+
private scene;
|
|
96
|
+
private camera;
|
|
97
|
+
constructor();
|
|
98
|
+
setConfig(config: Partial<SelectionConfig>): void;
|
|
99
|
+
setSize(resolution: THREE.Vector2, dpr: number): void;
|
|
100
|
+
render(renderer: THREE.WebGLRenderer, cameraX: number, cameraY: number, zoom: number, selected: SelectionBounds[], hovered: SelectionBounds | null, guides?: SnapGuide[], spacings?: EqualSpacingIndicator[]): void;
|
|
101
|
+
dispose(): void;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { DEFAULT_GRID_CONFIG as a, ContainerRefProvider as c, WidgetResolverProvider as d, useContainerRef as f, SelectionRenderer as i, EngineProvider as l, useWidgetResolver as m, SelectionBounds as n, GridConfig as o, useLayoutEngine as p, SelectionConfig as r, GridRenderer as s, DEFAULT_SELECTION_CONFIG as t, ResolvedWidget as u };
|
|
105
|
+
//# sourceMappingURL=SelectionRenderer-DlsBstAq.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectionRenderer-DlsBstAq.d.mts","names":[],"sources":["../src/react/context.ts","../src/react/webgl/GridRenderer.ts","../src/react/webgl/SelectionRenderer.ts"],"mappings":";;;;;;cASa,cAAA,EAAc,OAAA,CAAA,QAAA,CAAA,YAAA;AAAA,cAOd,oBAAA,EAAoB,OAAA,CAAA,QAAA,CAAA,OAAA,CAAA,SAAA,CAAA,cAAA;AAAA,iBAEjB,eAAA,CAAA,GAAmB,KAAA,CAAM,SAAA,CAAU,cAAA;AATnD;;;;AAAA,iBAiBgB,eAAA,CAAA,GAAmB,YAAA;;;;;KAgBvB,cAAA;EACP,OAAA;EAAgB,SAAA,EAAW,KAAA,CAAM,aAAA,CAAc,cAAA;AAAA;EAC/C,OAAA;EAAkB,SAAA,EAAW,KAAA,CAAM,aAAA,CAAc,cAAA;AAAA;AAAA,KAE1C,cAAA,IAAkB,QAAA,EAAU,QAAA,EAAU,UAAA,aAAuB,cAAA;AAAA,cAI5D,sBAAA,EAAsB,OAAA,CAAA,QAAA,CAAA,cAAA;AAAA,iBAEnB,iBAAA,CAAA,GAAqB,cAAA;;;UChDpB,UAAA;;EAEhB,QAAA;;EAEA,QAAA;EDCY;ECCZ,QAAA;;EAEA,MAAA;EDH0B;ECK1B,OAAA;EDE+D;ECA/D,SAAA;EDAgC;ECEhC,WAAA;AAAA;AAAA,cAGY,mBAAA,EAAqB,UAAA;AAAA,cAoFrB,YAAA;EAAA,QACJ,QAAA;EAAA,QACA,KAAA;EAAA,QACA,MAAA;EAAA,QACA,QAAA;EAAA,QACA,IAAA;cAEI,MAAA,EAAQ,iBAAA;ED9FU;EC8I9B,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,UAAA;EAW1B,OAAA,CAAQ,KAAA,UAAe,MAAA,UAAgB,GAAA;EAQvC,MAAA,CAAO,OAAA,UAAiB,OAAA,UAAiB,IAAA;EAOzC,OAAA,CAAA;EDxKkD;EC+KlD,gBAAA,CAAA,GAAoB,KAAA,CAAM,aAAA;AAAA;;;UC3LV,eAAA;;EAEhB,YAAA;;EAEA,YAAA;EFDmD;EEGnD,UAAA;EFH0B;EEK1B,UAAA;EFEY;EEAZ,UAAA;;EAEA,UAAA;EFFgC;EEIhC,YAAA;EFJgC;EEMhC,iBAAA;EFNgC;EEQhC,SAAA;AAAA;AAAA,cAGY,wBAAA,EAA0B,eAAA;AAAA,UActB,eAAA;EAChB,CAAA;EACA,CAAA;EACA,KAAA;EACA,MAAA;AAAA;AAAA,cAoOY,iBAAA;EAAA,QACJ,QAAA;EAAA,QACA,IAAA;EAAA,QACA,KAAA;EAAA,QACA,MAAA;;EAsDR,SAAA,CAAU,MAAA,EAAQ,OAAA,CAAQ,eAAA;EAc1B,OAAA,CAAQ,UAAA,EAAY,KAAA,CAAM,OAAA,EAAS,GAAA;EAKnC,MAAA,CACC,QAAA,EAAU,KAAA,CAAM,aAAA,EAChB,OAAA,UACA,OAAA,UACA,IAAA,UACA,QAAA,EAAU,eAAA,IACV,OAAA,EAAS,eAAA,SACT,MAAA,GAAQ,SAAA,IACR,QAAA,GAAU,qBAAA;EAiFX,OAAA,CAAA;AAAA"}
|