carboncanvas 0.1.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/CommentsRuntime-CRhC_WJU.js +6781 -0
- package/CommentsRuntime-CRhC_WJU.js.map +1 -0
- package/Inspector-D9W1Ie5_.js +7541 -0
- package/Inspector-D9W1Ie5_.js.map +1 -0
- package/LICENSE +21 -0
- package/README.md +160 -0
- package/brand-B9y8WrVi.js +134 -0
- package/brand-B9y8WrVi.js.map +1 -0
- package/index.d.ts +271 -0
- package/index.js +14 -0
- package/index.js.map +1 -0
- package/lib-CSrTsI4Y.js +2231 -0
- package/lib-CSrTsI4Y.js.map +1 -0
- package/package.json +65 -0
- package/tools/babel-plugin-data-anchor.d.ts +6 -0
- package/tools/babel-plugin-data-anchor.js +64 -0
- package/vite.d.ts +33 -0
- package/vite.js +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Roitch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# carboncanvas
|
|
2
|
+
|
|
3
|
+
> **Carbon Canvas** — the free, open (**MIT**) client for the Carbon Canvas
|
|
4
|
+
> review platform. `0.1.0`. The canvas + Inspector need no account and no
|
|
5
|
+
> backend; team comments/realtime are an optional hosted add-on.
|
|
6
|
+
|
|
7
|
+
A **Reviewable Flow Canvas** for React: a pan/zoom spatial canvas you author in
|
|
8
|
+
JSX (`<DesignCanvas>` / `<DCSection>` / `<DCArtboard>` / `<DCPage>`), with a
|
|
9
|
+
click-to-inspect **Inspector** that reads real React fibers, and a
|
|
10
|
+
design-system **adapter seam** so token reverse-lookup + library detection work
|
|
11
|
+
with any (or no) design system.
|
|
12
|
+
|
|
13
|
+
The canvas + Inspector are fully client-side — no account, no backend. Add
|
|
14
|
+
in-place **comments** (with live cursors/presence) by pointing the `comments`
|
|
15
|
+
prop at a hosted Carbon Canvas backend (see [Comments](#comments) below); the
|
|
16
|
+
comments/realtime runtime — including `socket.io-client` — is code-split into a
|
|
17
|
+
lazy chunk, so it costs nothing until you enable it and pulls in no extra dep.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm i carboncanvas
|
|
23
|
+
# react + react-dom are PEER deps — they use your app's existing copy
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Use
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
import { DesignCanvas, DCSection, DCArtboard } from 'carboncanvas';
|
|
30
|
+
|
|
31
|
+
export function Review() {
|
|
32
|
+
return (
|
|
33
|
+
<DesignCanvas inspector>
|
|
34
|
+
<DCSection title="Checkout flow">
|
|
35
|
+
<DCArtboard label="Cart" width={390} height={844}>
|
|
36
|
+
<YourCartScreen />
|
|
37
|
+
</DCArtboard>
|
|
38
|
+
<DCArtboard label="Payment" width={390} height={844}>
|
|
39
|
+
<YourPaymentScreen state="connecting" />
|
|
40
|
+
</DCArtboard>
|
|
41
|
+
</DCSection>
|
|
42
|
+
</DesignCanvas>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **One `<DesignCanvas>` per page.** The canvas chrome locates the active
|
|
48
|
+
> viewport through a global `[data-dc-viewport]` lookup, so two sibling
|
|
49
|
+
> DesignCanvas instances on one page cross-wire. Render at most one per route.
|
|
50
|
+
> (Nested canvases inside an artboard are fine — they're scoped by nearest
|
|
51
|
+
> viewport.)
|
|
52
|
+
|
|
53
|
+
## Consumer build requirements
|
|
54
|
+
|
|
55
|
+
Two build settings make the Inspector and durable comment pins work well. Both
|
|
56
|
+
live in **your** app's build, not in this package:
|
|
57
|
+
|
|
58
|
+
1. **`esbuild: { keepNames: true }`** — **required for readable inspection.** The
|
|
59
|
+
Inspector reads React component display names off the fiber tree; without
|
|
60
|
+
`keepNames`, minification renames them and the Hierarchy tree shows garbage.
|
|
61
|
+
|
|
62
|
+
Vite example:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// vite.config.ts
|
|
66
|
+
export default defineConfig({
|
|
67
|
+
esbuild: { keepNames: true },
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
2. **The `data-anchor` Babel plugin (optional, recommended for comments)** —
|
|
72
|
+
stamps every host element with a deterministic `data-anchor="file:line:col"`
|
|
73
|
+
so comment pins survive edits/HMR. Shipped as a subpath export:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// vite.config.ts
|
|
77
|
+
import react from '@vitejs/plugin-react';
|
|
78
|
+
import dataAnchor from 'carboncanvas/babel-plugin-data-anchor';
|
|
79
|
+
|
|
80
|
+
export default defineConfig({
|
|
81
|
+
plugins: [react({ babel: { plugins: [dataAnchor] } })],
|
|
82
|
+
esbuild: { keepNames: true },
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
On **React 19** this plugin is what makes the Inspector's Source row work at
|
|
87
|
+
all — React 19 removed `fiber._debugSource`, so the source path comes entirely
|
|
88
|
+
from `data-anchor`. Wire it if you want the Source row on React 19.
|
|
89
|
+
|
|
90
|
+
### Shortcut: `carbonPreset` (`carboncanvas/vite`)
|
|
91
|
+
|
|
92
|
+
So you don't hand-copy `keepNames`, the package ships a Vite config fragment.
|
|
93
|
+
Spread it into your config, and (optionally) pass the re-exported plugin to your
|
|
94
|
+
`react()`:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// vite.config.ts
|
|
98
|
+
import { defineConfig } from 'vite';
|
|
99
|
+
import react from '@vitejs/plugin-react';
|
|
100
|
+
import { carbonPreset, dataAnchorBabelPlugin } from 'carboncanvas/vite';
|
|
101
|
+
|
|
102
|
+
export default defineConfig({
|
|
103
|
+
...carbonPreset(), // sets esbuild.keepNames
|
|
104
|
+
plugins: [react({ babel: { plugins: [dataAnchorBabelPlugin] } })],
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The fragment only sets `keepNames` (a config fragment can't reach into your
|
|
109
|
+
`react()` plugin's babel option), so the `data-anchor` plugin is a separate
|
|
110
|
+
re-export you wire yourself. `carboncanvas publish` verifies the built bundle
|
|
111
|
+
actually kept names and warns if it didn't.
|
|
112
|
+
|
|
113
|
+
## Design-system adapter
|
|
114
|
+
|
|
115
|
+
The Inspector resolves design tokens + detects library components through one
|
|
116
|
+
swappable adapter. The default (`genericAdapter`) needs no design system and
|
|
117
|
+
reports raw computed values. Install a custom adapter once at app start:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { setDesignSystemAdapter } from 'carboncanvas';
|
|
121
|
+
import { myAdapter } from './myAdapter'; // implements DesignSystemAdapter
|
|
122
|
+
|
|
123
|
+
setDesignSystemAdapter(myAdapter);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Comments
|
|
127
|
+
|
|
128
|
+
In-place, pin-anchored comments (with live cursors + presence) are an optional
|
|
129
|
+
hosted add-on. Point the `comments` prop at your Carbon Canvas backend:
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<DesignCanvas
|
|
133
|
+
inspector
|
|
134
|
+
comments={{
|
|
135
|
+
canvasId: 'cnv_…', // the permanent comment partition (write-once)
|
|
136
|
+
serviceUrl: 'https://your-backend', // the hosted comments/realtime backend
|
|
137
|
+
enableUrl: 'https://your-dashboard', // where the "Enable / Renew" CTA points
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
No client-side key: entitlement resolves **server-side** from the registered
|
|
143
|
+
canvas's owner account. For local development with no backend, use the in-memory
|
|
144
|
+
mock instead: `comments={{ canvasId: 'demo', devMode: true }}`. The comments tab
|
|
145
|
+
is always present — until the canvas is entitled it renders an upsell rather than
|
|
146
|
+
a thread list. `socket.io-client` ships inside the lazy comments chunk, so it is
|
|
147
|
+
**not** an additional install.
|
|
148
|
+
|
|
149
|
+
## Exports
|
|
150
|
+
|
|
151
|
+
- **Canvas:** `DesignCanvas`, `DCSection`, `DCArtboard`, `DCPage`, `DCPostIt`,
|
|
152
|
+
`useArtboardActive`
|
|
153
|
+
- **Adapter seam:** `setDesignSystemAdapter`, `getDesignSystemAdapter`,
|
|
154
|
+
`genericAdapter`, and the `DesignSystemAdapter` type (+ `AdapterFiber`,
|
|
155
|
+
`ComponentKind`, `CssVarTokenSpec`, `TypographyTokenSpec`,
|
|
156
|
+
`UtilityClassPrefixes`, `AdapterTokens`)
|
|
157
|
+
|
|
158
|
+
## Peer dependencies
|
|
159
|
+
|
|
160
|
+
`react >=18` and `react-dom >=18` (externalized — your app's copy is reused).
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
function getAncestorScale(el) {
|
|
4
|
+
let scale = 1;
|
|
5
|
+
let cur = parentAcrossShadow(el);
|
|
6
|
+
while (cur) {
|
|
7
|
+
const t = window.getComputedStyle(cur).transform;
|
|
8
|
+
if (t && t !== "none") {
|
|
9
|
+
const m = new DOMMatrix(t);
|
|
10
|
+
if (m.a !== 0) scale *= m.a;
|
|
11
|
+
}
|
|
12
|
+
cur = parentAcrossShadow(cur);
|
|
13
|
+
}
|
|
14
|
+
return scale || 1;
|
|
15
|
+
}
|
|
16
|
+
__name(getAncestorScale, "getAncestorScale");
|
|
17
|
+
function parentAcrossShadow(el) {
|
|
18
|
+
if (el.parentElement) return el.parentElement;
|
|
19
|
+
const root = el.getRootNode();
|
|
20
|
+
return root instanceof ShadowRoot ? root.host : null;
|
|
21
|
+
}
|
|
22
|
+
__name(parentAcrossShadow, "parentAcrossShadow");
|
|
23
|
+
const FRAME_ATTR = "data-quilt-canvas-frame";
|
|
24
|
+
const FRAME_OVERLAY_ATTR = "data-quilt-frame-overlay";
|
|
25
|
+
function contentDocOf(frame) {
|
|
26
|
+
try {
|
|
27
|
+
const doc = frame.contentDocument;
|
|
28
|
+
return doc && doc.body ? doc : null;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
__name(contentDocOf, "contentDocOf");
|
|
34
|
+
function frameForTarget(target) {
|
|
35
|
+
var _a;
|
|
36
|
+
if (target instanceof HTMLIFrameElement && target.hasAttribute(FRAME_ATTR)) return target;
|
|
37
|
+
if (!target.hasAttribute(FRAME_OVERLAY_ATTR)) return null;
|
|
38
|
+
const wrap = target.parentElement;
|
|
39
|
+
return (_a = wrap == null ? void 0 : wrap.querySelector(`iframe[${FRAME_ATTR}]`)) != null ? _a : null;
|
|
40
|
+
}
|
|
41
|
+
__name(frameForTarget, "frameForTarget");
|
|
42
|
+
function isFrameEl(el) {
|
|
43
|
+
return enclosingFrameOf(el) !== null;
|
|
44
|
+
}
|
|
45
|
+
__name(isFrameEl, "isFrameEl");
|
|
46
|
+
function enclosingFrameOf(el) {
|
|
47
|
+
try {
|
|
48
|
+
const win = el.ownerDocument.defaultView;
|
|
49
|
+
if (!win || win === window) return null;
|
|
50
|
+
const frame = win.frameElement;
|
|
51
|
+
return frame instanceof HTMLIFrameElement && frame.hasAttribute(FRAME_ATTR) ? frame : null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
__name(enclosingFrameOf, "enclosingFrameOf");
|
|
57
|
+
function frameBodyOf(el) {
|
|
58
|
+
return enclosingFrameOf(el) ? el.ownerDocument.body : null;
|
|
59
|
+
}
|
|
60
|
+
__name(frameBodyOf, "frameBodyOf");
|
|
61
|
+
function frameScale(frame) {
|
|
62
|
+
const w = frame.clientWidth;
|
|
63
|
+
if (!w) return 1;
|
|
64
|
+
return frame.getBoundingClientRect().width / w || 1;
|
|
65
|
+
}
|
|
66
|
+
__name(frameScale, "frameScale");
|
|
67
|
+
function descendIntoFrame(target, clientX, clientY) {
|
|
68
|
+
const frame = frameForTarget(target);
|
|
69
|
+
if (!frame) return null;
|
|
70
|
+
const doc = contentDocOf(frame);
|
|
71
|
+
if (!doc) return null;
|
|
72
|
+
const r = frame.getBoundingClientRect();
|
|
73
|
+
const s = frameScale(frame);
|
|
74
|
+
const inner = doc.elementFromPoint((clientX - r.left) / s, (clientY - r.top) / s);
|
|
75
|
+
return { el: inner != null ? inner : doc.body, frameBody: doc.body, frame };
|
|
76
|
+
}
|
|
77
|
+
__name(descendIntoFrame, "descendIntoFrame");
|
|
78
|
+
function rectInHost(el) {
|
|
79
|
+
let rect = el.getBoundingClientRect();
|
|
80
|
+
let win = null;
|
|
81
|
+
try {
|
|
82
|
+
win = el.ownerDocument.defaultView;
|
|
83
|
+
} catch {
|
|
84
|
+
return rect;
|
|
85
|
+
}
|
|
86
|
+
let guard = 0;
|
|
87
|
+
while (win && win !== window && guard++ < 8) {
|
|
88
|
+
const frame = win.frameElement;
|
|
89
|
+
if (!(frame instanceof HTMLIFrameElement)) break;
|
|
90
|
+
const fr = frame.getBoundingClientRect();
|
|
91
|
+
const s = frameScale(frame);
|
|
92
|
+
rect = new DOMRect(
|
|
93
|
+
fr.left + rect.left * s,
|
|
94
|
+
fr.top + rect.top * s,
|
|
95
|
+
rect.width * s,
|
|
96
|
+
rect.height * s
|
|
97
|
+
);
|
|
98
|
+
win = frame.ownerDocument.defaultView;
|
|
99
|
+
}
|
|
100
|
+
return rect;
|
|
101
|
+
}
|
|
102
|
+
__name(rectInHost, "rectInHost");
|
|
103
|
+
function closestAcrossFrames(el, selector) {
|
|
104
|
+
let cur = el;
|
|
105
|
+
let guard = 0;
|
|
106
|
+
while (cur && guard++ < 16) {
|
|
107
|
+
const hit = cur.closest(selector);
|
|
108
|
+
if (hit) return hit;
|
|
109
|
+
cur = enclosingFrameOf(cur);
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
__name(closestAcrossFrames, "closestAcrossFrames");
|
|
114
|
+
const BRAND_NAME = "Carbon Canvas";
|
|
115
|
+
const BRAND = {
|
|
116
|
+
name: BRAND_NAME,
|
|
117
|
+
// Maturity tag shown next to the name (kept from the origin "alpha" pill).
|
|
118
|
+
tag: "alpha",
|
|
119
|
+
tagTitle: "Alpha — APIs and tree behaviour may change without notice",
|
|
120
|
+
credit: "created by Alex Roitch"
|
|
121
|
+
};
|
|
122
|
+
export {
|
|
123
|
+
BRAND as B,
|
|
124
|
+
FRAME_ATTR as F,
|
|
125
|
+
contentDocOf as a,
|
|
126
|
+
BRAND_NAME as b,
|
|
127
|
+
closestAcrossFrames as c,
|
|
128
|
+
descendIntoFrame as d,
|
|
129
|
+
frameBodyOf as f,
|
|
130
|
+
getAncestorScale as g,
|
|
131
|
+
isFrameEl as i,
|
|
132
|
+
rectInHost as r
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=brand-B9y8WrVi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand-B9y8WrVi.js","sources":["../src/DesignCanvas/getAncestorScale.ts","../src/DesignCanvas/frameInspect.ts","../src/brand.ts"],"sourcesContent":["// Walks up the parent chain from `el` and multiplies any CSS `transform`\n// scale factors. Used by Inspector / XRay / ExplodedView to compensate for\n// the DesignCanvas viewport's `transform: scale(N)` — without this, an\n// element's getBoundingClientRect comes back at *visual* size (post-canvas-\n// zoom) while its computed paddings / font-sizes stay at natural CSS px,\n// and clones look like they were \"drag-resized\" rather than scaled.\n//\n// Assumes uniform scaling (a === d in the matrix), which is true for the\n// canvas. Returns 1 if no transforming ancestor exists.\n//\n// Crosses shadow boundaries (parentElement → host hop): frozen snapshot tiles\n// (src/viewer/FrozenTile) render inside a shadow root, but the canvas zoom\n// transform lives on a light-DOM ancestor of the host — without the hop, every\n// measurement inside a snapshot would ignore the canvas zoom. Light-DOM\n// callers are unaffected (a Document root node ends the walk exactly like the\n// old `parentElement === null` did).\nexport function getAncestorScale(el: Element): number {\n let scale = 1;\n let cur: Element | null = parentAcrossShadow(el);\n while (cur) {\n const t = window.getComputedStyle(cur).transform;\n if (t && t !== 'none') {\n const m = new DOMMatrix(t);\n if (m.a !== 0) scale *= m.a;\n }\n cur = parentAcrossShadow(cur);\n }\n return scale || 1;\n}\n\nfunction parentAcrossShadow(el: Element): Element | null {\n if (el.parentElement) return el.parentElement;\n const root = el.getRootNode();\n return root instanceof ShadowRoot ? root.host : null;\n}\n","// frameInspect — same-origin iframe plumbing for the IN-APP canvas mode\n// (the 2026-06-12 pivot: the user's live routes ARE the artboards, rendered\n// as same-origin iframes of their own running app).\n//\n// This is the iframe sibling of domInspect.ts's shadow-root plumbing, and the\n// two solve the same problem with the same shape: document-level listeners in\n// the HOST page never see events from inside an iframe, so comment/dev modes\n// cover each live frame with a transparent overlay (stamped\n// `data-quilt-frame-overlay`); a click/hover lands on the overlay in HOST\n// coordinates and we \"descend\" — point-map into the frame's content document\n// and resolve the real element under the cursor. Because the frames are the\n// customer's OWN app on their OWN origin, contentDocument is reachable and the\n// elements carry real React fibers — that's what makes the in-app Inspector\n// \"native fiber\" instead of DOM-mode.\n//\n// Coordinate model: inside a frame, rects are natural CSS px (the canvas zoom\n// transform scales the iframe ELEMENT in the host, never the layout inside).\n// `rectInHost` maps an inner rect out to host-viewport px through the frame\n// chain; `descendIntoFrame` maps a host point in. Everything that DRAWS in the\n// host (hover/selection outlines, pins) maps out; everything that MEASURES\n// (computed styles, box model) reads natural px straight off the inner element\n// — which is exactly what the Inspector wants to display.\n//\n// Library-core rules: framework-free, no design-system imports.\n\n/** Stamped on every live route iframe the in-app canvas renders. */\nexport const FRAME_ATTR = 'data-quilt-canvas-frame';\n\n/** Stamped on the transparent event-catching overlay above a live frame\n * (present in comment/dev modes; absent while the tile is being interacted\n * with in cursor mode). */\nexport const FRAME_OVERLAY_ATTR = 'data-quilt-frame-overlay';\n\n/** The frame's content document, or null when unreachable (cross-origin,\n * detached, still loading about:blank with no body yet). */\nexport function contentDocOf(frame: HTMLIFrameElement): Document | null {\n try {\n const doc = frame.contentDocument;\n return doc && doc.body ? doc : null;\n } catch {\n return null; // cross-origin — not a quilt canvas frame's normal state\n }\n}\n\n/** The quilt canvas frame an overlay (or the frame itself) fronts, or null. */\nexport function frameForTarget(target: Element): HTMLIFrameElement | null {\n if (target instanceof HTMLIFrameElement && target.hasAttribute(FRAME_ATTR)) return target;\n if (!target.hasAttribute(FRAME_OVERLAY_ATTR)) return null;\n // The overlay is absolutely positioned over the frame inside the same tile\n // wrapper — find the frame among the wrapper's descendants.\n const wrap = target.parentElement;\n return wrap?.querySelector<HTMLIFrameElement>(`iframe[${FRAME_ATTR}]`) ?? null;\n}\n\n/** Is this element inside a quilt canvas frame's document (any nesting level)? */\nexport function isFrameEl(el: Element): boolean {\n return enclosingFrameOf(el) !== null;\n}\n\n/** The quilt canvas frame ELEMENT (in the parent document) whose document\n * contains `el`, or null for host-document elements. */\nexport function enclosingFrameOf(el: Element): HTMLIFrameElement | null {\n try {\n const win = el.ownerDocument.defaultView;\n if (!win || win === window) return null;\n const frame = win.frameElement;\n return frame instanceof HTMLIFrameElement && frame.hasAttribute(FRAME_ATTR) ? frame : null;\n } catch {\n return null;\n }\n}\n\n/** The frame document's body for an element inside a quilt canvas frame —\n * the selector scope pins are built against (the iframe twin of\n * domInspect's snapshotBodyOf). Null for host elements. */\nexport function frameBodyOf(el: Element): Element | null {\n return enclosingFrameOf(el) ? el.ownerDocument.body : null;\n}\n\n/** Rendered scale of the frame's content on the host screen — the canvas zoom\n * as it applies to this frame element. 1 when unscaled/unmeasurable. */\nexport function frameScale(frame: HTMLIFrameElement): number {\n const w = frame.clientWidth;\n if (!w) return 1;\n return frame.getBoundingClientRect().width / w || 1;\n}\n\n/**\n * Descend through a frame overlay (or the frame element itself) into the live\n * document inside: map the HOST-viewport point to frame-content coordinates\n * and resolve the element under it. Returns the inner element plus the frame\n * body (the pin selector scope) and the frame, or null when `target` doesn't\n * front a readable quilt canvas frame — light-DOM paths stay untouched, same\n * contract as the snapshot descent.\n */\nexport function descendIntoFrame(\n target: Element,\n clientX: number,\n clientY: number,\n): { el: Element; frameBody: Element; frame: HTMLIFrameElement } | null {\n const frame = frameForTarget(target);\n if (!frame) return null;\n const doc = contentDocOf(frame);\n if (!doc) return null;\n const r = frame.getBoundingClientRect();\n const s = frameScale(frame);\n const inner = doc.elementFromPoint((clientX - r.left) / s, (clientY - r.top) / s);\n return { el: inner ?? doc.body, frameBody: doc.body, frame };\n}\n\n/**\n * An element's bounding rect in HOST-viewport coordinates. Identity for host\n * elements; for elements inside (possibly nested) quilt canvas frames, maps\n * each frame's content coords out through the frame element's host rect and\n * rendered scale. Inner-document scroll is already baked into the inner\n * getBoundingClientRect, so no scroll math is needed here.\n */\nexport function rectInHost(el: Element): DOMRect {\n let rect = el.getBoundingClientRect();\n let win: Window | null = null;\n try {\n win = el.ownerDocument.defaultView;\n } catch {\n return rect;\n }\n let guard = 0;\n while (win && win !== window && guard++ < 8) {\n const frame = win.frameElement;\n if (!(frame instanceof HTMLIFrameElement)) break;\n const fr = frame.getBoundingClientRect();\n const s = frameScale(frame);\n rect = new DOMRect(\n fr.left + rect.left * s,\n fr.top + rect.top * s,\n rect.width * s,\n rect.height * s,\n );\n win = frame.ownerDocument.defaultView;\n }\n return rect;\n}\n\n/** `closest()` that keeps walking up through quilt canvas frame boundaries\n * (frame-element hops) — the iframe twin of domInspect's closestAcrossShadow.\n * Lets frame-content elements find their `[data-dc-slot]` artboard. */\nexport function closestAcrossFrames(el: Element, selector: string): Element | null {\n let cur: Element | null = el;\n let guard = 0;\n while (cur && guard++ < 16) {\n const hit = cur.closest(selector);\n if (hit) return hit;\n cur = enclosingFrameOf(cur);\n }\n return null;\n}\n\n/** Resolve `selector` inside every readable quilt canvas frame under `scope`\n * (light-DOM querySelector can't cross the document boundary). First match\n * wins — mirrors domInspect's querySnapshots. */\nexport function queryFrames(scope: ParentNode, selector: string): Element | null {\n for (const frame of Array.from(\n scope.querySelectorAll<HTMLIFrameElement>(`iframe[${FRAME_ATTR}]`),\n )) {\n const doc = contentDocOf(frame);\n const el = doc?.body.querySelector(selector);\n if (el) return el;\n }\n return null;\n}\n","// Single source of truth for the product name. The repo's working codename is\n// \"quilt\"; the public brand is \"Carbon Canvas\" (carboncanvas.design). The rename\n// is a one-line change here, not a find-and-replace across the inspector chrome —\n// the internal codename \"quilt\" stays in dir names and other identifiers.\nexport const BRAND_NAME = 'Carbon Canvas';\n\n// Header chrome shown in the Inspector panel. Tagline/credit live alongside the\n// name so the whole brand surface is editable in one place.\nexport const BRAND = {\n name: BRAND_NAME,\n // Maturity tag shown next to the name (kept from the origin \"alpha\" pill).\n tag: 'alpha',\n tagTitle: 'Alpha — APIs and tree behaviour may change without notice',\n credit: 'created by Alex Roitch',\n} as const;\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { ReactElement } from 'react';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
export declare type AdapterFiber = {
|
|
6
|
+
return: AdapterFiber | null;
|
|
7
|
+
child: AdapterFiber | null;
|
|
8
|
+
sibling: AdapterFiber | null;
|
|
9
|
+
type: any;
|
|
10
|
+
memoizedProps: Record<string, any> | null;
|
|
11
|
+
stateNode: any;
|
|
12
|
+
[k: string]: any;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export declare type AdapterTokens = {
|
|
16
|
+
color: CssVarTokenSpec;
|
|
17
|
+
shadow: CssVarTokenSpec;
|
|
18
|
+
spacing: CssVarTokenSpec;
|
|
19
|
+
radius: CssVarTokenSpec;
|
|
20
|
+
typography: TypographyTokenSpec;
|
|
21
|
+
utilityClassPrefixes: UtilityClassPrefixes;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Pluggable authentication strategy for the network client. The default
|
|
26
|
+
* (`accountlessAuthProvider`) is account-less: a sign-in is just a name (and an
|
|
27
|
+
* optional email) — no password, no external identity provider, no verification.
|
|
28
|
+
* Swap in your own provider to integrate OAuth / SSO / a real account system.
|
|
29
|
+
*/
|
|
30
|
+
export declare interface AuthProvider {
|
|
31
|
+
/** Resolve the current user for a stored bearer token (null = signed out). */
|
|
32
|
+
me(token: string | null): Promise<Me | null>;
|
|
33
|
+
/** Establish a session from the given identity; returns the bearer token + user. */
|
|
34
|
+
signIn(input: {
|
|
35
|
+
name: string;
|
|
36
|
+
email?: string;
|
|
37
|
+
}): Promise<{
|
|
38
|
+
token: string;
|
|
39
|
+
me: Me;
|
|
40
|
+
}>;
|
|
41
|
+
/** Best-effort server-side session teardown for the given token. */
|
|
42
|
+
signOut?(token: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The canvas interaction mode. One bar, mutually-exclusive modes:
|
|
47
|
+
* • cursor — normal pointer; play with the live prototypes, pan/zoom freely
|
|
48
|
+
* • comment — drop pins + open the comments sidebar
|
|
49
|
+
* • dev — click-to-inspect + the inspector panel
|
|
50
|
+
*
|
|
51
|
+
* Owned by DesignCanvas and threaded into the Inspector / CommentLayer so each
|
|
52
|
+
* derives its `enabled` state from the shared mode rather than its own toggle.
|
|
53
|
+
*/
|
|
54
|
+
export declare type CanvasMode = 'cursor' | 'comment' | 'dev';
|
|
55
|
+
|
|
56
|
+
/** Public `comments` prop on DesignCanvas. */
|
|
57
|
+
export declare interface CommentsConfig {
|
|
58
|
+
canvasId: string;
|
|
59
|
+
/** The hosted comments service base URL (required for network mode). */
|
|
60
|
+
serviceUrl?: string;
|
|
61
|
+
/** Use the in-memory mock store instead of the network. */
|
|
62
|
+
devMode?: boolean;
|
|
63
|
+
/** Authentication strategy. Defaults to `accountlessAuthProvider` (name-only sign-in). */
|
|
64
|
+
auth?: AuthProvider;
|
|
65
|
+
/**
|
|
66
|
+
* Multiplayer presence: live cursors + the who's-here facepile (network mode
|
|
67
|
+
* only; needs the realtime socket). Default true — set false to run
|
|
68
|
+
* comments-only with no socket connection.
|
|
69
|
+
*/
|
|
70
|
+
presence?: boolean;
|
|
71
|
+
/** Directory backend for @mention typeahead. Defaults to the service's `/api/directory`. */
|
|
72
|
+
directory?: DirectoryProvider;
|
|
73
|
+
/**
|
|
74
|
+
* Hostnames matching any of these patterns are treated as NON-stable (e.g.
|
|
75
|
+
* rotating preview/dev hosts) and fall back to the explicit per-project
|
|
76
|
+
* canvasId instead of auto-scoping by hostname. Default `[]` → every host is
|
|
77
|
+
* its own canvas.
|
|
78
|
+
*/
|
|
79
|
+
unstableHostPatterns?: RegExp[];
|
|
80
|
+
/**
|
|
81
|
+
* Auto-provision hint sent on the first write to an unregistered canvas, so the
|
|
82
|
+
* service can resolve the canvas owner deterministically rather than from
|
|
83
|
+
* whoever comments first. Ignored once the canvas exists.
|
|
84
|
+
*/
|
|
85
|
+
provisionHint?: string;
|
|
86
|
+
/**
|
|
87
|
+
* Where the comments upsell's "Enable / Renew" CTA points — your dashboard or
|
|
88
|
+
* checkout URL (Workstream B). Shown when the canvas owner isn't entitled
|
|
89
|
+
* (the always-visible comments tab renders the upsell instead of the live
|
|
90
|
+
* runtime). Optional; a missing/placeholder value renders a non-navigating CTA.
|
|
91
|
+
*/
|
|
92
|
+
enableUrl?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export declare type ComponentKind = 'library' | 'user';
|
|
96
|
+
|
|
97
|
+
export declare type CssVarTokenSpec = {
|
|
98
|
+
cssVarPrefix: string;
|
|
99
|
+
display?: (suffix: string) => string;
|
|
100
|
+
preferOnCollision?: (existing: string, candidate: string, suffix: string) => boolean;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export declare function DCArtboard(_props: DCArtboardProps): ReactElement | null;
|
|
104
|
+
|
|
105
|
+
export declare interface DCArtboardProps {
|
|
106
|
+
id?: string;
|
|
107
|
+
label: string;
|
|
108
|
+
width?: number;
|
|
109
|
+
height?: number;
|
|
110
|
+
style?: CSSProperties;
|
|
111
|
+
/**
|
|
112
|
+
* Make the artboard card a containing block for `position:fixed` descendants
|
|
113
|
+
* (adds `contain:layout`), so a host app's fixed portals — modals, drawer
|
|
114
|
+
* sheets, menus — clip to the tile instead of escaping to the transformed
|
|
115
|
+
* canvas. Used by composed live artboards (wave 10). Off by default.
|
|
116
|
+
*/
|
|
117
|
+
contain?: boolean;
|
|
118
|
+
children?: ReactNode;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export declare function DCPage(_props: DCPageProps): ReactElement | null;
|
|
122
|
+
|
|
123
|
+
export declare interface DCPageProps {
|
|
124
|
+
/** Stable page id; also the `?page=` deep-link value. Defaults to `title`. */
|
|
125
|
+
id?: string;
|
|
126
|
+
title: string;
|
|
127
|
+
children?: ReactNode;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export declare function DCPostIt({ children, top, left, right, bottom, rotate, width }: DCPostItProps): ReactElement;
|
|
131
|
+
|
|
132
|
+
export declare interface DCPostItProps {
|
|
133
|
+
children?: ReactNode;
|
|
134
|
+
top?: number | string;
|
|
135
|
+
left?: number | string;
|
|
136
|
+
right?: number | string;
|
|
137
|
+
bottom?: number | string;
|
|
138
|
+
rotate?: number;
|
|
139
|
+
width?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export declare function DCSection({ id, title, subtitle, children, gap }: DCSectionProps): ReactElement;
|
|
143
|
+
|
|
144
|
+
export declare interface DCSectionProps {
|
|
145
|
+
id?: string;
|
|
146
|
+
title: string;
|
|
147
|
+
subtitle?: string;
|
|
148
|
+
children?: ReactNode;
|
|
149
|
+
gap?: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export declare function DesignCanvas({ children, minScale, maxScale, minActiveScale, style, inspector, comments, adapter, }: DesignCanvasProps): ReactElement;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Props for {@link DesignCanvas}.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* **One `<DesignCanvas>` per page.** The canvas chrome (Inspector, ModeBar zoom,
|
|
159
|
+
* comment pin/cursor panning) locates the active viewport via a global
|
|
160
|
+
* `document.querySelector('[data-dc-viewport]')`, so two DesignCanvas instances
|
|
161
|
+
* mounted on the same page cross-wire. Render at most one per route; nested
|
|
162
|
+
* canvases-inside-an-artboard are supported (scoped by nearest-viewport), but two
|
|
163
|
+
* sibling canvases are not.
|
|
164
|
+
*/
|
|
165
|
+
export declare interface DesignCanvasProps {
|
|
166
|
+
children?: ReactNode;
|
|
167
|
+
minScale?: number;
|
|
168
|
+
maxScale?: number;
|
|
169
|
+
/**
|
|
170
|
+
* Artboards report `active = false` via `useArtboardActive()` when the
|
|
171
|
+
* viewport scale drops below this threshold (or when the artboard scrolls
|
|
172
|
+
* out of view). Heavy content (videos, canvases) should gate on it.
|
|
173
|
+
* Defaults to 0.35.
|
|
174
|
+
*/
|
|
175
|
+
minActiveScale?: number;
|
|
176
|
+
style?: CSSProperties;
|
|
177
|
+
/** Enables the click-to-inspect overlay (library component + props + className). */
|
|
178
|
+
inspector?: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Connect a design system to the Inspector (token reverse-lookup, library
|
|
181
|
+
* component + icon detection). Defaults to the no-design-system generic
|
|
182
|
+
* adapter. See `../adapters` + `examples/springAdapter.ts`.
|
|
183
|
+
*/
|
|
184
|
+
adapter?: DesignSystemAdapter;
|
|
185
|
+
/**
|
|
186
|
+
* Enables the comment layer (drop pins on artboard elements, thread, resolve).
|
|
187
|
+
* Inert when omitted/false. `canvasId` namespaces the data in the
|
|
188
|
+
* comments-service; `devMode` uses an in-memory mock store instead of the network.
|
|
189
|
+
*/
|
|
190
|
+
comments?: false | CommentsConfig;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export declare interface DesignSystemAdapter {
|
|
194
|
+
libraryLabel: string;
|
|
195
|
+
libraryShortLabel: string;
|
|
196
|
+
isLibraryComponent(type: any): boolean;
|
|
197
|
+
componentName(type: any): string | null;
|
|
198
|
+
classify(type: any): {
|
|
199
|
+
kind: ComponentKind;
|
|
200
|
+
name: string | null;
|
|
201
|
+
};
|
|
202
|
+
findIconName(fiber: AdapterFiber | null): string | null;
|
|
203
|
+
iconWrapperSize?(fiber: AdapterFiber | null): string | null;
|
|
204
|
+
iconImportSnippet(name: string): string;
|
|
205
|
+
iconLabel: string;
|
|
206
|
+
tokens: AdapterTokens;
|
|
207
|
+
themeScopeAttr?: string;
|
|
208
|
+
themeForegroundToken?: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** A person from the directory, for the @mention picker (GET /api/directory?q=). */
|
|
212
|
+
export declare interface DirectoryPerson {
|
|
213
|
+
/** Stable directory id for the picked person (the service's user id). */
|
|
214
|
+
personId: string;
|
|
215
|
+
name: string;
|
|
216
|
+
/** Shown to disambiguate same-named people. */
|
|
217
|
+
email: string;
|
|
218
|
+
/**
|
|
219
|
+
* True when this person has already participated on the queried canvas (commented
|
|
220
|
+
* or been @mentioned). Server-set, only present when a `canvasId` is sent with the
|
|
221
|
+
* query; drives the "On this canvas" grouping in the picker. Undefined for the mock
|
|
222
|
+
* client and any query without a canvas → the picker shows a flat, ungrouped list.
|
|
223
|
+
*/
|
|
224
|
+
isParticipant?: boolean;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Optional directory backend for the @mention typeahead. When omitted, the
|
|
229
|
+
* network client falls back to its own `/api/directory` endpoint.
|
|
230
|
+
*/
|
|
231
|
+
export declare interface DirectoryProvider {
|
|
232
|
+
search(q: string): Promise<DirectoryPerson[]>;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export declare const genericAdapter: DesignSystemAdapter;
|
|
236
|
+
|
|
237
|
+
export declare function getDesignSystemAdapter(): DesignSystemAdapter;
|
|
238
|
+
|
|
239
|
+
/** Signed-in profile (extends PublicUser with the write gate). */
|
|
240
|
+
export declare interface Me extends PublicUser {
|
|
241
|
+
canWrite: boolean;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** Curated public identity — what threads render. Never an email. */
|
|
245
|
+
export declare interface PublicUser {
|
|
246
|
+
id: string;
|
|
247
|
+
username: string;
|
|
248
|
+
displayName: string;
|
|
249
|
+
avatarUrl: string | null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export declare function setDesignSystemAdapter(adapter: DesignSystemAdapter): void;
|
|
253
|
+
|
|
254
|
+
/** Point all DesignCanvas-family portals at `el` (null restores body). */
|
|
255
|
+
export declare function setPortalRoot(el: HTMLElement | null): void;
|
|
256
|
+
|
|
257
|
+
export declare type TypographyTokenSpec = {
|
|
258
|
+
classMatcher: (selectorText: string) => string[];
|
|
259
|
+
signature?: (s: CSSStyleDeclaration) => string;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export declare const useArtboardActive: () => boolean;
|
|
263
|
+
|
|
264
|
+
export declare type UtilityClassPrefixes = {
|
|
265
|
+
typography: string;
|
|
266
|
+
text: string;
|
|
267
|
+
bg: string;
|
|
268
|
+
border: string;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export { }
|
package/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { D, h, j, k, m, n, g, s, q, u } from "./lib-CSrTsI4Y.js";
|
|
2
|
+
export {
|
|
3
|
+
D as DCArtboard,
|
|
4
|
+
h as DCPage,
|
|
5
|
+
j as DCPostIt,
|
|
6
|
+
k as DCSection,
|
|
7
|
+
m as DesignCanvas,
|
|
8
|
+
n as genericAdapter,
|
|
9
|
+
g as getDesignSystemAdapter,
|
|
10
|
+
s as setDesignSystemAdapter,
|
|
11
|
+
q as setPortalRoot,
|
|
12
|
+
u as useArtboardActive
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|