@bluepic/embed 0.5.9 → 0.5.11
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/dist/bluepic-embed.iife.js +72 -72
- package/dist/bluepic-embed.umd.js +72 -72
- package/dist/components/BxPreviewLayer.vue.d.ts +11 -0
- package/dist/components/TemplateEditor/BxTemplateEditor.vue.d.ts +8 -0
- package/dist/components/TemplateEditor/FieldHintsLayer.vue.d.ts +9 -0
- package/dist/components/TemplateEditor/ImageBusyLayer.vue.d.ts +14 -0
- package/dist/components/TemplateEditor/TemplateView.vue.d.ts +9 -0
- package/dist/embed/embed.d.ts +32 -0
- package/dist/main.cjs +24 -24
- package/dist/main.mjs +1873 -1614
- package/dist/style.css +1 -1
- package/dist/util/imageStates/index.d.ts +4 -0
- package/dist/util/imageStates/probe.d.ts +83 -0
- package/dist/util/imageStates/useImageStates.d.ts +63 -0
- package/package.json +3 -2
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { imageStateProbe, imageStateProbeStop, IMAGE_STATE_MESSAGE } from './probe';
|
|
2
|
+
export type { ImageLoadState, ImageStateEntry, ImageStatePoint, ImageStateQuad, ImageStateSnapshot } from './probe';
|
|
3
|
+
export { useImageStates, createImageStateStore } from './useImageStates';
|
|
4
|
+
export type { ImageOverlay } from './useImageStates';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sandbox-side image-state watcher.
|
|
3
|
+
*
|
|
4
|
+
* Everything else in the editor updates instantly: a binding changes, the
|
|
5
|
+
* engine recomposes, the pixels are already right. A picture is the exception —
|
|
6
|
+
* it has to travel the network first — and because an expression can drive
|
|
7
|
+
* `image.image` off something that *looks* instantaneous (a dropdown), there is
|
|
8
|
+
* no way to know from the outside whether a data change will land in one frame
|
|
9
|
+
* or in two seconds.
|
|
10
|
+
*
|
|
11
|
+
* `@bluepic/core` answers that on the element itself (`Image.vue`), publishing
|
|
12
|
+
* `data-bx-image-state` on each rendered image's `<g>`. The DOM is the channel
|
|
13
|
+
* because a sandboxed frame is all DOM to us: we cannot import from it, and its
|
|
14
|
+
* engine version is not ours to choose.
|
|
15
|
+
*
|
|
16
|
+
* ⚠️ SHIPPED AS SOURCE TEXT, NOT AS A CLOSURE — same rules as
|
|
17
|
+
* `fieldHints/probe.ts`: `EmbeddedController.evaluate()` does `func.toString()`
|
|
18
|
+
* and `new Function(...)` inside the frame, so the body runs in a scope where
|
|
19
|
+
* nothing from this bundle exists. No free variables beyond `document`/`window`,
|
|
20
|
+
* plain ES, JSON in and JSON out.
|
|
21
|
+
*
|
|
22
|
+
* AND NO NAMED INNER FUNCTION OF ANY KIND — a constraint that comes from the
|
|
23
|
+
* TEST pipeline, not from the shipped one. Vite's production build leaves probe
|
|
24
|
+
* bodies alone (verified against the built `dist/bluepic-embed.umd.js`), but
|
|
25
|
+
* `tsx`/esbuild runs with `keepNames`, which rewrites every function with an
|
|
26
|
+
* inferable name — `function read()`, `var read = function()`, `var read = () =>`,
|
|
27
|
+
* object methods alike — into `__name(fn, 'read')`, a helper that does not exist
|
|
28
|
+
* in the frame. A probe written with inner functions therefore cannot be
|
|
29
|
+
* EXERCISED by the `new Function` round trip that proves self-containment; the
|
|
30
|
+
* fieldHints probes only pass theirs because the stub returns before reaching
|
|
31
|
+
* any of their code. Two forms survive `keepNames`, and this probe uses both:
|
|
32
|
+
* an anonymous callback passed inline (`new MutationObserver(function () {…})`)
|
|
33
|
+
* and a function assigned to a MEMBER (`w.__bxImageStateRead = function () {…}`).
|
|
34
|
+
* The cost is a slightly odd shape; the gain is a test that runs the real body.
|
|
35
|
+
*
|
|
36
|
+
* Unlike the geometry probe this one INSTALLS: it returns the current snapshot
|
|
37
|
+
* and then keeps posting to the parent as things change. Polling at the latency
|
|
38
|
+
* a spinner needs would be a round trip every few frames.
|
|
39
|
+
*/
|
|
40
|
+
export type ImageLoadState = 'loading' | 'ready' | 'error';
|
|
41
|
+
export type ImageStatePoint = {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
};
|
|
45
|
+
export type ImageStateQuad = [ImageStatePoint, ImageStatePoint, ImageStatePoint, ImageStatePoint];
|
|
46
|
+
export type ImageStateEntry = {
|
|
47
|
+
/** Rendered instance id — an iterated element reports `id__0`, `id__1`, … */
|
|
48
|
+
id: string;
|
|
49
|
+
state: ImageLoadState;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the ENGINE is currently painting its in-flight treatment (the blur)
|
|
52
|
+
* on this instance — its own timed decision, not the raw `state`.
|
|
53
|
+
*
|
|
54
|
+
* The spinner follows this rather than timing the wait itself. While the two
|
|
55
|
+
* decided independently they disagreed by construction: the blur stopped the
|
|
56
|
+
* instant `load` fired, the spinner served out its own minimum, and it was
|
|
57
|
+
* left turning over an unblurred picture for up to 420ms. One clock, one
|
|
58
|
+
* follower.
|
|
59
|
+
*/
|
|
60
|
+
busy: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* The element's AUTHORED frame in serial coordinates, not the painted
|
|
63
|
+
* picture: a contain-mode image paints smaller than its frame, and a busy
|
|
64
|
+
* overlay that shrank to the old picture's letterbox would jump the moment
|
|
65
|
+
* the new one landed. Absent when the frame has not painted yet — the host
|
|
66
|
+
* keeps whatever it measured last.
|
|
67
|
+
*/
|
|
68
|
+
quad?: ImageStateQuad;
|
|
69
|
+
};
|
|
70
|
+
export type ImageStateSnapshot = {
|
|
71
|
+
/**
|
|
72
|
+
* `false` means this engine predates `data-bx-image-state`: it renders images
|
|
73
|
+
* but publishes no state for them. The host then treats every picture as
|
|
74
|
+
* loaded, which is exactly how the editor behaved before this feature.
|
|
75
|
+
*/
|
|
76
|
+
supported: boolean;
|
|
77
|
+
entries: ImageStateEntry[];
|
|
78
|
+
};
|
|
79
|
+
/** What the installed watcher posts to the parent window. */
|
|
80
|
+
export declare const IMAGE_STATE_MESSAGE = "bx:image-states";
|
|
81
|
+
export declare function imageStateProbe(configJson: string): ImageStateSnapshot;
|
|
82
|
+
/** Tears the watcher down. Separate function because probes ship as source. */
|
|
83
|
+
export declare function imageStateProbeStop(): boolean;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type Ref } from 'vue';
|
|
2
|
+
import { type ImageLoadState, type ImageStateEntry, type ImageStateQuad } from './probe';
|
|
3
|
+
export type ImageOverlay = {
|
|
4
|
+
/** Rendered instance id: `id__0`, `id__1`, … for an iterated element. */
|
|
5
|
+
id: string;
|
|
6
|
+
state: ImageLoadState;
|
|
7
|
+
/** Element frame in SERIAL coordinates. */
|
|
8
|
+
quad: ImageStateQuad;
|
|
9
|
+
aabb: {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
centroid: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
type EvaluateFn = (func: Function, ...args: string[]) => Promise<unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Snapshots in, "what is covered right now" out, keyed by RENDERED INSTANCE id —
|
|
23
|
+
* an iterated element contributes one entry per instance, so `logo__2` can be
|
|
24
|
+
* covered while `logo__0` and `logo__1` stay untouched.
|
|
25
|
+
*
|
|
26
|
+
* NO TIMERS LIVE HERE. Deciding when a wait is worth announcing used to be this
|
|
27
|
+
* file's job, and it was the right place while the host also drew the blur. Once
|
|
28
|
+
* the blur moved into the engine (only the engine knows an image's clip, radius
|
|
29
|
+
* and mask) two clocks were deciding one thing: the blur stopped the instant
|
|
30
|
+
* `load` fired while the spinner served out its own 420ms minimum, so on
|
|
31
|
+
* medium-speed loads the spinner was left turning over an unblurred picture.
|
|
32
|
+
* The engine now makes that call once and publishes it; this mirrors it. See
|
|
33
|
+
* `useInFlightTreatment` in @bluepic/core.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createImageStateStore(): {
|
|
36
|
+
apply: (list: ImageStateEntry[]) => void;
|
|
37
|
+
states: import("vue").ComputedRef<Record<string, ImageLoadState>>;
|
|
38
|
+
busy: import("vue").ComputedRef<boolean>;
|
|
39
|
+
overlays: import("vue").ComputedRef<ImageOverlay[]>;
|
|
40
|
+
coveredIds: import("vue").ComputedRef<Set<string>>;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Live load state for every rendered image in the sandbox.
|
|
44
|
+
*
|
|
45
|
+
* The store above is the level; the sandbox pushes the edges. See `probe.ts`
|
|
46
|
+
* for why this is a DOM watcher installed over `evaluate()` rather than a core
|
|
47
|
+
* event or a poll.
|
|
48
|
+
*/
|
|
49
|
+
export declare function useImageStates(options: {
|
|
50
|
+
/** Resolved lazily — the sandbox controller only exists once the iframe mounts. */
|
|
51
|
+
evaluate: () => EvaluateFn | undefined;
|
|
52
|
+
/** The frame's own window, so a message from anywhere else can be ignored. */
|
|
53
|
+
frameWindow: () => Window | null | undefined;
|
|
54
|
+
ready: Ref<boolean>;
|
|
55
|
+
}): {
|
|
56
|
+
states: import("vue").ComputedRef<Record<string, ImageLoadState>>;
|
|
57
|
+
busy: import("vue").ComputedRef<boolean>;
|
|
58
|
+
overlays: import("vue").ComputedRef<ImageOverlay[]>;
|
|
59
|
+
coveredIds: import("vue").ComputedRef<Set<string>>;
|
|
60
|
+
supported: Ref<boolean | undefined, boolean | undefined>;
|
|
61
|
+
dispose: () => void;
|
|
62
|
+
};
|
|
63
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bluepic/embed",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.11",
|
|
4
4
|
"description": "Bluepic embed sdk",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"test:autocrop": "tsx src/util/autoCrop/solveAutoCrop.test.ts",
|
|
43
43
|
"test:gallery": "tsx src/util/gallery.test.ts",
|
|
44
44
|
"test:fieldhints": "tsx src/util/fieldHints/fieldHints.test.ts",
|
|
45
|
-
"test:clone": "tsx src/util/cloneDeep.test.ts"
|
|
45
|
+
"test:clone": "tsx src/util/cloneDeep.test.ts",
|
|
46
|
+
"test:imagestates": "tsx src/util/imageStates/imageStates.test.ts"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"vue": "^3.5.23"
|