Merge pull request #1322 from lightpanda-io/input_clone

Add 'clone' callback to build, implement for Input
This commit is contained in:
Karl Seguin
2026-01-07 13:08:20 +08:00
committed by GitHub
2 changed files with 32 additions and 6 deletions

View File

@@ -990,6 +990,11 @@ pub fn cloneElement(self: *Element, deep: bool, page: *Page) !*Node {
const node = try page.createElement(namespace_uri, tag_name, self._attributes); const node = try page.createElement(namespace_uri, tag_name, self._attributes);
// Allow element-specific types to copy their runtime state
_ = Element.Build.call(node.as(Element), "cloned", .{ self, node.as(Element), page }) catch |err| {
log.err(.dom, "element.clone.failed", .{ .err = err });
};
if (deep) { if (deep) {
var child_it = self.asNode().childrenIterator(); var child_it = self.asNode().childrenIterator();
while (child_it.next()) |child| { while (child_it.next()) |child| {

View File

@@ -46,14 +46,16 @@ pub const Type = enum {
range, range,
date, date,
time, time,
datetime_local, @"datetime-local",
month, month,
week, week,
color, color,
pub fn fromString(str: []const u8) Type { pub fn fromString(str: []const u8) Type {
// Longest type name is "datetime-local" at 14 chars // Longest type name is "datetime-local" at 14 chars
if (str.len > 32) return .text; if (str.len > 32) {
return .text;
}
var buf: [32]u8 = undefined; var buf: [32]u8 = undefined;
const lower = std.ascii.lowerString(&buf, str); const lower = std.ascii.lowerString(&buf, str);
@@ -61,10 +63,7 @@ pub const Type = enum {
} }
pub fn toString(self: Type) []const u8 { pub fn toString(self: Type) []const u8 {
return switch (self) { return @tagName(self);
.datetime_local => "datetime-local",
else => @tagName(self),
};
} }
}; };
@@ -76,6 +75,7 @@ _checked: bool = false,
_checked_dirty: bool = false, _checked_dirty: bool = false,
_input_type: Type = .text, _input_type: Type = .text,
_selected: bool = false, _selected: bool = false,
_indeterminate: bool = false,
pub fn asElement(self: *Input) *Element { pub fn asElement(self: *Input) *Element {
return self._proto._proto; return self._proto._proto;
@@ -129,6 +129,14 @@ pub fn setChecked(self: *Input, checked: bool, page: *Page) !void {
self._checked_dirty = true; self._checked_dirty = true;
} }
pub fn getIndeterminate(self: *const Input) bool {
return self._indeterminate;
}
pub fn setIndeterminate(self: *Input, value: bool) !void {
self._indeterminate = value;
}
pub fn getDefaultChecked(self: *const Input) bool { pub fn getDefaultChecked(self: *const Input) bool {
return self._default_checked; return self._default_checked;
} }
@@ -342,6 +350,7 @@ pub const JsApi = struct {
pub const size = bridge.accessor(Input.getSize, Input.setSize, .{}); pub const size = bridge.accessor(Input.getSize, Input.setSize, .{});
pub const src = bridge.accessor(Input.getSrc, Input.setSrc, .{}); pub const src = bridge.accessor(Input.getSrc, Input.setSrc, .{});
pub const form = bridge.accessor(Input.getForm, null, .{}); pub const form = bridge.accessor(Input.getForm, null, .{});
pub const indeterminate = bridge.accessor(Input.getIndeterminate, Input.setIndeterminate, .{});
pub const select = bridge.function(Input.select, .{}); pub const select = bridge.function(Input.select, .{});
}; };
@@ -404,6 +413,18 @@ pub const Build = struct {
}, },
} }
} }
pub fn cloned(source_element: *Element, cloned_element: *Element, _: *Page) !void {
const source = source_element.as(Input);
const clone = cloned_element.as(Input);
// Copy runtime state from source to clone
clone._value = source._value;
clone._checked = source._checked;
clone._checked_dirty = source._checked_dirty;
clone._selected = source._selected;
clone._indeterminate = source._indeterminate;
}
}; };
const testing = @import("../../../../testing.zig"); const testing = @import("../../../../testing.zig");