From d8f7eb3f24d6864c28ba3b65e3d7c4dafcd97707 Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 7 Jan 2026 07:29:43 +0800 Subject: [PATCH 1/3] Add 'clone' callback to build, implement for Input --- src/browser/webapi/Element.zig | 5 +++++ src/browser/webapi/element/html/Input.zig | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 4de815e5..d1cdf802 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -978,6 +978,11 @@ pub fn cloneElement(self: *Element, deep: bool, page: *Page) !*Node { 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) { var child_it = self.asNode().childrenIterator(); while (child_it.next()) |child| { diff --git a/src/browser/webapi/element/html/Input.zig b/src/browser/webapi/element/html/Input.zig index 437cae8a..47b3af09 100644 --- a/src/browser/webapi/element/html/Input.zig +++ b/src/browser/webapi/element/html/Input.zig @@ -404,6 +404,17 @@ 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; + } }; const testing = @import("../../../../testing.zig"); From c9d0e2097d9ffd2b2ab5a2b4fc18ef152ef17b4d Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 7 Jan 2026 07:35:24 +0800 Subject: [PATCH 2/3] add input indeterminate accessor --- src/browser/webapi/element/html/Input.zig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/browser/webapi/element/html/Input.zig b/src/browser/webapi/element/html/Input.zig index 47b3af09..1af2d548 100644 --- a/src/browser/webapi/element/html/Input.zig +++ b/src/browser/webapi/element/html/Input.zig @@ -76,6 +76,7 @@ _checked: bool = false, _checked_dirty: bool = false, _input_type: Type = .text, _selected: bool = false, +_indeterminate: bool = false, pub fn asElement(self: *Input) *Element { return self._proto._proto; @@ -129,6 +130,14 @@ pub fn setChecked(self: *Input, checked: bool, page: *Page) !void { 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 { return self._default_checked; } @@ -342,6 +351,7 @@ pub const JsApi = struct { pub const size = bridge.accessor(Input.getSize, Input.setSize, .{}); pub const src = bridge.accessor(Input.getSrc, Input.setSrc, .{}); pub const form = bridge.accessor(Input.getForm, null, .{}); + pub const indeterminate = bridge.accessor(Input.getIndeterminate, Input.setIndeterminate, .{}); pub const select = bridge.function(Input.select, .{}); }; @@ -414,6 +424,7 @@ pub const Build = struct { clone._checked = source._checked; clone._checked_dirty = source._checked_dirty; clone._selected = source._selected; + clone._indeterminate = source._indeterminate; } }; From 6864a2272118965f4d38d83bd6132aa476fb33df Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Wed, 7 Jan 2026 07:39:42 +0800 Subject: [PATCH 3/3] fix datetime-local input type --- src/browser/webapi/element/html/Input.zig | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/browser/webapi/element/html/Input.zig b/src/browser/webapi/element/html/Input.zig index 1af2d548..7bcd27a3 100644 --- a/src/browser/webapi/element/html/Input.zig +++ b/src/browser/webapi/element/html/Input.zig @@ -46,14 +46,16 @@ pub const Type = enum { range, date, time, - datetime_local, + @"datetime-local", month, week, color, pub fn fromString(str: []const u8) Type { // 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; const lower = std.ascii.lowerString(&buf, str); @@ -61,10 +63,7 @@ pub const Type = enum { } pub fn toString(self: Type) []const u8 { - return switch (self) { - .datetime_local => "datetime-local", - else => @tagName(self), - }; + return @tagName(self); } };