@bluepic/embed 0.4.0-next.138 → 0.4.0-next.142
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 +122 -122
- package/dist/bluepic-embed.umd.js +122 -122
- package/dist/components/fields/Text.vue.d.ts +1 -1
- package/dist/embed/embed.d.ts +6 -0
- package/dist/main.cjs +70 -70
- package/dist/main.mjs +13080 -13081
- package/dist/util/fieldHints/geometry.d.ts +52 -0
- package/dist/util/fieldHints/index.d.ts +8 -0
- package/dist/util/fieldHints/probe.d.ts +73 -0
- package/dist/util/fieldHints/resolve.d.ts +55 -0
- package/dist/util/fieldHints/useFieldHitboxes.d.ts +5692 -0
- package/dist/util/fieldTree.d.ts +20 -0
- package/dist/util/fields.d.ts +17 -1
- package/package.json +4 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { BluepicField } from '@bluepic/types';
|
|
2
|
+
import type { HintPoint, HintQuad } from './probe';
|
|
3
|
+
/**
|
|
4
|
+
* Geometry helpers over probe output. Everything here works in SERIAL
|
|
5
|
+
* coordinates — the overlay maps to screen space via zoompinch's
|
|
6
|
+
* `composePoint`, so nothing in this file needs to know about pan, zoom or
|
|
7
|
+
* viewport size.
|
|
8
|
+
*/
|
|
9
|
+
/** Shoelace area. Quads may be rotated or sheared, so no width×height shortcut. */
|
|
10
|
+
export declare function quadArea(quad: HintQuad): number;
|
|
11
|
+
export declare function quadCentroid(quad: HintQuad): HintPoint;
|
|
12
|
+
export declare function quadAABB(quad: HintQuad): {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Which frame a quad belongs to, in the 1-based numbering `field.frameIndex`
|
|
20
|
+
* already uses (`BxTemplateEditor` reads it as `field.frameIndex || 1` and
|
|
21
|
+
* derives `frameX = (frameIndex - 1) % frames.x`).
|
|
22
|
+
*
|
|
23
|
+
* Decided by the centroid, so an element straddling a frame boundary lands in
|
|
24
|
+
* the frame it mostly occupies rather than being duplicated or dropped.
|
|
25
|
+
*/
|
|
26
|
+
export declare function frameIndexOfPoint(point: HintPoint, serialWidth: number, serialHeight: number, frames: {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
} | undefined): number;
|
|
30
|
+
/**
|
|
31
|
+
* Stacking class for overlap resolution — lower sits ON TOP.
|
|
32
|
+
*
|
|
33
|
+
* Hitboxes overlap constantly (a logo inside a full-bleed background image), so
|
|
34
|
+
* the pointer has to go somewhere defensible. Content-bearing fields win over
|
|
35
|
+
* pickers, which win over the tweak-a-value controls.
|
|
36
|
+
*/
|
|
37
|
+
export declare function hintPriorityClass(fieldType: BluepicField['type']): number;
|
|
38
|
+
export type OrderableHitbox = {
|
|
39
|
+
fieldType: BluepicField['type'];
|
|
40
|
+
area: number;
|
|
41
|
+
/** Position of the element in the serial's depth-first order; later paints later. */
|
|
42
|
+
elementOrder: number;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Sorts hitboxes back-to-front, so the caller can render in array order and let
|
|
46
|
+
* DOM order do the stacking. The LAST entry is the topmost / most reachable.
|
|
47
|
+
*
|
|
48
|
+
* Smaller area on top is what keeps a logo sitting inside a full-bleed image
|
|
49
|
+
* clickable — without it the background would swallow every pointer event
|
|
50
|
+
* inside its own bounds.
|
|
51
|
+
*/
|
|
52
|
+
export declare function orderHitboxes<T extends OrderableHitbox>(hitboxes: T[]): T[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { fieldHitboxProbe } from './probe';
|
|
2
|
+
export type { HintPoint, HintQuad, ElementQuad, HitboxProbeResult } from './probe';
|
|
3
|
+
export { collectSerialElements, expandBindingClosure, fieldBindings, referencesIdentifier, resolveFieldElements, scoreElement, CANDIDATE_SCORE_RATIO, } from './resolve';
|
|
4
|
+
export type { FieldElementMatch } from './resolve';
|
|
5
|
+
export { frameIndexOfPoint, hintPriorityClass, orderHitboxes, quadAABB, quadArea, quadCentroid } from './geometry';
|
|
6
|
+
export type { OrderableHitbox } from './geometry';
|
|
7
|
+
export { useFieldHitboxes } from './useFieldHitboxes';
|
|
8
|
+
export type { FieldHitbox } from './useFieldHitboxes';
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sandbox-side geometry probe.
|
|
3
|
+
*
|
|
4
|
+
* Field hints need to know where each element ACTUALLY landed on the canvas —
|
|
5
|
+
* after every ancestor transform, layout-group flow shift, mask clip and text
|
|
6
|
+
* auto-fit. That composition already happened once, inside the sandbox iframe,
|
|
7
|
+
* and the browser is holding the result. So rather than re-deriving it in the
|
|
8
|
+
* parent (which would mean linking `@bluepic/core` into this package and
|
|
9
|
+
* pinning ONE engine version against sandboxes that deliberately freeze one
|
|
10
|
+
* engine per template), we ask the frame that drew the pixels.
|
|
11
|
+
*
|
|
12
|
+
* `getBBox()` gives an element's local geometry; `getScreenCTM()` gives its
|
|
13
|
+
* full transform chain — CSS `transform` included, which is how core applies
|
|
14
|
+
* per-element matrices. Composing the element's screen CTM with the INVERSE of
|
|
15
|
+
* the root SVG's screen CTM cancels out viewport sizing and `preserveAspectRatio`
|
|
16
|
+
* letterboxing, leaving a matrix straight into viewBox units — i.e. serial
|
|
17
|
+
* coordinates. Verified against a live sandbox (0.2.65) to 0.0000px for an
|
|
18
|
+
* identity rect, a 23°-rotated text element, a rotate+scale group, and a rect
|
|
19
|
+
* nested inside that group.
|
|
20
|
+
*
|
|
21
|
+
* Nothing here needs a core release or a sandbox redeploy: it travels as source
|
|
22
|
+
* text through the existing `EmbeddedController.evaluate()` channel.
|
|
23
|
+
*/
|
|
24
|
+
export type HintPoint = {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
};
|
|
28
|
+
/** Element corners in serial coordinates, clockwise from the local top-left. */
|
|
29
|
+
export type HintQuad = [HintPoint, HintPoint, HintPoint, HintPoint];
|
|
30
|
+
export type ElementQuad = {
|
|
31
|
+
/**
|
|
32
|
+
* The rendered instance's unique id (`data-id`). An element with an
|
|
33
|
+
* `iteration` renders once per item, so one serial element can yield several
|
|
34
|
+
* of these — `id__0`, `id__1`, … — all sharing one `data-orginal-id`.
|
|
35
|
+
*/
|
|
36
|
+
dataId: string;
|
|
37
|
+
quad: HintQuad;
|
|
38
|
+
};
|
|
39
|
+
export type HitboxProbeResult = {
|
|
40
|
+
supported: false;
|
|
41
|
+
/**
|
|
42
|
+
* `no-root` — no `.serial-wrapper > svg` yet (not mounted, or a sandbox
|
|
43
|
+
* that structures its DOM differently).
|
|
44
|
+
* `no-element-identity` — rendered, but the engine predates per-element
|
|
45
|
+
* `data-id` attributes (roughly < core 0.1.400). Nothing to anchor to;
|
|
46
|
+
* hints stay off for this template forever, by design.
|
|
47
|
+
* `no-ctm` — the root SVG has no screen CTM (whole subtree hidden).
|
|
48
|
+
*/
|
|
49
|
+
reason: 'no-root' | 'no-element-identity' | 'no-ctm';
|
|
50
|
+
} | {
|
|
51
|
+
supported: true;
|
|
52
|
+
quads: {
|
|
53
|
+
[originalId: string]: ElementQuad[];
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* ⚠️ THIS FUNCTION IS SHIPPED AS SOURCE TEXT, NOT AS A CLOSURE.
|
|
58
|
+
*
|
|
59
|
+
* `EmbeddedController.evaluate()` does `func.toString()` here and `new Function(...)`
|
|
60
|
+
* inside the iframe, so the body executes in a scope where NOTHING from this
|
|
61
|
+
* bundle exists. Any reference to an import, a module-scope const, or a helper
|
|
62
|
+
* defined outside these braces typechecks, builds green, and then throws
|
|
63
|
+
* `ReferenceError` in the sandbox under a minified name that won't resemble the
|
|
64
|
+
* original.
|
|
65
|
+
*
|
|
66
|
+
* Rules, all enforced by `probe.test.ts`:
|
|
67
|
+
* - one self-contained function; no free variables beyond `document`
|
|
68
|
+
* - plain ES (`var`, `function`, no optional chaining) so no transpiler
|
|
69
|
+
* helper can be hoisted out of the body
|
|
70
|
+
* - arguments in as a JSON string, return value JSON-serialisable — flatten
|
|
71
|
+
* every `DOMMatrix`/`DOMRect` before returning
|
|
72
|
+
*/
|
|
73
|
+
export declare function fieldHitboxProbe(originalIdsJson: string): HitboxProbeResult;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { BluepicField, Template } from '@bluepic/types';
|
|
2
|
+
/**
|
|
3
|
+
* Candidates scoring below this share of the winner are dropped. Keeps the
|
|
4
|
+
* legitimate multi-element cases — a headline plus the background bar bound to
|
|
5
|
+
* it, or one binding echoed across two frames — while cutting the long tail of
|
|
6
|
+
* weak style/visibility couplings that would otherwise blanket the canvas.
|
|
7
|
+
*/
|
|
8
|
+
export declare const CANDIDATE_SCORE_RATIO = 0.6;
|
|
9
|
+
export type FieldElementMatch = {
|
|
10
|
+
/** Serial element id — matches the rendered `data-orginal-id`. */
|
|
11
|
+
elementId: string;
|
|
12
|
+
element: Template.Element;
|
|
13
|
+
score: number;
|
|
14
|
+
/** Property keys that produced the match, for debugging a surprising hitbox. */
|
|
15
|
+
matchedProperties: string[];
|
|
16
|
+
};
|
|
17
|
+
/** Depth-first walk over the serial tree, descending into group/mask slots. */
|
|
18
|
+
export declare function collectSerialElements(elements: Template.Element[]): Generator<Template.Element>;
|
|
19
|
+
/**
|
|
20
|
+
* Does `expression` reference `name` as a standalone identifier?
|
|
21
|
+
*
|
|
22
|
+
* Hand-rolled rather than a regex with a lookbehind: `(?<!…)` still throws at
|
|
23
|
+
* compile time on Safari below 16.4, and a template that renders fine
|
|
24
|
+
* everywhere else must not blank its hints on an older iPad. A preceding `.`
|
|
25
|
+
* is excluded so `other.headline` doesn't match `headline`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function referencesIdentifier(expression: string, name: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Every binding that carries this field's value, mapped to how many
|
|
30
|
+
* `computedBindings` hops away it is. A field may write `headline`, while the
|
|
31
|
+
* element actually reads `headlineUpper = UPPER(headline)`.
|
|
32
|
+
*
|
|
33
|
+
* Iterated to a fixpoint and guarded on improvement only, so a cyclic
|
|
34
|
+
* computed-binding definition terminates instead of spinning.
|
|
35
|
+
*/
|
|
36
|
+
export declare function expandBindingClosure(computedBindings: {
|
|
37
|
+
[k: string]: string;
|
|
38
|
+
} | undefined, roots: string[]): Map<string, number>;
|
|
39
|
+
/** The bindings a field writes. Group/Instruction fields have none. */
|
|
40
|
+
export declare function fieldBindings(field: BluepicField): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Score one element against one field. Returns `null` when nothing matched.
|
|
43
|
+
* The score is the STRONGEST single property match, not a sum — an element
|
|
44
|
+
* whose text is bound to the field shouldn't outrank a sibling merely by also
|
|
45
|
+
* borrowing the same value for its opacity.
|
|
46
|
+
*/
|
|
47
|
+
export declare function scoreElement(field: BluepicField, element: Template.Element, hopsByBinding: Map<string, number>): {
|
|
48
|
+
score: number;
|
|
49
|
+
matchedProperties: string[];
|
|
50
|
+
} | null;
|
|
51
|
+
/**
|
|
52
|
+
* The elements a field drives, best first, already cut to the candidates worth
|
|
53
|
+
* drawing a hitbox for.
|
|
54
|
+
*/
|
|
55
|
+
export declare function resolveFieldElements(serial: Template.Serial, field: BluepicField): FieldElementMatch[];
|