Skip to content

Commit 34345f4

Browse files
authored
wip: HTMLElementAttributeMap
1 parent ae873f9 commit 34345f4

File tree

2 files changed

+170
-2
lines changed

2 files changed

+170
-2
lines changed

src/tagFactory.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Signal } from "./signal.ts"
2-
import type { Children } from "./types.ts"
2+
import type { Children, HTMLElementAttributeMap } from "./types.ts"
33
import { escapeHTML } from "./utils/escape.ts"
44

55
export const tagFactory = <T extends keyof HTMLElementTagNameMap>(tagName: T) =>
6-
(props: Record<string, string>, ...children: Children): HTMLElementTagNameMap[T] => {
6+
(props: HTMLElementAttributeMap[T], ...children: Children): HTMLElementTagNameMap[T] => {
77
const element = document.createElement(tagName)
88

99
Object.entries(props).forEach(([name, value]) => element.setAttribute(name, value))

src/types.ts

+168
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,171 @@ export type Equals<T> = (before: T, after: T) => boolean
66
// TODO: support all primitive values
77
export type Child = HTMLElement | Signal | string | number
88
export type Children = Array<Child>
9+
10+
// ---------- Utils ----------
11+
// export type AddBooleanString<T extends object> = {
12+
// [K in keyof T]: boolean extends T[K] ? T[K] | "true" | "false" : T[K]
13+
// }
14+
15+
// ---------- HTML ----------
16+
17+
// based on HTML Living Standard (March 6, 2025)
18+
// https://html.spec.whatwg.org/multipage/dom.html#global-attributes
19+
type HTMLElementGlobalAttribute = Partial<{
20+
accesskey: string // TODO: Enumerate all keys?
21+
// anchor: string // Non-standard https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/anchor
22+
autocapitalize: "off" | "sentences" | "none" | "on" | "words" | "characters"
23+
autocorrect: "on" | "" | "off"
24+
autofocus: boolean // boolean attribute https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attribute
25+
class: string // TODO: allow array
26+
contenteditable: boolean | "plaintext-only"
27+
// data-*
28+
dir: "rtl" | "ltr" | "auto"
29+
draggable: boolean
30+
enterkeyhint: "enter" | "done" | "go" | "next" | "previous" | "search" | "send"
31+
/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts */
32+
exportparts: string // CSS Shadow Parts
33+
hidden: "" | "hidden" | "until-found"
34+
id: string
35+
inert: boolean // boolean attribute
36+
inputmode: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search"
37+
is: string // TODO: Extend with type arguments
38+
itemid: string
39+
itemprop: string
40+
itemref: string
41+
itemscope: boolean // boolean attribute
42+
itemtype: string
43+
lang: string // TODO: Enumeration of all language codes?
44+
nonce: string
45+
/** @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/part */
46+
part: string // CSS Shadow Parts
47+
/** @see https://developer.mozilla.org/en-US/docs/Web/API/Popover_API */
48+
popover: "auto" | "" | "manual" | "hint"
49+
slot: string
50+
spellcheck: boolean | ""
51+
style: string // TODO: CSS in JS
52+
tabindex: number
53+
title: string
54+
translate: "yes" | "" | "no"
55+
// virtualkeyboardpolicy: "manual" | "auto" // Non-standard https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/virtualkeyboardpolicy
56+
writingsuggestions: boolean | ""
57+
}>
58+
59+
type HTMLElementAttributeFactory<T extends Record<string, object>> = {
60+
[K in keyof T]: Partial<T[K]> & HTMLElementGlobalAttribute
61+
}
62+
63+
export type HTMLElementAttributeMap = HTMLElementAttributeFactory<{
64+
a: {}
65+
abbr: {}
66+
address: {}
67+
area: {}
68+
article: {}
69+
aside: {}
70+
audio: {}
71+
b: {}
72+
base: {}
73+
bdi: {}
74+
bdo: {}
75+
blockquote: {}
76+
body: {}
77+
br: {}
78+
button: {}
79+
canvas: {}
80+
caption: {}
81+
cite: {}
82+
code: {}
83+
col: {}
84+
colgroup: {}
85+
data: {}
86+
datalist: {}
87+
dd: {}
88+
del: {}
89+
details: {}
90+
dfn: {}
91+
dialog: {}
92+
div: {}
93+
dl: {}
94+
dt: {}
95+
em: {}
96+
embed: {}
97+
fieldset: {}
98+
figcaption: {}
99+
figure: {}
100+
footer: {}
101+
form: {}
102+
h1: {}
103+
h2: {}
104+
h3: {}
105+
h4: {}
106+
h5: {}
107+
h6: {}
108+
head: {}
109+
header: {}
110+
hgroup: {}
111+
hr: {}
112+
html: {}
113+
i: {}
114+
iframe: {}
115+
img: {}
116+
input: {}
117+
ins: {}
118+
kbd: {}
119+
label: {}
120+
legend: {}
121+
li: {}
122+
link: {}
123+
main: {}
124+
map: {}
125+
mark: {}
126+
menu: {}
127+
meta: {}
128+
meter: {}
129+
nav: {}
130+
noscript: {}
131+
object: {}
132+
ol: {}
133+
optgroup: {}
134+
option: {}
135+
output: {}
136+
p: {}
137+
picture: {}
138+
pre: {}
139+
progress: {}
140+
q: {}
141+
rp: {}
142+
rt: {}
143+
ruby: {}
144+
s: {}
145+
samp: {}
146+
script: {}
147+
search: {}
148+
section: {}
149+
select: {}
150+
slot: {}
151+
small: {}
152+
source: {}
153+
span: {}
154+
strong: {}
155+
style: {}
156+
sub: {}
157+
summary: {}
158+
sup: {}
159+
table: {}
160+
tbody: {}
161+
td: {}
162+
template: {}
163+
textarea: {}
164+
tfoot: {}
165+
th: {}
166+
thead: {}
167+
time: {}
168+
title: {}
169+
tr: {}
170+
track: {}
171+
u: {}
172+
ul: {}
173+
var: {}
174+
video: {}
175+
wbr: {}
176+
}>

0 commit comments

Comments
 (0)