@bluepic/embed 0.4.0-next.146 → 0.4.0-next.148

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.
@@ -0,0 +1,23 @@
1
+ import type { BluepicField } from '@bluepic/types';
2
+ /**
3
+ * What clicking a hint chip does.
4
+ *
5
+ * There is no per-field hint MODE any more — hints are simply on or off for the
6
+ * whole campaign (`config.hints.enabled`). What a chip does is inferred from the
7
+ * field itself:
8
+ *
9
+ * - `upload` — an image field that accepts a device upload. Clicking goes
10
+ * straight to its own upload flow, which is the only thing anyone wants from
11
+ * an image chip.
12
+ * - `focus` — everything else, including image fields restricted to libraries.
13
+ * The chip scrolls the field into view and focuses its control, so the next
14
+ * keystroke already types into it.
15
+ */
16
+ export type ChipAction = 'upload' | 'focus';
17
+ /**
18
+ * `field.props` entries may be author expressions (functions) rather than
19
+ * literals, so a prop can only be read through the host's evaluator — the same
20
+ * `wrapFieldProps` treatment `FieldsList` gives every field component.
21
+ */
22
+ export declare function readFieldProp<T>(value: T | (() => T), evaluate?: (fn: Function) => unknown): T | undefined;
23
+ export declare function chipActionFor(field: BluepicField, evaluate?: (fn: Function) => unknown): ChipAction;
@@ -49,7 +49,7 @@ export declare const FIELD_FOCUS_FLASH_CLASS = "bx-field-hint-target";
49
49
  * container, and centering yanks the whole list even when the target was
50
50
  * already comfortably visible.
51
51
  */
52
- export declare function revealFieldElement(el: HTMLElement | null | undefined): void;
52
+ export declare function revealFieldElement(el: HTMLElement | null | undefined): HTMLElement | undefined;
53
53
  /**
54
54
  * Creates the desktop half: a registry keyed by the field object itself.
55
55
  *
@@ -9,7 +9,13 @@ export type { FieldHitbox } from './useFieldHitboxes';
9
9
  export { useHintReveal } from './useHintReveal';
10
10
  export { createFieldElementRegistry, provideFieldFocus, revealFieldElement, useFieldFocus, FIELD_FOCUS_KEY, FIELD_FOCUS_FLASH_CLASS, } from './fieldFocus';
11
11
  export type { FieldFocusController } from './fieldFocus';
12
- export { interactModeFor, inlineTextBinding, readFieldProp } from './interact';
13
- export type { InteractMode } from './interact';
12
+ export { chipActionFor, readFieldProp } from './chipAction';
13
+ export type { ChipAction } from './chipAction';
14
+ export { textGeometryProbe } from './textProbe';
15
+ export type { CaretGeometry, SelectionQuad, TextGeometryResult, TextIndexResult } from './textProbe';
16
+ export { useCanvasTextEditing } from './useCanvasTextEditing';
17
+ export type { CanvasTextState, SelectionHandle } from './useCanvasTextEditing';
18
+ export { chooseChipPlacement, chipIsCentered, estimateChipWidth, arrowRotationForSide } from './placement';
19
+ export type { ChipSide, PlacementResult } from './placement';
14
20
  export { useFieldActivator } from './fieldFocus';
15
21
  export type { FieldActivator } from './fieldFocus';
@@ -55,3 +55,18 @@ export declare function chooseChipPlacement(input: PlacementInput): PlacementRes
55
55
  * guess here would place the first paint visibly wrong.
56
56
  */
57
57
  export declare function estimateChipWidth(label: string, max?: number): number;
