feat: client updates for livepage features#10
Conversation
Release @livetemplate/client v0.7.1 This release follows the core library version: 0.7.x 🤖 Generated with automated release script
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds client-side utilities and refactors event delegation to support livepage features, specifically expanding confirmation dialog support and introducing data extraction utilities.
- Refactored
lvt-confirmhandling to apply to all actions (not just delete) - Added reusable utility functions
checkLvtConfirmandextractLvtData - Exported new utilities and
setupReactiveAttributeListenersfor external use
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
utils/confirm.ts |
New utility file with checkLvtConfirm for confirmation dialogs and extractLvtData for extracting lvt-data-* attributes |
dom/event-delegation.ts |
Refactored to use checkLvtConfirm utility and expanded confirmation support from delete-only to all actions |
livetemplate-client.ts |
Exported checkLvtConfirm, extractLvtData, and setupReactiveAttributeListeners for external consumption |
package.json |
Bumped version from 0.7.0 to 0.7.1 |
package-lock.json |
Updated lock file to reflect version bump |
VERSION |
Updated version number to 0.7.1 |
CHANGELOG.md |
Added v0.7.1 release entry (though changes listed may not match this PR) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function checkLvtConfirm(element: HTMLElement): boolean { | ||
| if (element.hasAttribute("lvt-confirm")) { | ||
| const confirmMessage = element.getAttribute("lvt-confirm"); | ||
| if (confirmMessage && !confirm(confirmMessage)) { | ||
| return false; // User cancelled | ||
| } | ||
| } | ||
| return true; // Proceed | ||
| } |
There was a problem hiding this comment.
The checkLvtConfirm function lacks test coverage. Given that the repository has comprehensive test coverage for other utility functions (e.g., tests/rate-limit.test.ts for utils/rate-limit.ts), this new utility function should also have tests covering various scenarios including: elements with lvt-confirm attribute where user confirms, elements with lvt-confirm attribute where user cancels, and elements without the attribute.
| export function extractLvtData(element: HTMLElement): Record<string, string> { | ||
| const data: Record<string, string> = {}; | ||
| const attributes = element.attributes; | ||
|
|
||
| for (let i = 0; i < attributes.length; i++) { | ||
| const attr = attributes[i]; | ||
| if (attr.name.startsWith("lvt-data-")) { | ||
| const key = attr.name.substring(9); // Remove "lvt-data-" prefix | ||
| data[key] = attr.value; | ||
| } | ||
| } | ||
|
|
||
| return data; | ||
| } |
There was a problem hiding this comment.
The extractLvtData function lacks test coverage. Given that the repository has comprehensive test coverage for other utility functions (e.g., tests/rate-limit.test.ts for utils/rate-limit.ts), this new utility function should also have tests covering various scenarios including: extracting single attributes, extracting multiple attributes, handling elements without lvt-data attributes, and handling attribute names with hyphens like lvt-data-user-name.
| // Handle lvt-confirm for any action | ||
| if (!checkLvtConfirm(targetElement as HTMLElement)) { | ||
| this.logger.debug("Action cancelled by user:", action); | ||
| return; | ||
| } |
There was a problem hiding this comment.
The refactored lvt-confirm handling now applies to all actions, not just delete actions. This is a significant behavioral change that should be covered by tests. The existing tests/event-delegation.test.ts does not have any tests for lvt-confirm functionality. Tests should be added to verify that: 1) actions with lvt-confirm are properly blocked when the user cancels, 2) actions proceed when the user confirms, and 3) this works for various action types (not just delete).
| ## [v0.7.1] - 2025-12-14 | ||
|
|
||
| ### Changes | ||
|
|
||
| - fix: apply differential ops to existing range structures (#9) (50a3ebc) | ||
| - fix: handle objects with only numeric keys in renderValue (#8) (b1c7827) | ||
| - feat: add lvt-focus-trap and lvt-autofocus attributes (#7) (7b14402) | ||
| - feat: add reactive attributes for action lifecycle events (#6) (46e2065) | ||
|
|
||
|
|
There was a problem hiding this comment.
The CHANGELOG entry for v0.7.1 lists changes from previous PRs (issues #6-9) that don't appear to be related to this PR. According to the PR description, this PR adds client-side updates for livepage features including event delegation updates, livetemplate client updates, and a confirm utility. The CHANGELOG should be updated to accurately reflect the changes in this specific PR.
| export function checkLvtConfirm(element: HTMLElement): boolean { | ||
| if (element.hasAttribute("lvt-confirm")) { | ||
| const confirmMessage = element.getAttribute("lvt-confirm"); | ||
| if (confirmMessage && !confirm(confirmMessage)) { | ||
| return false; // User cancelled | ||
| } | ||
| } | ||
| return true; // Proceed | ||
| } |
There was a problem hiding this comment.
The checkLvtConfirm function has different behavior than the original code it replaces. The original code in dom/event-delegation.ts provided a default message "Are you sure you want to delete this item?" when lvt-confirm had an empty value. The new implementation will skip the confirmation dialog if the attribute value is empty or null (line 8 condition: if (confirmMessage && !confirm(confirmMessage))). This means elements with lvt-confirm="" will now proceed without confirmation, whereas previously they would show the default message. This could be a breaking change if any code relies on the default message behavior.
| // Handle lvt-confirm for any action | ||
| if (!checkLvtConfirm(targetElement as HTMLElement)) { |
There was a problem hiding this comment.
This change expands lvt-confirm from only working with delete actions to working with all actions. While this is a useful enhancement, it's a breaking behavioral change that should be documented in the CHANGELOG. Users who previously added lvt-confirm to non-delete actions (expecting it to be ignored) will now see confirmation dialogs. Consider noting this as a potentially breaking change in the version release notes.
| // Handle lvt-confirm for any action | |
| if (!checkLvtConfirm(targetElement as HTMLElement)) { | |
| // Only apply lvt-confirm to delete-like actions to avoid breaking behavior | |
| const isDeleteAction = | |
| typeof action === "string" && /^delete/i.test(action); | |
| if (isDeleteAction && !checkLvtConfirm(targetElement as HTMLElement)) { |
| export function extractLvtData(element: HTMLElement): Record<string, string> { | ||
| const data: Record<string, string> = {}; | ||
| const attributes = element.attributes; | ||
|
|
||
| for (let i = 0; i < attributes.length; i++) { | ||
| const attr = attributes[i]; | ||
| if (attr.name.startsWith("lvt-data-")) { | ||
| const key = attr.name.substring(9); // Remove "lvt-data-" prefix | ||
| data[key] = attr.value; | ||
| } | ||
| } | ||
|
|
||
| return data; | ||
| } |
There was a problem hiding this comment.
The extractLvtData function duplicates logic that already exists in three places in dom/event-delegation.ts (lines 197-202, 365-370, and 444-449). However, there's a subtle difference: the existing code uses replace("lvt-data-", "") which would only replace the first occurrence, while this new function uses substring(9) which is more correct. Additionally, the existing code applies parseValue() to the attribute values, while this function does not. Consider consolidating this logic into a single reusable function and updating all call sites to use it, ensuring consistent behavior across the codebase.
Summary
Client-side updates to support livepage features.
Changes
dom/event-delegation.tslivetemplate-client.tsutils/confirm.tsTest plan
🤖 Generated with Claude Code