@livetemplate/client 0.11.5 → 0.11.7

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.
@@ -153,4 +153,157 @@ export declare function setupToastClickOutside(): void;
153
153
  * also logs a console.warn so the divergence is visible.
154
154
  */
155
155
  export declare function handleShadowRootHydration(rootElement: Element): void;
156
+ /**
157
+ * Apply area-select directives. `lvt-fx:area-select="<actionName>"` on
158
+ * an element (typically an `<img>` inside a positioned parent) lets
159
+ * the user drag a rectangle locally — a `<div>` overlay tracks the
160
+ * gesture in real time without a server round-trip — and on
161
+ * `pointerup` dispatches a single livetemplate action with the final
162
+ * `{x, y, w, h}` as 0..1 fractions of the element's rendered bounding
163
+ * rect. The image's intrinsic dimensions don't matter for the
164
+ * fractions: any uniform scale (zoom, responsive layout) preserves
165
+ * the fraction. The consumer scales to pixels using the natural size
166
+ * if it needs them.
167
+ *
168
+ * Contract:
169
+ * - Host's `parentElement` must establish a positioning context
170
+ * (`position: relative` / `absolute` / `fixed`). The overlay is
171
+ * `position: absolute` inside that parent so it follows the host
172
+ * on scroll / reflow.
173
+ * - Consumers usually pair this with `touch-action: none` on the
174
+ * host so iOS Safari doesn't interpret the drag as a pinch/scroll.
175
+ * - `<img>` and other natively-draggable hosts work automatically:
176
+ * the directive calls `preventDefault()` on `dragstart` so the
177
+ * browser's native drag (which would otherwise steal the gesture)
178
+ * is suppressed.
179
+ * - On pointer-cancel (e.g. system gesture, app switch), the overlay
180
+ * is removed and no action is dispatched — same effect as cancelling
181
+ * a click on `mouseleave`.
182
+ * - Drags smaller than `MIN_AREA_FRACTION` in BOTH dimensions are
183
+ * dropped — a click on the host still fires normal `click`
184
+ * handlers via the compatibility mouse events.
185
+ * - For text-bearing hosts, set `user-select: none` (the directive
186
+ * deliberately does NOT call `preventDefault()` on `pointerdown`
187
+ * so click handlers still receive the gesture; that means the
188
+ * browser's default text-selection-on-drag behaviour also fires
189
+ * unless the host opts out via CSS).
190
+ * - The overlay uses `z-index: var(--lvt-area-select-z-index, 9999)`.
191
+ * 9999 is high enough for most use cases but can collide with
192
+ * portals / modals / drawers that also sit at a high z-index.
193
+ * Set `--lvt-area-select-z-index` on the host (or any ancestor)
194
+ * to override. Color + fill follow the same pattern via
195
+ * `--lvt-area-select-color` and `--lvt-area-select-fill`.
196
+ * - **No keyboard equivalent.** Pointer-only by design (a keyboard-
197
+ * selected rectangle requires a different UX — focus + arrow keys
198
+ * to position + arrow keys to size). Consumers needing a11y for
199
+ * area selection should provide a parallel form-based affordance.
200
+ *
201
+ * Idempotent across renders: an element re-armed with the same action
202
+ * keeps its existing listeners. A different action causes a tear-down
203
+ * and re-arm. Disconnected elements (and elements whose attribute was
204
+ * cleared by a server diff) get their listeners cleaned up by the
205
+ * sweep at the top of every call — we use a regular Map (not WeakMap)
206
+ * specifically so the sweep can iterate.
207
+ *
208
+ * Module-level singleton: `areaSelectArmed` is shared across all
209
+ * LiveTemplateClient instances in the same window. If two clients
210
+ * ever arm the same element with different actions, the second wins
211
+ * and the first client's send() is orphaned. Single-client use is
212
+ * unaffected.
213
+ */
214
+ export declare function handleAreaSelectDirectives(rootElement: Element, send: (message: {
215
+ action: string;
216
+ data: Record<string, unknown>;
217
+ }) => void): void;
218
+ /**
219
+ * Cancel area-select listeners for every armed element under root.
220
+ * Mirrors teardownAutoClickTimers: meant for the client's disconnect /
221
+ * destroy lifecycle so the module-level singleton doesn't outlive a
222
+ * client that was torn down without a subsequent
223
+ * handleAreaSelectDirectives call (e.g. network error closed the
224
+ * socket while an element was armed). Without this, a SPA that mounts
225
+ * + tears down livetemplate trees would leak listeners across mounts.
226
+ */
227
+ export declare function teardownAreaSelectForRoot(rootElement: Element): void;
228
+ /**
229
+ * Apply url-hash directives. `lvt-fx:url-hash="<actionName>"` plus a
230
+ * `data-lvt-url-hash="<hash>"` attribute on an element (typically the
231
+ * `<body>`) wires a two-way bridge between server state and
232
+ * `location.hash`:
233
+ *
234
+ * - **State → URL** (every render): if `data-lvt-url-hash` differs
235
+ * from `location.hash`, mirror the data-attr into the URL via
236
+ * `history.pushState` when the path component changed (everything
237
+ * before the first `:`) or `history.replaceState` when only the
238
+ * target (line range / anchor) changed. Replace is the right
239
+ * default for line scrolls so the back-button cycles between files,
240
+ * not between every clicked line.
241
+ * - **URL → State** (on `hashchange` AND initial arm): dispatch
242
+ * `{action: <actionName>, data: {hash: <hash>}}` so the server can
243
+ * parse the hash and update its state (which then renders back as
244
+ * a matching data-attr — closing the loop).
245
+ *
246
+ * The directive uses `history.pushState`/`replaceState` (not
247
+ * `location.hash = ...`) for the state→URL direction precisely so
248
+ * those writes do NOT fire `hashchange` — only true user-initiated
249
+ * navigation (anchor click, address-bar edit, back-button) reaches
250
+ * the URL→state listener. This avoids the obvious infinite loop.
251
+ *
252
+ * Idempotent across renders: same action → keep listener + update
253
+ * send. Different action → cleanup + re-arm. Detached / attribute-
254
+ * removed elements are swept on every call (same pattern as
255
+ * area-select). The window listener is registered on first arm and
256
+ * removed when the armed map becomes empty.
257
+ *
258
+ * Coexistence with `setupHashLink`: prereview-style hashes
259
+ * (`README.md:L4`, `foo/bar.html:h-anchor`) never match a
260
+ * `document.getElementById(...)`, so the existing dialog/popover/
261
+ * details hash machinery silently no-ops. If a deep-link hash
262
+ * happens to collide with an element id, both handlers will fire —
263
+ * the server is expected to no-op on hashes that don't resolve to a
264
+ * known file.
265
+ *
266
+ * **Pre-encoding contract**: `data-lvt-url-hash` must hold the hash
267
+ * value already in URL-encoded form. The directive writes the
268
+ * attribute verbatim into `history.pushState`/`replaceState`, so a
269
+ * value containing spaces, `[`, `]`, `%`, or other reserved
270
+ * characters needs to be percent-encoded by the server. The hash
271
+ * sent to the action on `hashchange` is also passed through unmodified
272
+ * (no decoding) — both directions are byte-exact mirrors of what's
273
+ * in `location.hash`.
274
+ *
275
+ * **URL/state divergence after a non-deep-link initial load**: if
276
+ * the user lands with a native-anchor hash (`#hero`) AND the server
277
+ * has a selected file, the directive leaves the URL on `#hero` (case
278
+ * b) — URL and server state diverge until the user navigates. This
279
+ * is intentional: popovers/anchors aren't ours to overwrite. The
280
+ * next user action that triggers a server render will re-sync only
281
+ * once URL and state share a deep-link hash.
282
+ *
283
+ * **Path-only deep links require an extension**: the
284
+ * `looksLikeDeepLinkHash` heuristic dispatches only hashes
285
+ * containing `:`, `/`, or `.`. Extension-less root files
286
+ * (`#Makefile`, `#Dockerfile`, `#LICENSE`) won't dispatch as
287
+ * path-only deep links — use the line form (`#Makefile:L1`)
288
+ * instead. The trade-off favours not clobbering native-anchor
289
+ * machinery for single-token hashes.
290
+ */
291
+ export declare function handleURLHashDirective(rootElement: Element, send: (message: {
292
+ action: string;
293
+ data: Record<string, unknown>;
294
+ }) => void): void;
295
+ /**
296
+ * Cancel url-hash listeners for every armed element under root. Same
297
+ * lifecycle role as teardownAreaSelectForRoot.
298
+ */
299
+ export declare function teardownURLHashForRoot(rootElement: Element): void;
300
+ /**
301
+ * Test-only: reset the per-page dedupe Set that suppresses repeated
302
+ * `warnIfUnencodedHash` calls for the same hash value. Production
303
+ * code shouldn't need this — the Set is bounded by the number of
304
+ * unique malformed hashes — but tests that re-use the same hash
305
+ * across cases need to clear it or the second test won't see the
306
+ * warning. Mirrors `__resetAnimatedElementsForTesting`.
307
+ */
308
+ export declare function __resetURLHashUnencodedWarnedForTesting(): void;
156
309
  //# sourceMappingURL=directives.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":"AA4CA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iCAAiC,IAAI,IAAI,CAKxD;AAsBD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CA0CvF;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAWrE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,OAAO,EACpB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAiBN;AAiLD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAiBpE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAUvE;AAaD,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAMjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA8FpE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAQlE;AAwCD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA4BhE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAW7C;AAkFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAyGpE"}
1
+ {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../../dom/directives.ts"],"names":[],"mappings":"AA4CA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iCAAiC,IAAI,IAAI,CAKxD;AAsBD;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CA0CvF;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAWrE;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,OAAO,EACpB,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAiBN;AAiLD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAiBpE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAUvE;AAaD,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAMjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA8FpE;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAMpE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAQlE;AAwCD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA4BhE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAW7C;AAkFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAyGpE;AA4CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,OAAO,EACpB,IAAI,EAAE,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,KAAK,IAAI,GACzE,IAAI,CAyCN;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CAQpE;AAqDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,OAAO,EACpB,IAAI,EAAE,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,KAAK,IAAI,GACzE,IAAI,CAyFN;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI,CA0BjE;AAgFD;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,IAAI,IAAI,CAE9D"}