id-dom 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADDITIONAL_TERMS.md +122 -0
- package/LICENSE +694 -285
- package/README.md +295 -296
- package/dist/index.cjs +56 -16
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +56 -16
- package/dist/index.js.map +3 -3
- package/dist/index.min.js +1 -1
- package/package.json +5 -3
- package/robots.txt +79 -0
package/README.md
CHANGED
|
@@ -1,296 +1,295 @@
|
|
|
1
|
-
# id-dom
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/id-dom)
|
|
4
|
+
[](https://www.npmjs.com/package/id-dom)
|
|
5
|
+
[](https://bundlephobia.com/package/id-dom)
|
|
6
|
+
[](https://github.com/iWhatty/id-dom/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/iWhatty/id-dom)
|
|
8
|
+
|
|
9
|
+
Deterministic DOM element getters by ID. Typed, tiny, modern. A small utility for grabbing DOM references safely by `id`, with predictable behavior.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Typed getters like `button('saveBtn')`, `input('nameInput')`, `svg('icon')`
|
|
14
|
+
- Strict or optional mode (`throw` vs `null`)
|
|
15
|
+
- Short optional alias via `.opt`
|
|
16
|
+
- Scoped lookups for `document`, `ShadowRoot`, `DocumentFragment`, or an `Element`
|
|
17
|
+
- Centralized error handling with `onError` and optional `warn`
|
|
18
|
+
- Zero dependencies
|
|
19
|
+
|
|
20
|
+
This is deliberately **not** a selector framework. It is a tiny, ID-first primitive for safe DOM wiring.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm add id-dom
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Quick start
|
|
33
|
+
|
|
34
|
+
Two import styles, same root, same behavior. Pick by preference:
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
// Default-object style. Every typed helper lives under one namespace.
|
|
38
|
+
import dom from 'id-dom'
|
|
39
|
+
|
|
40
|
+
const saveBtn = dom.button('saveBtn')
|
|
41
|
+
saveBtn.addEventListener('click', save)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// Named-import style, added in 0.0.5. Makes the dependency surface explicit
|
|
46
|
+
// in the import declaration. Tree-shaken identically by modern bundlers
|
|
47
|
+
// (esbuild, vite, rollup, webpack 5) since the package ships
|
|
48
|
+
// `sideEffects: false`.
|
|
49
|
+
import { button, input, div } from 'id-dom'
|
|
50
|
+
|
|
51
|
+
const saveBtn = button('saveBtn')
|
|
52
|
+
const email = input('email')
|
|
53
|
+
const panel = div('mainPanel')
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Optional access never throws for missing or wrong-type elements:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const debug = dom.div.optional('debugPanel') // default-object style
|
|
60
|
+
debug?.append('hello')
|
|
61
|
+
|
|
62
|
+
import { canvas } from 'id-dom'
|
|
63
|
+
const maybeCanvas = canvas.opt('game') // named style
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
### Default export: `dom`
|
|
71
|
+
|
|
72
|
+
The default export is a scoped instance using `document` (when available) with **strict** behavior:
|
|
73
|
+
|
|
74
|
+
- missing element → **throws**
|
|
75
|
+
- wrong type or wrong tag → **throws**
|
|
76
|
+
- invalid input → **throws**
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import dom from 'id-dom'
|
|
80
|
+
|
|
81
|
+
const name = dom.input('nameInput')
|
|
82
|
+
const submit = dom.button('submitBtn')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `createDom(root, config?)`
|
|
86
|
+
|
|
87
|
+
Create a scoped instance that searches within a specific root:
|
|
88
|
+
|
|
89
|
+
- `document` → uses `getElementById`
|
|
90
|
+
- `ShadowRoot`, `DocumentFragment`, or `Element` → uses `querySelector(#id)` fallback
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import { createDom } from 'id-dom'
|
|
94
|
+
|
|
95
|
+
const d = createDom(document, { mode: 'null', warn: true })
|
|
96
|
+
const sidebar = d.div('sidebar')
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Config:**
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
type DomMode = 'throw' | 'null'
|
|
103
|
+
|
|
104
|
+
{
|
|
105
|
+
mode?: DomMode
|
|
106
|
+
warn?: boolean
|
|
107
|
+
onError?: (err: Error, ctx: any) => void
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `byId(id, Type, config?)`
|
|
112
|
+
|
|
113
|
+
Generic typed lookup:
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
import { byId } from 'id-dom'
|
|
117
|
+
|
|
118
|
+
const btn = byId('saveBtn', HTMLButtonElement)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Optional variants:
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
const maybeBtn = byId.optional('saveBtn', HTMLButtonElement)
|
|
125
|
+
const maybeBtn2 = byId.opt('saveBtn', HTMLButtonElement)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Behavior:
|
|
129
|
+
|
|
130
|
+
- valid match → returns the element
|
|
131
|
+
- missing element → throws or returns `null`
|
|
132
|
+
- wrong type → throws or returns `null`
|
|
133
|
+
- invalid `id` → throws or returns `null`
|
|
134
|
+
- invalid `Type` → throws or returns `null`
|
|
135
|
+
|
|
136
|
+
### `tag(id, tagName, config?)`
|
|
137
|
+
|
|
138
|
+
Tag-based validation when constructor checks are not the right fit:
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { tag } from 'id-dom'
|
|
142
|
+
|
|
143
|
+
const main = tag('appMain', 'main')
|
|
144
|
+
const icon = tag('icon', 'svg', { root: container })
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Optional variants:
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
const maybeMain = tag.optional('appMain', 'main')
|
|
151
|
+
const maybeMain2 = tag.opt('appMain', 'main')
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Behavior:
|
|
155
|
+
|
|
156
|
+
- valid tag match → returns the element
|
|
157
|
+
- missing element → throws or returns `null`
|
|
158
|
+
- wrong tag → throws or returns `null`
|
|
159
|
+
- invalid `id` → throws or returns `null`
|
|
160
|
+
- invalid `tagName` → throws or returns `null`
|
|
161
|
+
|
|
162
|
+
### Built-in getters
|
|
163
|
+
|
|
164
|
+
Typed getters available on `dom` and on any `createDom()` instance:
|
|
165
|
+
|
|
166
|
+
- `el(id)` → `HTMLElement`
|
|
167
|
+
- `input(id)` → `HTMLInputElement`
|
|
168
|
+
- `button(id)` → `HTMLButtonElement`
|
|
169
|
+
- `textarea(id)` → `HTMLTextAreaElement`
|
|
170
|
+
- `select(id)` → `HTMLSelectElement`
|
|
171
|
+
- `form(id)` → `HTMLFormElement`
|
|
172
|
+
- `div(id)` → `HTMLDivElement`
|
|
173
|
+
- `span(id)` → `HTMLSpanElement`
|
|
174
|
+
- `label(id)` → `HTMLLabelElement`
|
|
175
|
+
- `canvas(id)` → `HTMLCanvasElement`
|
|
176
|
+
- `template(id)` → `HTMLTemplateElement`
|
|
177
|
+
- `svg(id)` → `SVGSVGElement`
|
|
178
|
+
- `body(id)` → `HTMLBodyElement`
|
|
179
|
+
|
|
180
|
+
Each getter also has `.optional` and `.opt` variants:
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
dom.canvas.optional('game')
|
|
184
|
+
dom.canvas.opt('game')
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Common tag helpers:
|
|
188
|
+
|
|
189
|
+
- `main(id)` → validates `<main>`
|
|
190
|
+
- `section(id)` → validates `<section>`
|
|
191
|
+
- `small(id)` → validates `<small>`
|
|
192
|
+
|
|
193
|
+
Each also supports `.optional` and `.opt`.
|
|
194
|
+
|
|
195
|
+
### Error handling
|
|
196
|
+
|
|
197
|
+
**Throwing mode:**
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
import dom from 'id-dom'
|
|
201
|
+
|
|
202
|
+
dom.button('missing') // throws
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**Null-returning mode:**
|
|
206
|
+
|
|
207
|
+
```js
|
|
208
|
+
import { createDom } from 'id-dom'
|
|
209
|
+
|
|
210
|
+
const d = createDom(document, { mode: 'null' })
|
|
211
|
+
d.button('missing') // null
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Central reporting:**
|
|
215
|
+
|
|
216
|
+
```js
|
|
217
|
+
const d = createDom(document, {
|
|
218
|
+
mode: 'null',
|
|
219
|
+
onError: (err, ctx) => {
|
|
220
|
+
// sendToSentry({ err, ctx })
|
|
221
|
+
},
|
|
222
|
+
})
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Enable console warnings too:
|
|
226
|
+
|
|
227
|
+
```js
|
|
228
|
+
createDom(document, { mode: 'null', warn: true })
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Notes
|
|
234
|
+
|
|
235
|
+
### Why id-first?
|
|
236
|
+
|
|
237
|
+
Using `getElementById` is fast, unambiguous, and easy to reason about. With typed getters, you immediately know whether you got a `HTMLButtonElement`, `HTMLInputElement`, `SVGSVGElement`, and so on.
|
|
238
|
+
|
|
239
|
+
When scoped roots do not support `getElementById`, id-dom falls back to `querySelector(#id)` and safely escapes edge-case IDs.
|
|
240
|
+
|
|
241
|
+
### Bundle-size note
|
|
242
|
+
|
|
243
|
+
The shared lookup machinery (validation, CSS-escape fallback, error policy, root resolution) is the bulk of the package, roughly 1.9 KB gzipped in a modern bundler. Importing 4 helpers vs 1 vs the full default object lands in the same ballpark. The named-import style is recommended for readability and explicit-surface clarity, not for size.
|
|
244
|
+
|
|
245
|
+
### Scoped roots
|
|
246
|
+
|
|
247
|
+
**Shadow DOM:**
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
import { createDom } from 'id-dom'
|
|
251
|
+
|
|
252
|
+
const host = document.querySelector('#widget')
|
|
253
|
+
const shadow = host.attachShadow({ mode: 'open' })
|
|
254
|
+
shadow.innerHTML = `<button id="shadowBtn">Click</button>`
|
|
255
|
+
|
|
256
|
+
const d = createDom(shadow)
|
|
257
|
+
const btn = d.button('shadowBtn')
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
**Element root:**
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
const container = document.querySelector('#settings-panel')
|
|
264
|
+
const d = createDom(container)
|
|
265
|
+
const input = d.input('emailInput')
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**SVG in scoped roots:**
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
const container = document.querySelector('#icons')
|
|
272
|
+
const d = createDom(container)
|
|
273
|
+
const icon = d.svg('logoMark')
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Misc
|
|
277
|
+
|
|
278
|
+
- `el(id)` is specifically for `HTMLElement`, not every possible DOM `Element`.
|
|
279
|
+
- `body(id)` looks up a `<body>` **by ID**. This library stays ID-first on purpose.
|
|
280
|
+
- `tag()` can validate non-HTML tags too, such as `svg`, when used against supported scoped roots.
|
|
281
|
+
|
|
282
|
+
### Browser support
|
|
283
|
+
|
|
284
|
+
Modern browsers supporting:
|
|
285
|
+
|
|
286
|
+
- `getElementById`
|
|
287
|
+
- `querySelector`
|
|
288
|
+
|
|
289
|
+
`CSS.escape` is used when available. A safe internal fallback is included for environments such as some jsdom builds where it may be missing.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
Licensed under AGPL-3.0 with WATT3D Additional Terms. See [LICENSE](./LICENSE) and [ADDITIONAL_TERMS.md](./ADDITIONAL_TERMS.md). Commercial AI/model-training use requires compliance with those terms or a separate WATT3D license. © WATT3D.
|