Skip to content

Commit

Permalink
feat(wasm-api-dom): add attrib creation opts
Browse files Browse the repository at this point in the history
- add Attrib, AttribValue, AttribType types
- update CreateElementOpts
- update initElement() to batch create given attribs
- update doc strings
  • Loading branch information
postspectacular committed Nov 1, 2022
1 parent a0e7132 commit 0e69c47
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 18 deletions.
27 changes: 24 additions & 3 deletions packages/wasm-api-dom/src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
$CreateElementOpts,
$Event,
$WindowInfo,
Attrib,
AttribType,
CreateElementOpts,
DOMExports,
DOMImports,
Expand Down Expand Up @@ -138,7 +140,7 @@ export class WasmDom implements IWasmAPI<DOMExports> {
const opts = $CreateCanvasOpts(this.parent).instance(optsAddr);
const el = document.createElement("canvas");
adaptDPI(el, opts.width, opts.height, opts.dpr);
this.initElement(el, <any>opts);
this.initElement(el, opts);
return this.elements.add(el);
},

Expand Down Expand Up @@ -362,17 +364,36 @@ export class WasmDom implements IWasmAPI<DOMExports> {
Readonly<CreateElementOpts>,
"class" | "id" | "index" | "parent"
> &
Partial<{ html: ReadonlyWasmString; text: ReadonlyWasmString }>,
Partial<{
attribs: Attrib[];
html: ReadonlyWasmString;
text: ReadonlyWasmString;
}>,
nestedParent?: number
) {
const { id, class: $class, index } = opts;
const { id, attribs, class: $class, index } = opts;
if (id.length) el.setAttribute("id", id.deref());
if ($class.length) el.setAttribute("class", $class.deref());
if (opts.html?.length) {
el.innerHTML = opts.html.deref();
} else if (opts.text?.length) {
(<HTMLElement>el).innerText = opts.text.deref();
}
if (attribs && attribs.length) {
for (let attr of attribs) {
const name = attr.name.deref();
if (attr.kind === AttribType.FLAG) {
attr.value.flag && el.setAttribute(name, "");
} else {
el.setAttribute(
name,
attr.kind === AttribType.STR
? attr.value.str.deref()
: String(attr.value.num)
);
}
}
}
const parent = nestedParent != undefined ? nestedParent : opts.parent;
if (parent >= 0) {
const parentEl = this.elements.get(parent);
Expand Down
127 changes: 120 additions & 7 deletions packages/wasm-api-dom/src/generated/api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Generated by @thi.ng/wasm-api at 2022-10-30T07:52:41.295Z - DO NOT EDIT!
* Generated by @thi.ng/wasm-api at 2022-11-01T11:56:07.332Z - DO NOT EDIT!
*/

// @ts-ignore possibly includes unused imports
Expand Down Expand Up @@ -951,11 +951,12 @@ export const $EventBody: WasmTypeConstructor<EventBody> = (mem) => ({
export interface Event extends WasmTypeBase {
id: EventType;
/**
* Target element ID, positive if a known element, otherwise:
* Target element ID, > 1 if a known (WASM created) element, otherwise:
*
* - 0: document.body
* - -1: window
* - -2: = unknown
* - -1: window
* - 0: document.head
* - 1: document.body
*
* WASM type: i32
*/
Expand All @@ -964,6 +965,7 @@ export interface Event extends WasmTypeBase {
* Event details / payload. Currently, only the following event types have a
* defined body:
*
* - drag
* - input
* - key
* - mouse
Expand Down Expand Up @@ -1050,15 +1052,24 @@ export interface CreateElementOpts extends WasmTypeBase {
* WASM type: i32
*/
index: number;
/**
* Optional slice of child element specs, which will be automatically attached
* as children to this element (their `parent` ID will be ignored)
*/
children: CreateElementOpts[];
/**
* Optional slice of attribute definitions for this element. Also see provided
* `Attrib` factory fns for convenience.
*/
attribs: Attrib[];
}

export const $CreateElementOpts: WasmTypeConstructor<CreateElementOpts> = (mem) => ({
get align() {
return 4;
},
get size() {
return 64;
return 72;
},
instance: (base) => {
let $tag: WasmStringSlice | null = null;
Expand All @@ -1072,7 +1083,7 @@ export const $CreateElementOpts: WasmTypeConstructor<CreateElementOpts> = (mem)
return base;
},
get __bytes() {
return mem.u8.subarray(base, base + 64);
return mem.u8.subarray(base, base + 72);
},
get tag(): WasmStringSlice {
return $tag || ($tag = new WasmStringSlice(mem, base, true));
Expand Down Expand Up @@ -1109,13 +1120,115 @@ export const $CreateElementOpts: WasmTypeConstructor<CreateElementOpts> = (mem)
const addr = mem.u32[(base + 56) >>> 2];
const inst = $CreateElementOpts(mem);
const slice: CreateElementOpts[] = [];
for(let i = 0; i < len; i++) slice.push(inst.instance(addr + i * 8));
for(let i = 0; i < len; i++) slice.push(inst.instance(addr + i * 72));
return slice;
},
get attribs(): Attrib[] {
const len = mem.u32[(base + 68) >>> 2];
const addr = mem.u32[(base + 64) >>> 2];
const inst = $Attrib(mem);
const slice: Attrib[] = [];
for(let i = 0; i < len; i++) slice.push(inst.instance(addr + i * 24));
return slice;
},
};
}
});

export interface Attrib extends WasmTypeBase {
name: WasmStringSlice;
value: AttribValue;
kind: AttribType;
}

export const $Attrib: WasmTypeConstructor<Attrib> = (mem) => ({
get align() {
return 8;
},
get size() {
return 24;
},
instance: (base) => {
let $name: WasmStringSlice | null = null;
return {
get __base() {
return base;
},
get __bytes() {
return mem.u8.subarray(base, base + 24);
},
get name(): WasmStringSlice {
return $name || ($name = new WasmStringSlice(mem, base, true));
},
get value(): AttribValue {
return $AttribValue(mem).instance((base + 8));
},
set value(x: AttribValue) {
mem.u8.set(x.__bytes, (base + 8));
},
get kind(): AttribType {
return mem.u8[(base + 16)];
},
set kind(x: AttribType) {
mem.u8[(base + 16)] = x;
},
};
}
});

export interface AttribValue extends WasmTypeBase {
str: WasmStringSlice;
/**
* WASM type: f64
*/
num: number;
/**
* WASM type: u8
*/
flag: number;
}

export const $AttribValue: WasmTypeConstructor<AttribValue> = (mem) => ({
get align() {
return 8;
},
get size() {
return 8;
},
instance: (base) => {
let $str: WasmStringSlice | null = null;
return {
get __base() {
return base;
},
get __bytes() {
return mem.u8.subarray(base, base + 8);
},
get str(): WasmStringSlice {
return $str || ($str = new WasmStringSlice(mem, base, true));
},
get num(): number {
return mem.f64[base >>> 3];
},
set num(x: number) {
mem.f64[base >>> 3] = x;
},
get flag(): number {
return mem.u8[base];
},
set flag(x: number) {
mem.u8[base] = x;
},
};
}
});

export enum AttribType {
STR,
NUM,
FLAG,
}

export interface CreateCanvasOpts extends WasmTypeBase {
/**
* Canvas width (in CSS pixels)
Expand Down
56 changes: 53 additions & 3 deletions packages/wasm-api-dom/src/typedefs.json
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,12 @@
"name": "target",
"type": "i32",
"doc": [
"Target element ID, positive if a known element, otherwise:",
"Target element ID, > 1 if a known (WASM created) element, otherwise:",
"",
"- 0: document.body",
"- -2: = unknown",
"- -1: window",
"- -2: = unknown"
"- 0: document.head",
"- 1: document.body"
]
},
{
Expand All @@ -527,6 +528,7 @@
"doc": [
"Event details / payload. Currently, only the following event types have a defined body:",
"",
"- drag",
"- input",
"- key",
"- mouse",
Expand Down Expand Up @@ -590,10 +592,58 @@
"type": "CreateElementOpts",
"tag": "slice",
"const": true,
"doc": "Optional slice of child element specs, which will be automatically attached as children to this element (their `parent` ID will be ignored)",
"default": { "zig": "&.{}" }
},
{
"name": "attribs",
"type": "Attrib",
"tag": "slice",
"const": true,
"doc": "Optional slice of attribute definitions for this element. Also see provided `Attrib` factory fns for convenience.",
"default": { "zig": "&.{}" }
}
]
},
{
"name": "Attrib",
"type": "struct",
"fields": [
{ "name": "name", "type": "string" },
{ "name": "value", "type": "AttribValue" },
{ "name": "kind", "type": "AttribType" }
],
"body": {
"zig": [
"pub fn string(name: []const u8, val: []const u8) Attrib {",
"return Attrib{ .name = name, .kind = .str, .value = .{ .str = val } };",
"}",
"",
"pub fn number(name: []const u8, val: f64) Attrib {",
"return Attrib{ .name = name, .kind = .num, .value = .{ .num = val } };",
"}",
"",
"pub fn flag(name: []const u8, val: bool) Attrib {",
"return Attrib{ .name = name, .kind = .flag, .value = .{ .flag = if (val) 1 else 0 } };",
"}"
]
}
},
{
"name": "AttribValue",
"type": "union",
"fields": [
{ "name": "str", "type": "string" },
{ "name": "num", "type": "f64" },
{ "name": "flag", "type": "u8" }
]
},
{
"name": "AttribType",
"type": "enum",
"tag": "u8",
"values": ["str", "num", "flag"]
},
{
"name": "CreateCanvasOpts",
"type": "struct",
Expand Down
48 changes: 43 additions & 5 deletions packages/wasm-api-dom/zig/api.zig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Generated by @thi.ng/wasm-api at 2022-10-30T07:52:41.299Z - DO NOT EDIT!
//! Generated by @thi.ng/wasm-api at 2022-11-01T11:56:07.336Z - DO NOT EDIT!

const std = @import("std");

Expand Down Expand Up @@ -204,15 +204,17 @@ pub const EventBody = union {

pub const Event = struct {
id: EventType,
/// Target element ID, positive if a known element, otherwise:
/// Target element ID, > 1 if a known (WASM created) element, otherwise:
///
/// - 0: document.body
/// - -1: window
/// - -2: = unknown
/// - -1: window
/// - 0: document.head
/// - 1: document.body
target: i32,
/// Event details / payload. Currently, only the following event types have a
/// defined body:
///
/// - drag
/// - input
/// - key
/// - mouse
Expand Down Expand Up @@ -241,7 +243,43 @@ pub const CreateElementOpts = struct {
parent: i32 = -1,
/// Insertion index for new element or -1 to append (default)
index: i32 = -1,
children: []const CreateElementOpts = &.{},
/// Optional slice of child element specs, which will be automatically attached
/// as children to this element (their `parent` ID will be ignored)
children: []const CreateElementOpts = &.{},
/// Optional slice of attribute definitions for this element. Also see provided
/// `Attrib` factory fns for convenience.
attribs: []const Attrib = &.{},
};

pub const Attrib = struct {
name: []const u8,
value: AttribValue,
kind: AttribType,

pub fn string(name: []const u8, val: []const u8) Attrib {
return Attrib{ .name = name, .kind = .str, .value = .{ .str = val } };
}

pub fn number(name: []const u8, val: f64) Attrib {
return Attrib{ .name = name, .kind = .num, .value = .{ .num = val } };
}

pub fn flag(name: []const u8, val: bool) Attrib {
return Attrib{ .name = name, .kind = .flag, .value = .{ .flag = if (val) 1 else 0 } };
}

};

pub const AttribValue = union {
str: []const u8,
num: f64,
flag: u8,
};

pub const AttribType = enum(u8) {
str,
num,
flag,
};

pub const CreateCanvasOpts = struct {
Expand Down

0 comments on commit 0e69c47

Please sign in to comment.