58
+ /**
59
+ * The arrow artwork points RIGHT at rest — the path's tip is authored on the
60
+ * left, but `popoverArrow`'s outer `matrix(-1,0,-0,-1,...)` flips it. Verified
61
+ * by rasterising the mask: the left edge is ~97% covered (the flat base) and
62
+ * the right edge ~4% (the point).
63
+ */
64
+ export declare const ARROW_NATIVE_DIRECTION: {
65
+ x: number;
66
+ y: number;
67
+ };
68
+ /**
69
+ * Degrees to rotate the arrow so it points from the chip back at its hitbox.
70
+ * CSS rotation is clockwise with y pointing down.
71
+ */
72
+ export declare function arrowRotationForSide(side: ChipSide): number;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Text geometry on the canvas: where the caret is, what the selection covers,
3
+ * and which character a point lands on.
4
+ *
5
+ * All three answers come from the glyphs the engine actually laid out, via
6
+ * `SVGTextContentElement`:
7
+ * `getStartPositionOfChar` / `getEndPositionOfChar` — caret and range edges
8
+ * `getExtentOfChar` — line height / em box
9
+ * `getCharNumAtPosition` — point → character
10
+ * plus the tspan's computed `fill` for colour. Verified against a live 0.2.65
11
+ * sandbox: hit-testing along a line returned the exact character at each
12
+ * position and −1 outside.
13
+ *
14
+ * ONE probe with an `op` rather than three: it ships as SOURCE TEXT (see the
15
+ * warning on `fieldHitboxProbe`), so helpers cannot be shared between separate
16
+ * probe functions — they would have to be duplicated inside each one. The line
17
+ * mapping below is subtle enough that having two copies drift apart is a real
18
+ * risk, so the ops share one body.
19
+ */
20
+ /**
21
+ * A caret as a SEGMENT rather than a point plus a height.
22
+ *
23
+ * Both ends are computed in the line's local space and mapped out, so the
24
+ * segment carries the text's rotation, skew and scale intrinsically. Returning
25
+ * `{x, y, height}` instead forced the consumer to subtract the ascent in SERIAL
26
+ * y — which is only "up" for unrotated text, and left carets and handle stems
27
+ * standing vertically through slanted text.
28
+ */
29
+ export type CaretGeometry = {
30
+ /** Top of the em box, in serial coordinates. */
31
+ top: {
32
+ x: number;
33
+ y: number;
34
+ };
35
+ /** Bottom of the em box, in serial coordinates. */
36
+ bottom: {
37
+ x: number;
38
+ y: number;
39
+ };
40
+ /** Resolved text colour, so the caret matches the words it sits in. */
41
+ color: string;
42
+ lineIndex: number;
43
+ };
44
+ /** One selected run on one line, as a quad so rotated text still works. */
45
+ export type SelectionQuad = {
46
+ points: Array<{
47
+ x: number;
48
+ y: number;
49
+ }>;
50
+ lineIndex: number;
51
+ };
52
+ export type TextGeometryResult = {
53
+ found: false;
54
+ } | {
55
+ found: true;
56
+ /** Present only when the selection is collapsed — a caret, not a range. */
57
+ caret?: CaretGeometry;
58
+ selection: SelectionQuad[];
59
+ /** Range ends, for the mobile drag handles. Present when a range exists. */
60
+ startAnchor?: CaretGeometry;
61
+ endAnchor?: CaretGeometry;
62
+ };
63
+ export type TextIndexResult = {
64
+ index: number | null;
65
+ };
66
+ /**
67
+ * ⚠️ SHIPPED AS SOURCE TEXT — no imports, no module-scope references, plain ES.
68
+ *
69
+ * @param argsJson `{ op, elementId, value, selectionStart, selectionEnd, x, y }`
70
+ */
71
+ export declare function textGeometryProbe(argsJson: string): TextGeometryResult | TextIndexResult;
@@ -0,0 +1,125 @@
1
+ import { type Ref } from 'vue';
2
+ import type { BluepicField } from '@bluepic/types';
3
+ import { type CaretGeometry, type SelectionQuad } from './textProbe';
4
+ type EvaluateFn = (func: Function, ...args: string[]) => Promise<unknown>;
5
+ export type CanvasTextState = {
6
+ caret?: CaretGeometry;
7
+ selection: SelectionQuad[];
8
+ startAnchor?: CaretGeometry;
9
+ endAnchor?: CaretGeometry;
10
+ };
11
+ export type SelectionHandle = 'start' | 'end';
12
+ export declare function useCanvasTextEditing(options: {
13
+ evaluate: () => EvaluateFn | undefined;
14
+ data: Ref<{
15
+ [k: string]: unknown;
16
+ }>;
17
+ }): {
18
+ state: Ref<{
19
+ caret?: {
20
+ top: {
21
+ x: number;
22
+ y: number;
23
+ };
24
+ bottom: {
25
+ x: number;
26
+ y: number;
27
+ };
28
+ color: string;
29
+ lineIndex: number;
30
+ } | undefined;
31
+ selection: {
32
+ points: {
33
+ x: number;
34
+ y: number;
35
+ }[];
36
+ lineIndex: number;
37
+ }[];
38
+ startAnchor?: {
39
+ top: {
40
+ x: number;
41
+ y: number;
42
+ };
43
+ bottom: {
44
+ x: number;
45
+ y: number;
46
+ };
47
+ color: string;
48
+ lineIndex: number;
49
+ } | undefined;
50
+ endAnchor?: {
51
+ top: {
52
+ x: number;
53
+ y: number;
54
+ };
55
+ bottom: {
56
+ x: number;
57
+ y: number;
58
+ };
59
+ color: string;
60
+ lineIndex: number;
61
+ } | undefined;
62
+ } | undefined, CanvasTextState | {
63
+ caret?: {
64
+ top: {
65
+ x: number;
66
+ y: number;
67
+ };
68
+ bottom: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ color: string;
73
+ lineIndex: number;
74
+ } | undefined;
75
+ selection: {
76
+ points: {
77
+ x: number;
78
+ y: number;
79
+ }[];
80
+ lineIndex: number;
81
+ }[];
82
+ startAnchor?: {
83
+ top: {
84
+ x: number;
85
+ y: number;
86
+ };
87
+ bottom: {
88
+ x: number;
89
+ y: number;
90
+ };
91
+ color: string;
92
+ lineIndex: number;
93
+ } | undefined;
94
+ endAnchor?: {
95
+ top: {
96
+ x: number;
97
+ y: number;
98
+ };
99
+ bottom: {
100
+ x: number;
101
+ y: number;
102
+ };
103
+ color: string;
104
+ lineIndex: number;
105
+ } | undefined;
106
+ } | undefined>;
107
+ activeElementId: Ref<string | undefined, string | undefined>;
108
+ isActive: import("vue").ComputedRef<boolean>;
109
+ begin: (next: {
110
+ field: BluepicField;
111
+ elementId: string;
112
+ binding: string;
113
+ input: HTMLInputElement | HTMLTextAreaElement;
114
+ }) => void;
115
+ end: () => void;
116
+ beginSelectionAt: (x: number, y: number) => Promise<void>;
117
+ beginHandleDrag: (handle: SelectionHandle, point: {
118
+ x: number;
119
+ y: number;
120
+ }) => void;
121
+ extendSelectionTo: (x: number, y: number) => Promise<void>;
122
+ endSelectionDrag: () => void;
123
+ selectWordAt: (x: number, y: number) => Promise<void>;
124
+ };
125
+ export {};