@bluepic/embed 0.4.0-next.99 → 0.5.1

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.
Files changed (87) hide show
  1. package/dist/bluepic-embed.iife.js +402 -178
  2. package/dist/bluepic-embed.umd.js +402 -178
  3. package/dist/components/AssetViewer/AssetViewer.vue.d.ts +71 -0
  4. package/dist/components/BxAudioPlayButton.vue.d.ts +24 -0
  5. package/dist/components/BxCard.vue.d.ts +35 -0
  6. package/dist/components/BxInput.vue.d.ts +7 -1
  7. package/dist/components/BxList.vue.d.ts +9 -0
  8. package/dist/components/BxListItem.vue.d.ts +13 -1
  9. package/dist/components/BxPopover.vue.d.ts +7 -0
  10. package/dist/components/BxPreviewLayer.vue.d.ts +18 -0
  11. package/dist/components/BxScrollbar.vue.d.ts +7 -0
  12. package/dist/components/BxSelect.vue.d.ts +16 -2
  13. package/dist/components/BxTable.vue.d.ts +109 -0
  14. package/dist/components/BxTabs.vue.d.ts +7 -0
  15. package/dist/components/BxWaveformThumb.vue.d.ts +27 -0
  16. package/dist/components/CollectionFieldPopup.vue.d.ts +4 -0
  17. package/dist/components/PopoverElement.vue.d.ts +10 -1
  18. package/dist/components/TemplateEditor/BatchCell.vue.d.ts +18 -0
  19. package/dist/components/TemplateEditor/BatchEditor.vue.d.ts +264 -0
  20. package/dist/components/TemplateEditor/BatchExportPopup.vue.d.ts +68 -0
  21. package/dist/components/TemplateEditor/BatchImportPopup.vue.d.ts +25 -0
  22. package/dist/components/TemplateEditor/BxLiveTemplate.vue.d.ts +8 -0
  23. package/dist/components/TemplateEditor/BxTemplateEditor.vue.d.ts +285 -16
  24. package/dist/components/TemplateEditor/FieldHintsLayer.vue.d.ts +86 -0
  25. package/dist/components/TemplateEditor/TemplateView.vue.d.ts +77 -2
  26. package/dist/components/User/UserInfo.vue.d.ts +12 -1
  27. package/dist/components/directives/usePopup.d.ts +5 -0
  28. package/dist/components/fields/Collection.vue.d.ts +3 -0
  29. package/dist/components/fields/Image.vue.d.ts +19 -5
  30. package/dist/components/fields/ImageEdit.vue.d.ts +6 -1
  31. package/dist/components/fields/Text.vue.d.ts +1 -1
  32. package/dist/embed/embed.d.ts +1024 -228
  33. package/dist/{index-CWm6zOv7.js → index-C99_zLhc.js} +9 -9
  34. package/dist/index-D8N6IfRw.cjs +1 -0
  35. package/dist/main.cjs +240 -162
  36. package/dist/main.d.ts +20 -0
  37. package/dist/main.mjs +79043 -68465
  38. package/dist/markdown-it-5-ieF6Bh.js +3790 -0
  39. package/dist/markdown-it-CLB5Jta6.cjs +16 -0
  40. package/dist/postal-mime-Df-WB8Vq.js +3337 -0
  41. package/dist/postal-mime-_7WF5UBe.cjs +28 -0
  42. package/dist/style.css +1 -1
  43. package/dist/theme/bridge.d.ts +14 -0
  44. package/dist/theme/color.d.ts +80 -0
  45. package/dist/theme/css.d.ts +8 -0
  46. package/dist/theme/index.d.ts +19 -0
  47. package/dist/theme/legacy.d.ts +3 -0
  48. package/dist/theme/resolve.d.ts +10 -0
  49. package/dist/theme/tokens.d.ts +129 -0
  50. package/dist/theme/types-contract.d.ts +13 -0
  51. package/dist/theme.cjs +1 -0
  52. package/dist/theme.mjs +1313 -0
  53. package/dist/util/assetAuth.d.ts +35 -0
  54. package/dist/util/audioPreview.d.ts +8 -0
  55. package/dist/util/batch/csv.d.ts +58 -0
  56. package/dist/util/batch/export.d.ts +92 -0
  57. package/dist/util/batch/fields.d.ts +22 -0
  58. package/dist/util/batch/parseCSV.d.ts +72 -0
  59. package/dist/util/batch/useBatchRows.d.ts +67 -0
  60. package/dist/util/cloneDeep.d.ts +5 -5
  61. package/dist/util/cloudflareImages.d.ts +8 -1
  62. package/dist/util/contextCapture.d.ts +19 -0
  63. package/dist/util/export.d.ts +65 -18
  64. package/dist/util/fieldHints/chipAction.d.ts +23 -0
  65. package/dist/util/fieldHints/fieldFocus.d.ts +81 -0
  66. package/dist/util/fieldHints/geometry.d.ts +52 -0
  67. package/dist/util/fieldHints/index.d.ts +20 -0
  68. package/dist/util/fieldHints/probe.d.ts +84 -0
  69. package/dist/util/fieldHints/resolve.d.ts +55 -0
  70. package/dist/util/fieldHints/textProbe.d.ts +71 -0
  71. package/dist/util/fieldHints/useCanvasTextEditing.d.ts +125 -0
  72. package/dist/util/fieldHints/useChipHighlight.d.ts +29 -0
  73. package/dist/util/fieldHints/useFieldHitboxes.d.ts +5601 -0
  74. package/dist/util/fieldHints/useHintReveal.d.ts +10 -0
  75. package/dist/util/fieldTree.d.ts +20 -0
  76. package/dist/util/fields.d.ts +1 -1
  77. package/dist/util/gallery.d.ts +78 -30
  78. package/dist/util/popoverArrow.d.ts +33 -0
  79. package/dist/util/popupHeaderTools.d.ts +26 -0
  80. package/dist/util/scrollPassthrough.d.ts +9 -0
  81. package/dist/util/useTheme.d.ts +36 -1
  82. package/dist/util/visualViewport.d.ts +47 -0
  83. package/dist/xlsx-BopDBbWb.js +24176 -0
  84. package/dist/xlsx-qn1xoUuv.cjs +105 -0
  85. package/package.json +18 -5
  86. package/dist/index-DFXQWOGQ.cjs +0 -1
  87. package/dist/util/backgroundRemoval.d.ts +0 -51
@@ -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,20 @@
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';
9
+ export { useHintReveal } from './useHintReveal';
10
+ export { useChipHighlight } from './useChipHighlight';
11
+ export { createFieldElementRegistry, provideFieldFocus, revealFieldElement, useFieldFocus, FIELD_FOCUS_KEY, FIELD_FOCUS_FLASH_CLASS, FIELD_HOVER_CLASS, } from './fieldFocus';
12
+ export type { FieldFocusController } from './fieldFocus';
13
+ export { chipActionFor, fieldHasChip, readFieldProp } from './chipAction';
14
+ export type { ChipAction } from './chipAction';
15
+ export { textGeometryProbe } from './textProbe';
16
+ export type { CaretGeometry, SelectionQuad, TextGeometryResult, TextIndexResult } from './textProbe';
17
+ export { useCanvasTextEditing } from './useCanvasTextEditing';
18
+ export type { CanvasTextState, SelectionHandle } from './useCanvasTextEditing';
19
+ export { useFieldActivator } from './fieldFocus';
20
+ export type { FieldActivator } from './fieldFocus';
@@ -0,0 +1,84 @@
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
+ * Tighter box to POINT AT, when the element has one. Present only for text
40
+ * elements whose painted box is larger than the glyphs — i.e. text carrying a
41
+ * surface/background bar, where `quad` balloons out to the whole text frame.
42
+ *
43
+ * The hover region stays `quad` (generous, easy to hit); only the tooltip's
44
+ * anchor moves here, so a bubble describing a headline points at the words
45
+ * rather than at the far corner of the bar behind them. Absent whenever the
46
+ * two coincide, which is the common case.
47
+ */
48
+ anchor?: HintQuad;
49
+ };
50
+ export type HitboxProbeResult = {
51
+ supported: false;
52
+ /**
53
+ * `no-root` — no `.serial-wrapper > svg` yet (not mounted, or a sandbox
54
+ * that structures its DOM differently).
55
+ * `no-element-identity` — rendered, but the engine predates per-element
56
+ * `data-id` attributes (roughly < core 0.1.400). Nothing to anchor to;
57
+ * hints stay off for this template forever, by design.
58
+ * `no-ctm` — the root SVG has no screen CTM (whole subtree hidden).
59
+ */
60
+ reason: 'no-root' | 'no-element-identity' | 'no-ctm';
61
+ } | {
62
+ supported: true;
63
+ quads: {
64
+ [originalId: string]: ElementQuad[];
65
+ };
66
+ };
67
+ /**
68
+ * ⚠️ THIS FUNCTION IS SHIPPED AS SOURCE TEXT, NOT AS A CLOSURE.
69
+ *
70
+ * `EmbeddedController.evaluate()` does `func.toString()` here and `new Function(...)`
71
+ * inside the iframe, so the body executes in a scope where NOTHING from this
72
+ * bundle exists. Any reference to an import, a module-scope const, or a helper
73
+ * defined outside these braces typechecks, builds green, and then throws
74
+ * `ReferenceError` in the sandbox under a minified name that won't resemble the
75
+ * original.
76
+ *
77
+ * Rules, all enforced by `probe.test.ts`:
78
+ * - one self-contained function; no free variables beyond `document`
79
+ * - plain ES (`var`, `function`, no optional chaining) so no transpiler
80
+ * helper can be hoisted out of the body
81
+ * - arguments in as a JSON string, return value JSON-serialisable — flatten
82
+ * every `DOMMatrix`/`DOMRect` before returning
83
+ */
84
+ 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[];
@@ -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 {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Which hint is highlighted, and which chip is on screen — two answers, because
3
+ * they are not the same question.
4
+ *
5
+ * The OUTLINE follows the pointer exactly: whatever it is over is the element
6
+ * being asked about, and nothing else may be lit.
7
+ *
8
+ * The CHIP cannot, because of where it sits. It is centred on its picture, so
9
+ * reaching it means travelling ACROSS that picture — and pictures nest (a logo,
10
+ * a portrait, a badge over a background), so the trip regularly crosses another
11
+ * hitbox. Handing the chip straight over to whatever the pointer touched on the
12
+ * way pulled it out from under a pointer already aimed at it, and the click
13
+ * landed on the element underneath instead: the upload dialog simply never
14
+ * opened. A chip that has just lost the highlight therefore stays painted (and
15
+ * clickable) for a moment longer.
16
+ *
17
+ * That grace period is not a lifetime: arriving on the chip re-activates it
18
+ * (`activate` from the chip's own `pointerenter`), so it only ever has to
19
+ * outlast the trip.
20
+ */
21
+ export declare function useChipHighlight({ lingerMs }?: {
22
+ lingerMs?: number;
23
+ }): {
24
+ activeKey: import("vue").Ref<string | undefined, string | undefined>;
25
+ chipShown: (key: string) => boolean;
26
+ activate: (key: string) => void;
27
+ release: (key: string) => boolean;
28
+ reset: () => void;
29
+ };