id-dom 0.0.5 → 0.0.6
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/dist/index.cjs +13 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +13 -1
- package/dist/index.js.map +2 -2
- package/dist/index.min.js +1 -1
- package/dist/types/id-dom.d.ts +152 -0
- package/package.json +7 -2
package/dist/index.cjs
CHANGED
|
@@ -332,7 +332,19 @@ function createDom(root, config) {
|
|
|
332
332
|
const DEFAULT_BASE = normalizeConfig({ mode: "throw", root: DEFAULT_ROOT });
|
|
333
333
|
const DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: "null" };
|
|
334
334
|
function defaultTypedHelper(Type) {
|
|
335
|
-
|
|
335
|
+
if (Type) return makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL);
|
|
336
|
+
const ssrThrow = (
|
|
337
|
+
/** @type {any} */
|
|
338
|
+
(function ssrUnavailable() {
|
|
339
|
+
throw new Error(
|
|
340
|
+
"id-dom: typed-element helper requires a DOM. The corresponding HTMLElement constructor is undefined in this environment (Node without jsdom, edge runtime, etc.). Use createDom() with a custom root, or guard SSR call sites, or use the .optional variant which returns null in non-DOM environments."
|
|
341
|
+
);
|
|
342
|
+
})
|
|
343
|
+
);
|
|
344
|
+
const ssrNull = () => null;
|
|
345
|
+
ssrThrow.optional = ssrNull;
|
|
346
|
+
ssrThrow.opt = ssrNull;
|
|
347
|
+
return ssrThrow;
|
|
336
348
|
}
|
|
337
349
|
function defaultTagHelper(tagName) {
|
|
338
350
|
return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/id-dom.js"],
|
|
4
|
-
"sourcesContent": ["// id-dom.js\n// id-dom \u2014 deterministic DOM element getters by ID (typed, tiny, modern)\n//\n// Goals:\n// - Prefer getElementById (fast, unambiguous)\n// - Return the correct type or fail predictably\n// - Provide strict + optional variants\n// - Allow app/module-level defaults (throw vs null) without bundler magic\n// - Zero deps, framework-agnostic\n\nconst DEFAULT_ROOT =\n typeof document !== 'undefined' && document ? document : /** @type {any} */ (null)\n\nconst REASON = /** @type {const} */ ({\n INVALID_ID: 'invalid-id',\n INVALID_TYPE: 'invalid-type',\n INVALID_TAG: 'invalid-tag',\n MISSING: 'missing',\n WRONG_TYPE: 'wrong-type',\n WRONG_TAG: 'wrong-tag',\n})\n\nconst SAFE_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/\nconst NEEDS_START_ESCAPE_RE = /^(?:\\d|-\\d)/\n\n/**\n * @typedef {'throw' | 'null'} DomMode\n */\n\n/**\n * @typedef {{\n * mode?: DomMode\n * warn?: boolean\n * onError?: (error: Error, ctx: any) => void\n * root?: any\n * }} DomConfig\n */\n\n// -----------------------------------------------------------------------------\n// Config\n// -----------------------------------------------------------------------------\n\n/**\n * @param {DomConfig | undefined} cfg\n */\nfunction normalizeConfig(cfg) {\n return {\n mode: cfg?.mode ?? 'throw',\n warn: cfg?.warn ?? false,\n onError: typeof cfg?.onError === 'function' ? cfg.onError : null,\n root: cfg?.root ?? DEFAULT_ROOT,\n }\n}\n\n// -----------------------------------------------------------------------------\n// Root / DOM helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is { getElementById(id: string): Element | null }}\n */\nfunction hasGetElementById(v) {\n return !!v && typeof v === 'object' && typeof v.getElementById === 'function'\n}\n\n/**\n * @param {unknown} v\n * @returns {v is { querySelector(sel: string): Element | null }}\n */\nfunction hasQuerySelector(v) {\n return !!v && typeof v === 'object' && typeof v.querySelector === 'function'\n}\n\n/**\n * Minimal CSS.escape fallback for environments where CSS.escape is missing.\n * We only need to safely build `#${id}` selectors.\n *\n * @param {string} id\n * @returns {string}\n */\nfunction cssEscape(id) {\n const s = String(id)\n\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(s)\n }\n\n if (!NEEDS_START_ESCAPE_RE.test(s) && SAFE_ID_RE.test(s)) return s\n\n let out = ''\n for (let i = 0; i < s.length;) {\n const cp = s.codePointAt(i)\n const ch = String.fromCodePoint(cp)\n\n const isAsciiSafe =\n (cp >= 48 && cp <= 57) || // 0-9\n (cp >= 65 && cp <= 90) || // A-Z\n (cp >= 97 && cp <= 122) || // a-z\n cp === 95 || // _\n cp === 45 // -\n\n const next = s.codePointAt(i + 1)\n const startsWithDigit = cp >= 48 && cp <= 57\n const startsWithDashDigit = cp === 45 && s.length > 1 && next >= 48 && next <= 57\n const needsStartEscape = i === 0 && (startsWithDigit || startsWithDashDigit)\n\n if (!needsStartEscape && (isAsciiSafe || cp >= 0x00a0)) {\n out += ch\n } else if (i === 0 && startsWithDashDigit) {\n out += '\\\\-'\n } else {\n out += `\\\\${cp.toString(16).toUpperCase()} `\n }\n\n i += ch.length\n }\n\n return out\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Element}\n */\nfunction isElementNode(v) {\n if (!v || typeof v !== 'object') return false\n if (typeof Element !== 'undefined') return v instanceof Element\n return /** @type {any} */ (v).nodeType === 1\n}\n\n/**\n * Resolve an element by id from a root.\n * Supports:\n * - Document (getElementById)\n * - ShadowRoot / DocumentFragment / Element (querySelector fallback)\n *\n * @param {any} root\n * @param {string} id\n * @returns {Element | null}\n */\nfunction getById(root, id) {\n if (!root) return null\n\n if (hasGetElementById(root)) return root.getElementById(id)\n\n if (hasQuerySelector(root)) {\n const el = root.querySelector(`#${cssEscape(id)}`)\n return isElementNode(el) ? el : null\n }\n\n return null\n}\n\n// -----------------------------------------------------------------------------\n// Validation helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidId(v) {\n return typeof v === 'string' && v.length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidTagName(v) {\n return typeof v === 'string' && v.trim().length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Function}\n */\nfunction isConstructor(v) {\n return typeof v === 'function'\n}\n\n// -----------------------------------------------------------------------------\n// Error / policy helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {string} id\n * @returns {string}\n */\nfunction fmtId(id) {\n return id.startsWith('#') ? id : `#${id}`\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @returns {Error}\n */\nfunction missingElError(id, expected) {\n return new Error(`id-dom: missing ${expected} element ${fmtId(id)}`)\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @param {string} got\n * @returns {Error}\n */\nfunction wrongTypeError(id, expected, got) {\n return new Error(`id-dom: expected ${expected} for ${fmtId(id)}, got ${got}`)\n}\n\n/**\n * @template T\n * @param {Error} err\n * @param {any} ctx\n * @param {ReturnType<typeof normalizeConfig>} cfg\n * @returns {T | null}\n */\nfunction handleLookupError(err, ctx, cfg) {\n try {\n cfg.onError?.(err, ctx)\n } catch {\n // reporting must never break app logic\n }\n\n if (cfg.warn) console.warn(err, ctx)\n\n if (cfg.mode === 'throw') throw err\n return null\n}\n\n/**\n * @param {string} id\n * @param {any} root\n * @param {string} reason\n * @param {object} [extra]\n * @returns {any}\n */\nfunction createCtx(id, root, reason, extra) {\n return {\n id,\n root,\n reason,\n ...(extra || {}),\n }\n}\n\n// -----------------------------------------------------------------------------\n// Internal generic resolver\n// -----------------------------------------------------------------------------\n\n/**\n * @template T\n * @param {DomConfig | undefined} config\n * @param {{\n * id: string,\n * validateInput: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any } | null,\n * onMissing: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * matches: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => boolean,\n * onMismatch: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * }} spec\n * @returns {T | null}\n */\nfunction resolveLookup(config, spec) {\n const cfg = normalizeConfig(config)\n\n const inputFailure = spec.validateInput(cfg)\n if (inputFailure) {\n return handleLookupError(inputFailure.err, inputFailure.ctx, cfg)\n }\n\n const el = getById(cfg.root, spec.id)\n if (!el) {\n const failure = spec.onMissing(cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n if (!spec.matches(el, cfg)) {\n const failure = spec.onMismatch(el, cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n return /** @type {T} */ (el)\n}\n\n// -----------------------------------------------------------------------------\n// Public APIs\n// -----------------------------------------------------------------------------\n\n/**\n * Typed lookup by ID.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nexport function byId(id, Type, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { Type }),\n }\n }\n\n if (!isConstructor(Type)) {\n return {\n err: new Error(`id-dom: invalid Type for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TYPE, { Type }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, Type.name),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { Type }),\n }\n },\n\n matches(el) {\n return el instanceof Type\n },\n\n onMismatch(el, cfg) {\n const got = el?.constructor?.name || typeof el\n return {\n err: wrongTypeError(id, Type.name, got),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TYPE, { Type, got }),\n }\n },\n })\n}\n\n/**\n * Optional typed lookup: always returns T | null.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nbyId.optional = function byIdOptional(id, Type, config) {\n return byId(id, Type, { ...config, mode: 'null' })\n}\n\nbyId.opt = byId.optional\n\n/**\n * Tag-name lookup by element tag.\n * Useful when constructor checks are not the right fit.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\nexport function tag(id, tagName, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { tagName }),\n }\n }\n\n if (!isValidTagName(tagName)) {\n return {\n err: new Error(`id-dom: invalid tagName for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TAG, { tagName }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, `<${tagName}>`),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { tagName }),\n }\n },\n\n matches(el) {\n return String(el.tagName || '').toUpperCase() === String(tagName).toUpperCase()\n },\n\n onMismatch(el, cfg) {\n const expected = String(tagName).toUpperCase()\n const got = String(el.tagName || '').toUpperCase()\n\n return {\n err: wrongTypeError(id, `<${expected.toLowerCase()}>`, `<${got.toLowerCase()}>`),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TAG, { tagName, got }),\n }\n },\n })\n}\n\n/**\n * Optional tag lookup: always returns Element | null.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\ntag.optional = function tagOptional(id, tagName, config) {\n return tag(id, tagName, { ...config, mode: 'null' })\n}\n\ntag.opt = tag.optional\n\n// -----------------------------------------------------------------------------\n// Helper registries\n// -----------------------------------------------------------------------------\n\nconst TYPE_HELPERS = /** @type {Record<string, any>} */ ({\n el: typeof HTMLElement !== 'undefined' ? HTMLElement : null,\n input: typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null,\n button: typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null,\n textarea: typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null,\n select: typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null,\n form: typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null,\n div: typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null,\n span: typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null,\n label: typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null,\n canvas: typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null,\n template: typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null,\n svg: typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null,\n body: typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null,\n})\n\nconst TAG_HELPERS = /** @type {Record<string, string>} */ ({\n main: 'main',\n section: 'section',\n small: 'small',\n})\n\n// -----------------------------------------------------------------------------\n// Helper builders\n// -----------------------------------------------------------------------------\n\n/**\n * @template {Function} T\n * @param {T} fn\n * @param {Function} optionalFn\n * @returns {T & { optional: Function, opt: Function }}\n */\nfunction attachOptional(fn, optionalFn) {\n if (typeof fn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected fn to be a function')\n }\n\n if (typeof optionalFn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected optionalFn to be a function')\n }\n\n fn.optional = optionalFn\n fn.opt = optionalFn\n return fn\n}\n\n/**\n * @param {any} Type\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTypedHelper(Type, base, baseNull) {\n if (!Type) {\n throw new TypeError('id-dom: makeTypedHelper received an invalid Type')\n }\n\n return attachOptional(\n (id) => byId(id, Type, base),\n (id) => byId(id, Type, baseNull)\n )\n}\n\n/**\n * @param {string} tagName\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTagHelper(tagName, base, baseNull) {\n if (!tagName) {\n throw new TypeError('id-dom: makeTagHelper received an invalid tagName')\n }\n\n return attachOptional(\n (id) => tag(id, tagName, base),\n (id) => tag(id, tagName, baseNull)\n )\n}\n// -----------------------------------------------------------------------------\n// Factory\n// -----------------------------------------------------------------------------\n\n/**\n * Factory: scope getters to a specific root + default policy.\n *\n * @param {any} root\n * @param {Omit<DomConfig, 'root'>} [config]\n */\nexport function createDom(root, config) {\n const base = normalizeConfig({ ...config, root })\n const baseNull = { ...base, mode: 'null' }\n\n /** @type {any} */\n const api = {}\n\n api.byId = attachOptional(\n (id, Type) => byId(id, Type, base),\n (id, Type) => byId(id, Type, baseNull)\n )\n\n api.tag = attachOptional(\n (id, name) => tag(id, name, base),\n (id, name) => tag(id, name, baseNull)\n )\n\n for (const [name, Type] of Object.entries(TYPE_HELPERS)) {\n if (!Type) continue\n api[name] = makeTypedHelper(Type, base, baseNull)\n }\n\n for (const [name, tagName] of Object.entries(TAG_HELPERS)) {\n api[name] = makeTagHelper(tagName, base, baseNull)\n }\n\n return api\n}\n\n// -----------------------------------------------------------------------------\n// Default-root config (shared by the default export and the named typed helpers)\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_BASE = normalizeConfig({ mode: 'throw', root: DEFAULT_ROOT })\nconst DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: 'null' }\n\n/**\n * Build a typed helper bound to the default root.\n * Internal \u2014 exposed via the per-helper named exports below.\n *\n * @param {any} Type\n */\nfunction defaultTypedHelper(Type) {\n return Type ? makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL) : null\n}\n\n/**\n * Build a tag-name helper bound to the default root.\n *\n * @param {string} tagName\n */\nfunction defaultTagHelper(tagName) {\n return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL)\n}\n\n// -----------------------------------------------------------------------------\n// Named typed-element helpers (per-helper exports \u2014 tree-shakeable)\n//\n// Each one is a `const` initialized to a tiny closure produced by\n// makeTypedHelper. Modern bundlers (esbuild, rollup, vite) drop the\n// unused ones because the package declares sideEffects: false.\n//\n// SSR-safe: in environments where the corresponding global constructor\n// isn't defined (Node without jsdom, etc.), the export is `null` rather\n// than a thrown construction error.\n// -----------------------------------------------------------------------------\n\nexport const el = defaultTypedHelper(typeof HTMLElement !== 'undefined' ? HTMLElement : null)\nexport const input = defaultTypedHelper(typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null)\nexport const button = defaultTypedHelper(typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null)\nexport const textarea = defaultTypedHelper(typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null)\nexport const select = defaultTypedHelper(typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null)\nexport const form = defaultTypedHelper(typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null)\nexport const div = defaultTypedHelper(typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null)\nexport const span = defaultTypedHelper(typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null)\nexport const label = defaultTypedHelper(typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null)\nexport const canvas = defaultTypedHelper(typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null)\nexport const template = defaultTypedHelper(typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null)\nexport const svg = defaultTypedHelper(typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null)\nexport const body = defaultTypedHelper(typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null)\n\n// Named tag-name helpers (no dedicated constructor)\nexport const main = defaultTagHelper('main')\nexport const section = defaultTagHelper('section')\nexport const small = defaultTagHelper('small')\n\n// -----------------------------------------------------------------------------\n// Default export \u2014 the convenience object aggregating every helper. Use\n// named imports above for tree-shake-friendly bundles; use this default\n// when you want all helpers under one namespace (`dom.button(\u2026)`).\n// -----------------------------------------------------------------------------\n\nconst dom = createDom(DEFAULT_ROOT, { mode: 'throw' })\nexport default dom"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,MAAM,eACF,OAAO,aAAa,eAAe,WAAW;AAAA;AAAA,EAA+B;AAAA;AAEjF,MAAM;AAAA;AAAA,EAA+B;AAAA,IACjC,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,aAAa;AAAA,IACb,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,EACf;AAAA;AAEA,MAAM,aAAa;AACnB,MAAM,wBAAwB;
|
|
4
|
+
"sourcesContent": ["// id-dom.js\n// id-dom \u2014 deterministic DOM element getters by ID (typed, tiny, modern)\n//\n// Goals:\n// - Prefer getElementById (fast, unambiguous)\n// - Return the correct type or fail predictably\n// - Provide strict + optional variants\n// - Allow app/module-level defaults (throw vs null) without bundler magic\n// - Zero deps, framework-agnostic\n\nconst DEFAULT_ROOT =\n typeof document !== 'undefined' && document ? document : /** @type {any} */ (null)\n\nconst REASON = /** @type {const} */ ({\n INVALID_ID: 'invalid-id',\n INVALID_TYPE: 'invalid-type',\n INVALID_TAG: 'invalid-tag',\n MISSING: 'missing',\n WRONG_TYPE: 'wrong-type',\n WRONG_TAG: 'wrong-tag',\n})\n\nconst SAFE_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/\nconst NEEDS_START_ESCAPE_RE = /^(?:\\d|-\\d)/\n\n/**\n * @typedef {'throw' | 'null'} DomMode\n */\n\n/**\n * @typedef {{\n * mode?: DomMode\n * warn?: boolean\n * onError?: (error: Error, ctx: any) => void\n * root?: any\n * }} DomConfig\n */\n\n/**\n * The callable shape exposed by every typed helper (`input`, `button`, \u2026)\n * and tag helper (`main`, `section`, \u2026). The base call follows the helper's\n * default `mode` (typically `'throw'`); `.optional`/`.opt` always return `T | null`.\n *\n * @template T\n * @typedef {((id: string) => T) & {\n * optional: (id: string) => T | null,\n * opt: (id: string) => T | null\n * }} TypedHelper\n */\n\n/**\n * Aggregate API returned by {@link createDom}. Mirrors the named exports\n * but is scoped to the configured root.\n *\n * SSR behavior (0.0.6+): typed-element helpers are *always callable*.\n * In a non-DOM environment where the corresponding global constructor\n * is undefined (Node without jsdom, edge runtimes), the base call\n * throws a clear \"DOM required\" error and `.optional` / `.opt` return\n * `null`. This matches the throw / null semantics consumers already\n * expect from the browser path.\n *\n * @typedef {{\n * byId: (<T extends Element>(id: string, Type: { new (...args: any[]): T }) => T) & {\n * optional: <T extends Element>(id: string, Type: { new (...args: any[]): T }) => T | null,\n * opt: <T extends Element>(id: string, Type: { new (...args: any[]): T }) => T | null\n * },\n * tag: ((id: string, tagName: string) => Element) & {\n * optional: (id: string, tagName: string) => Element | null,\n * opt: (id: string, tagName: string) => Element | null\n * },\n * el: TypedHelper<HTMLElement>,\n * input: TypedHelper<HTMLInputElement>,\n * button: TypedHelper<HTMLButtonElement>,\n * textarea: TypedHelper<HTMLTextAreaElement>,\n * select: TypedHelper<HTMLSelectElement>,\n * form: TypedHelper<HTMLFormElement>,\n * div: TypedHelper<HTMLDivElement>,\n * span: TypedHelper<HTMLSpanElement>,\n * label: TypedHelper<HTMLLabelElement>,\n * canvas: TypedHelper<HTMLCanvasElement>,\n * template: TypedHelper<HTMLTemplateElement>,\n * svg: TypedHelper<SVGSVGElement>,\n * body: TypedHelper<HTMLBodyElement>,\n * main: TypedHelper<HTMLElement>,\n * section: TypedHelper<HTMLElement>,\n * small: TypedHelper<HTMLElement>\n * }} DomApi\n */\n\n// -----------------------------------------------------------------------------\n// Config\n// -----------------------------------------------------------------------------\n\n/**\n * @param {DomConfig | undefined} cfg\n */\nfunction normalizeConfig(cfg) {\n return {\n mode: cfg?.mode ?? 'throw',\n warn: cfg?.warn ?? false,\n onError: typeof cfg?.onError === 'function' ? cfg.onError : null,\n root: cfg?.root ?? DEFAULT_ROOT,\n }\n}\n\n// -----------------------------------------------------------------------------\n// Root / DOM helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is { getElementById(id: string): Element | null }}\n */\nfunction hasGetElementById(v) {\n return !!v && typeof v === 'object' && typeof v.getElementById === 'function'\n}\n\n/**\n * @param {unknown} v\n * @returns {v is { querySelector(sel: string): Element | null }}\n */\nfunction hasQuerySelector(v) {\n return !!v && typeof v === 'object' && typeof v.querySelector === 'function'\n}\n\n/**\n * Minimal CSS.escape fallback for environments where CSS.escape is missing.\n * We only need to safely build `#${id}` selectors.\n *\n * @param {string} id\n * @returns {string}\n */\nfunction cssEscape(id) {\n const s = String(id)\n\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(s)\n }\n\n if (!NEEDS_START_ESCAPE_RE.test(s) && SAFE_ID_RE.test(s)) return s\n\n let out = ''\n for (let i = 0; i < s.length;) {\n const cp = s.codePointAt(i)\n const ch = String.fromCodePoint(cp)\n\n const isAsciiSafe =\n (cp >= 48 && cp <= 57) || // 0-9\n (cp >= 65 && cp <= 90) || // A-Z\n (cp >= 97 && cp <= 122) || // a-z\n cp === 95 || // _\n cp === 45 // -\n\n const next = s.codePointAt(i + 1)\n const startsWithDigit = cp >= 48 && cp <= 57\n const startsWithDashDigit = cp === 45 && s.length > 1 && next >= 48 && next <= 57\n const needsStartEscape = i === 0 && (startsWithDigit || startsWithDashDigit)\n\n if (!needsStartEscape && (isAsciiSafe || cp >= 0x00a0)) {\n out += ch\n } else if (i === 0 && startsWithDashDigit) {\n out += '\\\\-'\n } else {\n out += `\\\\${cp.toString(16).toUpperCase()} `\n }\n\n i += ch.length\n }\n\n return out\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Element}\n */\nfunction isElementNode(v) {\n if (!v || typeof v !== 'object') return false\n if (typeof Element !== 'undefined') return v instanceof Element\n return /** @type {any} */ (v).nodeType === 1\n}\n\n/**\n * Resolve an element by id from a root.\n * Supports:\n * - Document (getElementById)\n * - ShadowRoot / DocumentFragment / Element (querySelector fallback)\n *\n * @param {any} root\n * @param {string} id\n * @returns {Element | null}\n */\nfunction getById(root, id) {\n if (!root) return null\n\n if (hasGetElementById(root)) return root.getElementById(id)\n\n if (hasQuerySelector(root)) {\n const el = root.querySelector(`#${cssEscape(id)}`)\n return isElementNode(el) ? el : null\n }\n\n return null\n}\n\n// -----------------------------------------------------------------------------\n// Validation helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidId(v) {\n return typeof v === 'string' && v.length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidTagName(v) {\n return typeof v === 'string' && v.trim().length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Function}\n */\nfunction isConstructor(v) {\n return typeof v === 'function'\n}\n\n// -----------------------------------------------------------------------------\n// Error / policy helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {string} id\n * @returns {string}\n */\nfunction fmtId(id) {\n return id.startsWith('#') ? id : `#${id}`\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @returns {Error}\n */\nfunction missingElError(id, expected) {\n return new Error(`id-dom: missing ${expected} element ${fmtId(id)}`)\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @param {string} got\n * @returns {Error}\n */\nfunction wrongTypeError(id, expected, got) {\n return new Error(`id-dom: expected ${expected} for ${fmtId(id)}, got ${got}`)\n}\n\n/**\n * @template T\n * @param {Error} err\n * @param {any} ctx\n * @param {ReturnType<typeof normalizeConfig>} cfg\n * @returns {T | null}\n */\nfunction handleLookupError(err, ctx, cfg) {\n try {\n cfg.onError?.(err, ctx)\n } catch {\n // reporting must never break app logic\n }\n\n if (cfg.warn) console.warn(err, ctx)\n\n if (cfg.mode === 'throw') throw err\n return null\n}\n\n/**\n * @param {string} id\n * @param {any} root\n * @param {string} reason\n * @param {object} [extra]\n * @returns {any}\n */\nfunction createCtx(id, root, reason, extra) {\n return {\n id,\n root,\n reason,\n ...(extra || {}),\n }\n}\n\n// -----------------------------------------------------------------------------\n// Internal generic resolver\n// -----------------------------------------------------------------------------\n\n/**\n * @template T\n * @param {DomConfig | undefined} config\n * @param {{\n * id: string,\n * validateInput: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any } | null,\n * onMissing: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * matches: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => boolean,\n * onMismatch: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * }} spec\n * @returns {T | null}\n */\nfunction resolveLookup(config, spec) {\n const cfg = normalizeConfig(config)\n\n const inputFailure = spec.validateInput(cfg)\n if (inputFailure) {\n return handleLookupError(inputFailure.err, inputFailure.ctx, cfg)\n }\n\n const el = getById(cfg.root, spec.id)\n if (!el) {\n const failure = spec.onMissing(cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n if (!spec.matches(el, cfg)) {\n const failure = spec.onMismatch(el, cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n return /** @type {T} */ (el)\n}\n\n// -----------------------------------------------------------------------------\n// Public APIs\n// -----------------------------------------------------------------------------\n\n/**\n * Typed lookup by ID.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nexport function byId(id, Type, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { Type }),\n }\n }\n\n if (!isConstructor(Type)) {\n return {\n err: new Error(`id-dom: invalid Type for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TYPE, { Type }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, Type.name),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { Type }),\n }\n },\n\n matches(el) {\n return el instanceof Type\n },\n\n onMismatch(el, cfg) {\n const got = el?.constructor?.name || typeof el\n return {\n err: wrongTypeError(id, Type.name, got),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TYPE, { Type, got }),\n }\n },\n })\n}\n\n/**\n * Optional typed lookup: always returns T | null.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nbyId.optional = function byIdOptional(id, Type, config) {\n return byId(id, Type, { ...config, mode: 'null' })\n}\n\nbyId.opt = byId.optional\n\n/**\n * Tag-name lookup by element tag.\n * Useful when constructor checks are not the right fit.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\nexport function tag(id, tagName, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { tagName }),\n }\n }\n\n if (!isValidTagName(tagName)) {\n return {\n err: new Error(`id-dom: invalid tagName for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TAG, { tagName }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, `<${tagName}>`),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { tagName }),\n }\n },\n\n matches(el) {\n return String(el.tagName || '').toUpperCase() === String(tagName).toUpperCase()\n },\n\n onMismatch(el, cfg) {\n const expected = String(tagName).toUpperCase()\n const got = String(el.tagName || '').toUpperCase()\n\n return {\n err: wrongTypeError(id, `<${expected.toLowerCase()}>`, `<${got.toLowerCase()}>`),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TAG, { tagName, got }),\n }\n },\n })\n}\n\n/**\n * Optional tag lookup: always returns Element | null.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\ntag.optional = function tagOptional(id, tagName, config) {\n return tag(id, tagName, { ...config, mode: 'null' })\n}\n\ntag.opt = tag.optional\n\n// -----------------------------------------------------------------------------\n// Helper registries\n// -----------------------------------------------------------------------------\n\nconst TYPE_HELPERS = /** @type {Record<string, any>} */ ({\n el: typeof HTMLElement !== 'undefined' ? HTMLElement : null,\n input: typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null,\n button: typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null,\n textarea: typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null,\n select: typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null,\n form: typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null,\n div: typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null,\n span: typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null,\n label: typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null,\n canvas: typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null,\n template: typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null,\n svg: typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null,\n body: typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null,\n})\n\nconst TAG_HELPERS = /** @type {Record<string, string>} */ ({\n main: 'main',\n section: 'section',\n small: 'small',\n})\n\n// -----------------------------------------------------------------------------\n// Helper builders\n// -----------------------------------------------------------------------------\n\n/**\n * @template {Function} T\n * @param {T} fn\n * @param {Function} optionalFn\n * @returns {T & { optional: Function, opt: Function }}\n */\nfunction attachOptional(fn, optionalFn) {\n if (typeof fn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected fn to be a function')\n }\n\n if (typeof optionalFn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected optionalFn to be a function')\n }\n\n fn.optional = optionalFn\n fn.opt = optionalFn\n return fn\n}\n\n/**\n * @param {any} Type\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTypedHelper(Type, base, baseNull) {\n if (!Type) {\n throw new TypeError('id-dom: makeTypedHelper received an invalid Type')\n }\n\n return attachOptional(\n (id) => byId(id, Type, base),\n (id) => byId(id, Type, baseNull)\n )\n}\n\n/**\n * @param {string} tagName\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTagHelper(tagName, base, baseNull) {\n if (!tagName) {\n throw new TypeError('id-dom: makeTagHelper received an invalid tagName')\n }\n\n return attachOptional(\n (id) => tag(id, tagName, base),\n (id) => tag(id, tagName, baseNull)\n )\n}\n// -----------------------------------------------------------------------------\n// Factory\n// -----------------------------------------------------------------------------\n\n/**\n * Factory: scope getters to a specific root + default policy.\n *\n * @param {any} root\n * @param {Omit<DomConfig, 'root'>} [config]\n * @returns {DomApi}\n */\nexport function createDom(root, config) {\n const base = normalizeConfig({ ...config, root })\n const baseNull = { ...base, mode: 'null' }\n\n /** @type {any} */\n const api = {}\n\n api.byId = attachOptional(\n (id, Type) => byId(id, Type, base),\n (id, Type) => byId(id, Type, baseNull)\n )\n\n api.tag = attachOptional(\n (id, name) => tag(id, name, base),\n (id, name) => tag(id, name, baseNull)\n )\n\n for (const [name, Type] of Object.entries(TYPE_HELPERS)) {\n if (!Type) continue\n api[name] = makeTypedHelper(Type, base, baseNull)\n }\n\n for (const [name, tagName] of Object.entries(TAG_HELPERS)) {\n api[name] = makeTagHelper(tagName, base, baseNull)\n }\n\n return api\n}\n\n// -----------------------------------------------------------------------------\n// Default-root config (shared by the default export and the named typed helpers)\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_BASE = normalizeConfig({ mode: 'throw', root: DEFAULT_ROOT })\nconst DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: 'null' }\n\n/**\n * Build a typed helper bound to the default root.\n * Internal \u2014 exposed via the per-helper named exports below.\n *\n * SSR-safe: when `Type` is null (the global constructor isn't defined \u2014\n * Node without jsdom, edge runtimes, etc.) we return an *always-callable*\n * shim rather than the raw `null` that pre-0.0.6 returned. The shim\n * throws a clear \"DOM required\" error on the base call (matches the\n * browser's `mode: 'throw'` semantic) and returns `null` on `.optional` /\n * `.opt` (matches the browser's `mode: 'null'` semantic for opt-in\n * tolerant callers). Closes the historical footgun where SSR consumers\n * hit `TypeError: input is not a function` instead of an actionable\n * message. See host carry-forward #6 for the full context.\n *\n * @param {any} Type\n * @returns {TypedHelper<any>}\n */\nfunction defaultTypedHelper(Type) {\n if (Type) return makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL)\n\n const ssrThrow = /** @type {any} */ (function ssrUnavailable() {\n throw new Error(\n 'id-dom: typed-element helper requires a DOM. The corresponding ' +\n 'HTMLElement constructor is undefined in this environment ' +\n '(Node without jsdom, edge runtime, etc.). Use createDom() with ' +\n 'a custom root, or guard SSR call sites, or use the .optional ' +\n 'variant which returns null in non-DOM environments.'\n )\n })\n const ssrNull = () => null\n ssrThrow.optional = ssrNull\n ssrThrow.opt = ssrNull\n return ssrThrow\n}\n\n/**\n * Build a tag-name helper bound to the default root.\n *\n * @param {string} tagName\n */\nfunction defaultTagHelper(tagName) {\n return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL)\n}\n\n// -----------------------------------------------------------------------------\n// Named typed-element helpers (per-helper exports \u2014 tree-shakeable)\n//\n// Each one is a `const` initialized to a tiny closure produced by\n// makeTypedHelper. Modern bundlers (esbuild, rollup, vite) drop the\n// unused ones because the package declares sideEffects: false.\n//\n// SSR-safe: in environments where the corresponding global constructor\n// isn't defined (Node without jsdom, etc.), the export is `null` rather\n// than a thrown construction error.\n// -----------------------------------------------------------------------------\n\n/** @type {TypedHelper<HTMLElement>} */\nexport const el = defaultTypedHelper(typeof HTMLElement !== 'undefined' ? HTMLElement : null)\n/** @type {TypedHelper<HTMLInputElement>} */\nexport const input = defaultTypedHelper(typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null)\n/** @type {TypedHelper<HTMLButtonElement>} */\nexport const button = defaultTypedHelper(typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null)\n/** @type {TypedHelper<HTMLTextAreaElement>} */\nexport const textarea = defaultTypedHelper(typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null)\n/** @type {TypedHelper<HTMLSelectElement>} */\nexport const select = defaultTypedHelper(typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null)\n/** @type {TypedHelper<HTMLFormElement>} */\nexport const form = defaultTypedHelper(typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null)\n/** @type {TypedHelper<HTMLDivElement>} */\nexport const div = defaultTypedHelper(typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null)\n/** @type {TypedHelper<HTMLSpanElement>} */\nexport const span = defaultTypedHelper(typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null)\n/** @type {TypedHelper<HTMLLabelElement>} */\nexport const label = defaultTypedHelper(typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null)\n/** @type {TypedHelper<HTMLCanvasElement>} */\nexport const canvas = defaultTypedHelper(typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null)\n/** @type {TypedHelper<HTMLTemplateElement>} */\nexport const template = defaultTypedHelper(typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null)\n/** @type {TypedHelper<SVGSVGElement>} */\nexport const svg = defaultTypedHelper(typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null)\n/** @type {TypedHelper<HTMLBodyElement>} */\nexport const body = defaultTypedHelper(typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null)\n\n// Named tag-name helpers (no dedicated constructor \u2014 return base Element)\n/** @type {TypedHelper<HTMLElement>} */\nexport const main = defaultTagHelper('main')\n/** @type {TypedHelper<HTMLElement>} */\nexport const section = defaultTagHelper('section')\n/** @type {TypedHelper<HTMLElement>} */\nexport const small = defaultTagHelper('small')\n\n// -----------------------------------------------------------------------------\n// Default export \u2014 the convenience object aggregating every helper. Use\n// named imports above for tree-shake-friendly bundles; use this default\n// when you want all helpers under one namespace (`dom.button(\u2026)`).\n// -----------------------------------------------------------------------------\n\nconst dom = createDom(DEFAULT_ROOT, { mode: 'throw' })\nexport default dom"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["el"]
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -291,7 +291,19 @@ function createDom(root, config) {
|
|
|
291
291
|
const DEFAULT_BASE = normalizeConfig({ mode: "throw", root: DEFAULT_ROOT });
|
|
292
292
|
const DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: "null" };
|
|
293
293
|
function defaultTypedHelper(Type) {
|
|
294
|
-
|
|
294
|
+
if (Type) return makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL);
|
|
295
|
+
const ssrThrow = (
|
|
296
|
+
/** @type {any} */
|
|
297
|
+
(function ssrUnavailable() {
|
|
298
|
+
throw new Error(
|
|
299
|
+
"id-dom: typed-element helper requires a DOM. The corresponding HTMLElement constructor is undefined in this environment (Node without jsdom, edge runtime, etc.). Use createDom() with a custom root, or guard SSR call sites, or use the .optional variant which returns null in non-DOM environments."
|
|
300
|
+
);
|
|
301
|
+
})
|
|
302
|
+
);
|
|
303
|
+
const ssrNull = () => null;
|
|
304
|
+
ssrThrow.optional = ssrNull;
|
|
305
|
+
ssrThrow.opt = ssrNull;
|
|
306
|
+
return ssrThrow;
|
|
295
307
|
}
|
|
296
308
|
function defaultTagHelper(tagName) {
|
|
297
309
|
return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL);
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/id-dom.js"],
|
|
4
|
-
"sourcesContent": ["// id-dom.js\n// id-dom \u2014 deterministic DOM element getters by ID (typed, tiny, modern)\n//\n// Goals:\n// - Prefer getElementById (fast, unambiguous)\n// - Return the correct type or fail predictably\n// - Provide strict + optional variants\n// - Allow app/module-level defaults (throw vs null) without bundler magic\n// - Zero deps, framework-agnostic\n\nconst DEFAULT_ROOT =\n typeof document !== 'undefined' && document ? document : /** @type {any} */ (null)\n\nconst REASON = /** @type {const} */ ({\n INVALID_ID: 'invalid-id',\n INVALID_TYPE: 'invalid-type',\n INVALID_TAG: 'invalid-tag',\n MISSING: 'missing',\n WRONG_TYPE: 'wrong-type',\n WRONG_TAG: 'wrong-tag',\n})\n\nconst SAFE_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/\nconst NEEDS_START_ESCAPE_RE = /^(?:\\d|-\\d)/\n\n/**\n * @typedef {'throw' | 'null'} DomMode\n */\n\n/**\n * @typedef {{\n * mode?: DomMode\n * warn?: boolean\n * onError?: (error: Error, ctx: any) => void\n * root?: any\n * }} DomConfig\n */\n\n// -----------------------------------------------------------------------------\n// Config\n// -----------------------------------------------------------------------------\n\n/**\n * @param {DomConfig | undefined} cfg\n */\nfunction normalizeConfig(cfg) {\n return {\n mode: cfg?.mode ?? 'throw',\n warn: cfg?.warn ?? false,\n onError: typeof cfg?.onError === 'function' ? cfg.onError : null,\n root: cfg?.root ?? DEFAULT_ROOT,\n }\n}\n\n// -----------------------------------------------------------------------------\n// Root / DOM helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is { getElementById(id: string): Element | null }}\n */\nfunction hasGetElementById(v) {\n return !!v && typeof v === 'object' && typeof v.getElementById === 'function'\n}\n\n/**\n * @param {unknown} v\n * @returns {v is { querySelector(sel: string): Element | null }}\n */\nfunction hasQuerySelector(v) {\n return !!v && typeof v === 'object' && typeof v.querySelector === 'function'\n}\n\n/**\n * Minimal CSS.escape fallback for environments where CSS.escape is missing.\n * We only need to safely build `#${id}` selectors.\n *\n * @param {string} id\n * @returns {string}\n */\nfunction cssEscape(id) {\n const s = String(id)\n\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(s)\n }\n\n if (!NEEDS_START_ESCAPE_RE.test(s) && SAFE_ID_RE.test(s)) return s\n\n let out = ''\n for (let i = 0; i < s.length;) {\n const cp = s.codePointAt(i)\n const ch = String.fromCodePoint(cp)\n\n const isAsciiSafe =\n (cp >= 48 && cp <= 57) || // 0-9\n (cp >= 65 && cp <= 90) || // A-Z\n (cp >= 97 && cp <= 122) || // a-z\n cp === 95 || // _\n cp === 45 // -\n\n const next = s.codePointAt(i + 1)\n const startsWithDigit = cp >= 48 && cp <= 57\n const startsWithDashDigit = cp === 45 && s.length > 1 && next >= 48 && next <= 57\n const needsStartEscape = i === 0 && (startsWithDigit || startsWithDashDigit)\n\n if (!needsStartEscape && (isAsciiSafe || cp >= 0x00a0)) {\n out += ch\n } else if (i === 0 && startsWithDashDigit) {\n out += '\\\\-'\n } else {\n out += `\\\\${cp.toString(16).toUpperCase()} `\n }\n\n i += ch.length\n }\n\n return out\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Element}\n */\nfunction isElementNode(v) {\n if (!v || typeof v !== 'object') return false\n if (typeof Element !== 'undefined') return v instanceof Element\n return /** @type {any} */ (v).nodeType === 1\n}\n\n/**\n * Resolve an element by id from a root.\n * Supports:\n * - Document (getElementById)\n * - ShadowRoot / DocumentFragment / Element (querySelector fallback)\n *\n * @param {any} root\n * @param {string} id\n * @returns {Element | null}\n */\nfunction getById(root, id) {\n if (!root) return null\n\n if (hasGetElementById(root)) return root.getElementById(id)\n\n if (hasQuerySelector(root)) {\n const el = root.querySelector(`#${cssEscape(id)}`)\n return isElementNode(el) ? el : null\n }\n\n return null\n}\n\n// -----------------------------------------------------------------------------\n// Validation helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidId(v) {\n return typeof v === 'string' && v.length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidTagName(v) {\n return typeof v === 'string' && v.trim().length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Function}\n */\nfunction isConstructor(v) {\n return typeof v === 'function'\n}\n\n// -----------------------------------------------------------------------------\n// Error / policy helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {string} id\n * @returns {string}\n */\nfunction fmtId(id) {\n return id.startsWith('#') ? id : `#${id}`\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @returns {Error}\n */\nfunction missingElError(id, expected) {\n return new Error(`id-dom: missing ${expected} element ${fmtId(id)}`)\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @param {string} got\n * @returns {Error}\n */\nfunction wrongTypeError(id, expected, got) {\n return new Error(`id-dom: expected ${expected} for ${fmtId(id)}, got ${got}`)\n}\n\n/**\n * @template T\n * @param {Error} err\n * @param {any} ctx\n * @param {ReturnType<typeof normalizeConfig>} cfg\n * @returns {T | null}\n */\nfunction handleLookupError(err, ctx, cfg) {\n try {\n cfg.onError?.(err, ctx)\n } catch {\n // reporting must never break app logic\n }\n\n if (cfg.warn) console.warn(err, ctx)\n\n if (cfg.mode === 'throw') throw err\n return null\n}\n\n/**\n * @param {string} id\n * @param {any} root\n * @param {string} reason\n * @param {object} [extra]\n * @returns {any}\n */\nfunction createCtx(id, root, reason, extra) {\n return {\n id,\n root,\n reason,\n ...(extra || {}),\n }\n}\n\n// -----------------------------------------------------------------------------\n// Internal generic resolver\n// -----------------------------------------------------------------------------\n\n/**\n * @template T\n * @param {DomConfig | undefined} config\n * @param {{\n * id: string,\n * validateInput: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any } | null,\n * onMissing: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * matches: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => boolean,\n * onMismatch: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * }} spec\n * @returns {T | null}\n */\nfunction resolveLookup(config, spec) {\n const cfg = normalizeConfig(config)\n\n const inputFailure = spec.validateInput(cfg)\n if (inputFailure) {\n return handleLookupError(inputFailure.err, inputFailure.ctx, cfg)\n }\n\n const el = getById(cfg.root, spec.id)\n if (!el) {\n const failure = spec.onMissing(cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n if (!spec.matches(el, cfg)) {\n const failure = spec.onMismatch(el, cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n return /** @type {T} */ (el)\n}\n\n// -----------------------------------------------------------------------------\n// Public APIs\n// -----------------------------------------------------------------------------\n\n/**\n * Typed lookup by ID.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nexport function byId(id, Type, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { Type }),\n }\n }\n\n if (!isConstructor(Type)) {\n return {\n err: new Error(`id-dom: invalid Type for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TYPE, { Type }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, Type.name),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { Type }),\n }\n },\n\n matches(el) {\n return el instanceof Type\n },\n\n onMismatch(el, cfg) {\n const got = el?.constructor?.name || typeof el\n return {\n err: wrongTypeError(id, Type.name, got),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TYPE, { Type, got }),\n }\n },\n })\n}\n\n/**\n * Optional typed lookup: always returns T | null.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nbyId.optional = function byIdOptional(id, Type, config) {\n return byId(id, Type, { ...config, mode: 'null' })\n}\n\nbyId.opt = byId.optional\n\n/**\n * Tag-name lookup by element tag.\n * Useful when constructor checks are not the right fit.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\nexport function tag(id, tagName, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { tagName }),\n }\n }\n\n if (!isValidTagName(tagName)) {\n return {\n err: new Error(`id-dom: invalid tagName for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TAG, { tagName }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, `<${tagName}>`),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { tagName }),\n }\n },\n\n matches(el) {\n return String(el.tagName || '').toUpperCase() === String(tagName).toUpperCase()\n },\n\n onMismatch(el, cfg) {\n const expected = String(tagName).toUpperCase()\n const got = String(el.tagName || '').toUpperCase()\n\n return {\n err: wrongTypeError(id, `<${expected.toLowerCase()}>`, `<${got.toLowerCase()}>`),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TAG, { tagName, got }),\n }\n },\n })\n}\n\n/**\n * Optional tag lookup: always returns Element | null.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\ntag.optional = function tagOptional(id, tagName, config) {\n return tag(id, tagName, { ...config, mode: 'null' })\n}\n\ntag.opt = tag.optional\n\n// -----------------------------------------------------------------------------\n// Helper registries\n// -----------------------------------------------------------------------------\n\nconst TYPE_HELPERS = /** @type {Record<string, any>} */ ({\n el: typeof HTMLElement !== 'undefined' ? HTMLElement : null,\n input: typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null,\n button: typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null,\n textarea: typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null,\n select: typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null,\n form: typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null,\n div: typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null,\n span: typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null,\n label: typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null,\n canvas: typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null,\n template: typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null,\n svg: typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null,\n body: typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null,\n})\n\nconst TAG_HELPERS = /** @type {Record<string, string>} */ ({\n main: 'main',\n section: 'section',\n small: 'small',\n})\n\n// -----------------------------------------------------------------------------\n// Helper builders\n// -----------------------------------------------------------------------------\n\n/**\n * @template {Function} T\n * @param {T} fn\n * @param {Function} optionalFn\n * @returns {T & { optional: Function, opt: Function }}\n */\nfunction attachOptional(fn, optionalFn) {\n if (typeof fn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected fn to be a function')\n }\n\n if (typeof optionalFn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected optionalFn to be a function')\n }\n\n fn.optional = optionalFn\n fn.opt = optionalFn\n return fn\n}\n\n/**\n * @param {any} Type\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTypedHelper(Type, base, baseNull) {\n if (!Type) {\n throw new TypeError('id-dom: makeTypedHelper received an invalid Type')\n }\n\n return attachOptional(\n (id) => byId(id, Type, base),\n (id) => byId(id, Type, baseNull)\n )\n}\n\n/**\n * @param {string} tagName\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTagHelper(tagName, base, baseNull) {\n if (!tagName) {\n throw new TypeError('id-dom: makeTagHelper received an invalid tagName')\n }\n\n return attachOptional(\n (id) => tag(id, tagName, base),\n (id) => tag(id, tagName, baseNull)\n )\n}\n// -----------------------------------------------------------------------------\n// Factory\n// -----------------------------------------------------------------------------\n\n/**\n * Factory: scope getters to a specific root + default policy.\n *\n * @param {any} root\n * @param {Omit<DomConfig, 'root'>} [config]\n */\nexport function createDom(root, config) {\n const base = normalizeConfig({ ...config, root })\n const baseNull = { ...base, mode: 'null' }\n\n /** @type {any} */\n const api = {}\n\n api.byId = attachOptional(\n (id, Type) => byId(id, Type, base),\n (id, Type) => byId(id, Type, baseNull)\n )\n\n api.tag = attachOptional(\n (id, name) => tag(id, name, base),\n (id, name) => tag(id, name, baseNull)\n )\n\n for (const [name, Type] of Object.entries(TYPE_HELPERS)) {\n if (!Type) continue\n api[name] = makeTypedHelper(Type, base, baseNull)\n }\n\n for (const [name, tagName] of Object.entries(TAG_HELPERS)) {\n api[name] = makeTagHelper(tagName, base, baseNull)\n }\n\n return api\n}\n\n// -----------------------------------------------------------------------------\n// Default-root config (shared by the default export and the named typed helpers)\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_BASE = normalizeConfig({ mode: 'throw', root: DEFAULT_ROOT })\nconst DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: 'null' }\n\n/**\n * Build a typed helper bound to the default root.\n * Internal \u2014 exposed via the per-helper named exports below.\n *\n * @param {any} Type\n */\nfunction defaultTypedHelper(Type) {\n return Type ? makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL) : null\n}\n\n/**\n * Build a tag-name helper bound to the default root.\n *\n * @param {string} tagName\n */\nfunction defaultTagHelper(tagName) {\n return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL)\n}\n\n// -----------------------------------------------------------------------------\n// Named typed-element helpers (per-helper exports \u2014 tree-shakeable)\n//\n// Each one is a `const` initialized to a tiny closure produced by\n// makeTypedHelper. Modern bundlers (esbuild, rollup, vite) drop the\n// unused ones because the package declares sideEffects: false.\n//\n// SSR-safe: in environments where the corresponding global constructor\n// isn't defined (Node without jsdom, etc.), the export is `null` rather\n// than a thrown construction error.\n// -----------------------------------------------------------------------------\n\nexport const el = defaultTypedHelper(typeof HTMLElement !== 'undefined' ? HTMLElement : null)\nexport const input = defaultTypedHelper(typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null)\nexport const button = defaultTypedHelper(typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null)\nexport const textarea = defaultTypedHelper(typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null)\nexport const select = defaultTypedHelper(typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null)\nexport const form = defaultTypedHelper(typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null)\nexport const div = defaultTypedHelper(typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null)\nexport const span = defaultTypedHelper(typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null)\nexport const label = defaultTypedHelper(typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null)\nexport const canvas = defaultTypedHelper(typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null)\nexport const template = defaultTypedHelper(typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null)\nexport const svg = defaultTypedHelper(typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null)\nexport const body = defaultTypedHelper(typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null)\n\n// Named tag-name helpers (no dedicated constructor)\nexport const main = defaultTagHelper('main')\nexport const section = defaultTagHelper('section')\nexport const small = defaultTagHelper('small')\n\n// -----------------------------------------------------------------------------\n// Default export \u2014 the convenience object aggregating every helper. Use\n// named imports above for tree-shake-friendly bundles; use this default\n// when you want all helpers under one namespace (`dom.button(\u2026)`).\n// -----------------------------------------------------------------------------\n\nconst dom = createDom(DEFAULT_ROOT, { mode: 'throw' })\nexport default dom"],
|
|
5
|
-
"mappings": "AAUA,MAAM,eACF,OAAO,aAAa,eAAe,WAAW;AAAA;AAAA,EAA+B;AAAA;AAEjF,MAAM;AAAA;AAAA,EAA+B;AAAA,IACjC,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,aAAa;AAAA,IACb,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,EACf;AAAA;AAEA,MAAM,aAAa;AACnB,MAAM,wBAAwB;
|
|
4
|
+
"sourcesContent": ["// id-dom.js\n// id-dom \u2014 deterministic DOM element getters by ID (typed, tiny, modern)\n//\n// Goals:\n// - Prefer getElementById (fast, unambiguous)\n// - Return the correct type or fail predictably\n// - Provide strict + optional variants\n// - Allow app/module-level defaults (throw vs null) without bundler magic\n// - Zero deps, framework-agnostic\n\nconst DEFAULT_ROOT =\n typeof document !== 'undefined' && document ? document : /** @type {any} */ (null)\n\nconst REASON = /** @type {const} */ ({\n INVALID_ID: 'invalid-id',\n INVALID_TYPE: 'invalid-type',\n INVALID_TAG: 'invalid-tag',\n MISSING: 'missing',\n WRONG_TYPE: 'wrong-type',\n WRONG_TAG: 'wrong-tag',\n})\n\nconst SAFE_ID_RE = /^[A-Za-z_][A-Za-z0-9_-]*$/\nconst NEEDS_START_ESCAPE_RE = /^(?:\\d|-\\d)/\n\n/**\n * @typedef {'throw' | 'null'} DomMode\n */\n\n/**\n * @typedef {{\n * mode?: DomMode\n * warn?: boolean\n * onError?: (error: Error, ctx: any) => void\n * root?: any\n * }} DomConfig\n */\n\n/**\n * The callable shape exposed by every typed helper (`input`, `button`, \u2026)\n * and tag helper (`main`, `section`, \u2026). The base call follows the helper's\n * default `mode` (typically `'throw'`); `.optional`/`.opt` always return `T | null`.\n *\n * @template T\n * @typedef {((id: string) => T) & {\n * optional: (id: string) => T | null,\n * opt: (id: string) => T | null\n * }} TypedHelper\n */\n\n/**\n * Aggregate API returned by {@link createDom}. Mirrors the named exports\n * but is scoped to the configured root.\n *\n * SSR behavior (0.0.6+): typed-element helpers are *always callable*.\n * In a non-DOM environment where the corresponding global constructor\n * is undefined (Node without jsdom, edge runtimes), the base call\n * throws a clear \"DOM required\" error and `.optional` / `.opt` return\n * `null`. This matches the throw / null semantics consumers already\n * expect from the browser path.\n *\n * @typedef {{\n * byId: (<T extends Element>(id: string, Type: { new (...args: any[]): T }) => T) & {\n * optional: <T extends Element>(id: string, Type: { new (...args: any[]): T }) => T | null,\n * opt: <T extends Element>(id: string, Type: { new (...args: any[]): T }) => T | null\n * },\n * tag: ((id: string, tagName: string) => Element) & {\n * optional: (id: string, tagName: string) => Element | null,\n * opt: (id: string, tagName: string) => Element | null\n * },\n * el: TypedHelper<HTMLElement>,\n * input: TypedHelper<HTMLInputElement>,\n * button: TypedHelper<HTMLButtonElement>,\n * textarea: TypedHelper<HTMLTextAreaElement>,\n * select: TypedHelper<HTMLSelectElement>,\n * form: TypedHelper<HTMLFormElement>,\n * div: TypedHelper<HTMLDivElement>,\n * span: TypedHelper<HTMLSpanElement>,\n * label: TypedHelper<HTMLLabelElement>,\n * canvas: TypedHelper<HTMLCanvasElement>,\n * template: TypedHelper<HTMLTemplateElement>,\n * svg: TypedHelper<SVGSVGElement>,\n * body: TypedHelper<HTMLBodyElement>,\n * main: TypedHelper<HTMLElement>,\n * section: TypedHelper<HTMLElement>,\n * small: TypedHelper<HTMLElement>\n * }} DomApi\n */\n\n// -----------------------------------------------------------------------------\n// Config\n// -----------------------------------------------------------------------------\n\n/**\n * @param {DomConfig | undefined} cfg\n */\nfunction normalizeConfig(cfg) {\n return {\n mode: cfg?.mode ?? 'throw',\n warn: cfg?.warn ?? false,\n onError: typeof cfg?.onError === 'function' ? cfg.onError : null,\n root: cfg?.root ?? DEFAULT_ROOT,\n }\n}\n\n// -----------------------------------------------------------------------------\n// Root / DOM helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is { getElementById(id: string): Element | null }}\n */\nfunction hasGetElementById(v) {\n return !!v && typeof v === 'object' && typeof v.getElementById === 'function'\n}\n\n/**\n * @param {unknown} v\n * @returns {v is { querySelector(sel: string): Element | null }}\n */\nfunction hasQuerySelector(v) {\n return !!v && typeof v === 'object' && typeof v.querySelector === 'function'\n}\n\n/**\n * Minimal CSS.escape fallback for environments where CSS.escape is missing.\n * We only need to safely build `#${id}` selectors.\n *\n * @param {string} id\n * @returns {string}\n */\nfunction cssEscape(id) {\n const s = String(id)\n\n if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {\n return CSS.escape(s)\n }\n\n if (!NEEDS_START_ESCAPE_RE.test(s) && SAFE_ID_RE.test(s)) return s\n\n let out = ''\n for (let i = 0; i < s.length;) {\n const cp = s.codePointAt(i)\n const ch = String.fromCodePoint(cp)\n\n const isAsciiSafe =\n (cp >= 48 && cp <= 57) || // 0-9\n (cp >= 65 && cp <= 90) || // A-Z\n (cp >= 97 && cp <= 122) || // a-z\n cp === 95 || // _\n cp === 45 // -\n\n const next = s.codePointAt(i + 1)\n const startsWithDigit = cp >= 48 && cp <= 57\n const startsWithDashDigit = cp === 45 && s.length > 1 && next >= 48 && next <= 57\n const needsStartEscape = i === 0 && (startsWithDigit || startsWithDashDigit)\n\n if (!needsStartEscape && (isAsciiSafe || cp >= 0x00a0)) {\n out += ch\n } else if (i === 0 && startsWithDashDigit) {\n out += '\\\\-'\n } else {\n out += `\\\\${cp.toString(16).toUpperCase()} `\n }\n\n i += ch.length\n }\n\n return out\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Element}\n */\nfunction isElementNode(v) {\n if (!v || typeof v !== 'object') return false\n if (typeof Element !== 'undefined') return v instanceof Element\n return /** @type {any} */ (v).nodeType === 1\n}\n\n/**\n * Resolve an element by id from a root.\n * Supports:\n * - Document (getElementById)\n * - ShadowRoot / DocumentFragment / Element (querySelector fallback)\n *\n * @param {any} root\n * @param {string} id\n * @returns {Element | null}\n */\nfunction getById(root, id) {\n if (!root) return null\n\n if (hasGetElementById(root)) return root.getElementById(id)\n\n if (hasQuerySelector(root)) {\n const el = root.querySelector(`#${cssEscape(id)}`)\n return isElementNode(el) ? el : null\n }\n\n return null\n}\n\n// -----------------------------------------------------------------------------\n// Validation helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidId(v) {\n return typeof v === 'string' && v.length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is string}\n */\nfunction isValidTagName(v) {\n return typeof v === 'string' && v.trim().length > 0\n}\n\n/**\n * @param {unknown} v\n * @returns {v is Function}\n */\nfunction isConstructor(v) {\n return typeof v === 'function'\n}\n\n// -----------------------------------------------------------------------------\n// Error / policy helpers\n// -----------------------------------------------------------------------------\n\n/**\n * @param {string} id\n * @returns {string}\n */\nfunction fmtId(id) {\n return id.startsWith('#') ? id : `#${id}`\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @returns {Error}\n */\nfunction missingElError(id, expected) {\n return new Error(`id-dom: missing ${expected} element ${fmtId(id)}`)\n}\n\n/**\n * @param {string} id\n * @param {string} expected\n * @param {string} got\n * @returns {Error}\n */\nfunction wrongTypeError(id, expected, got) {\n return new Error(`id-dom: expected ${expected} for ${fmtId(id)}, got ${got}`)\n}\n\n/**\n * @template T\n * @param {Error} err\n * @param {any} ctx\n * @param {ReturnType<typeof normalizeConfig>} cfg\n * @returns {T | null}\n */\nfunction handleLookupError(err, ctx, cfg) {\n try {\n cfg.onError?.(err, ctx)\n } catch {\n // reporting must never break app logic\n }\n\n if (cfg.warn) console.warn(err, ctx)\n\n if (cfg.mode === 'throw') throw err\n return null\n}\n\n/**\n * @param {string} id\n * @param {any} root\n * @param {string} reason\n * @param {object} [extra]\n * @returns {any}\n */\nfunction createCtx(id, root, reason, extra) {\n return {\n id,\n root,\n reason,\n ...(extra || {}),\n }\n}\n\n// -----------------------------------------------------------------------------\n// Internal generic resolver\n// -----------------------------------------------------------------------------\n\n/**\n * @template T\n * @param {DomConfig | undefined} config\n * @param {{\n * id: string,\n * validateInput: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any } | null,\n * onMissing: (cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * matches: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => boolean,\n * onMismatch: (el: Element, cfg: ReturnType<typeof normalizeConfig>) => { err: Error, ctx: any },\n * }} spec\n * @returns {T | null}\n */\nfunction resolveLookup(config, spec) {\n const cfg = normalizeConfig(config)\n\n const inputFailure = spec.validateInput(cfg)\n if (inputFailure) {\n return handleLookupError(inputFailure.err, inputFailure.ctx, cfg)\n }\n\n const el = getById(cfg.root, spec.id)\n if (!el) {\n const failure = spec.onMissing(cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n if (!spec.matches(el, cfg)) {\n const failure = spec.onMismatch(el, cfg)\n return handleLookupError(failure.err, failure.ctx, cfg)\n }\n\n return /** @type {T} */ (el)\n}\n\n// -----------------------------------------------------------------------------\n// Public APIs\n// -----------------------------------------------------------------------------\n\n/**\n * Typed lookup by ID.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nexport function byId(id, Type, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { Type }),\n }\n }\n\n if (!isConstructor(Type)) {\n return {\n err: new Error(`id-dom: invalid Type for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TYPE, { Type }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, Type.name),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { Type }),\n }\n },\n\n matches(el) {\n return el instanceof Type\n },\n\n onMismatch(el, cfg) {\n const got = el?.constructor?.name || typeof el\n return {\n err: wrongTypeError(id, Type.name, got),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TYPE, { Type, got }),\n }\n },\n })\n}\n\n/**\n * Optional typed lookup: always returns T | null.\n *\n * @template {Element} T\n * @param {string} id\n * @param {{ new (...args: any[]): T }} Type\n * @param {DomConfig} [config]\n * @returns {T | null}\n */\nbyId.optional = function byIdOptional(id, Type, config) {\n return byId(id, Type, { ...config, mode: 'null' })\n}\n\nbyId.opt = byId.optional\n\n/**\n * Tag-name lookup by element tag.\n * Useful when constructor checks are not the right fit.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\nexport function tag(id, tagName, config) {\n return resolveLookup(config, {\n id,\n\n validateInput(cfg) {\n if (!isValidId(id)) {\n return {\n err: new Error('id-dom: invalid id (expected non-empty string)'),\n ctx: createCtx(String(id), cfg.root, REASON.INVALID_ID, { tagName }),\n }\n }\n\n if (!isValidTagName(tagName)) {\n return {\n err: new Error(`id-dom: invalid tagName for ${fmtId(id)}`),\n ctx: createCtx(id, cfg.root, REASON.INVALID_TAG, { tagName }),\n }\n }\n\n return null\n },\n\n onMissing(cfg) {\n return {\n err: missingElError(id, `<${tagName}>`),\n ctx: createCtx(id, cfg.root, REASON.MISSING, { tagName }),\n }\n },\n\n matches(el) {\n return String(el.tagName || '').toUpperCase() === String(tagName).toUpperCase()\n },\n\n onMismatch(el, cfg) {\n const expected = String(tagName).toUpperCase()\n const got = String(el.tagName || '').toUpperCase()\n\n return {\n err: wrongTypeError(id, `<${expected.toLowerCase()}>`, `<${got.toLowerCase()}>`),\n ctx: createCtx(id, cfg.root, REASON.WRONG_TAG, { tagName, got }),\n }\n },\n })\n}\n\n/**\n * Optional tag lookup: always returns Element | null.\n *\n * @param {string} id\n * @param {string} tagName\n * @param {DomConfig} [config]\n * @returns {Element | null}\n */\ntag.optional = function tagOptional(id, tagName, config) {\n return tag(id, tagName, { ...config, mode: 'null' })\n}\n\ntag.opt = tag.optional\n\n// -----------------------------------------------------------------------------\n// Helper registries\n// -----------------------------------------------------------------------------\n\nconst TYPE_HELPERS = /** @type {Record<string, any>} */ ({\n el: typeof HTMLElement !== 'undefined' ? HTMLElement : null,\n input: typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null,\n button: typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null,\n textarea: typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null,\n select: typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null,\n form: typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null,\n div: typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null,\n span: typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null,\n label: typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null,\n canvas: typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null,\n template: typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null,\n svg: typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null,\n body: typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null,\n})\n\nconst TAG_HELPERS = /** @type {Record<string, string>} */ ({\n main: 'main',\n section: 'section',\n small: 'small',\n})\n\n// -----------------------------------------------------------------------------\n// Helper builders\n// -----------------------------------------------------------------------------\n\n/**\n * @template {Function} T\n * @param {T} fn\n * @param {Function} optionalFn\n * @returns {T & { optional: Function, opt: Function }}\n */\nfunction attachOptional(fn, optionalFn) {\n if (typeof fn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected fn to be a function')\n }\n\n if (typeof optionalFn !== 'function') {\n throw new TypeError('id-dom: attachOptional expected optionalFn to be a function')\n }\n\n fn.optional = optionalFn\n fn.opt = optionalFn\n return fn\n}\n\n/**\n * @param {any} Type\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTypedHelper(Type, base, baseNull) {\n if (!Type) {\n throw new TypeError('id-dom: makeTypedHelper received an invalid Type')\n }\n\n return attachOptional(\n (id) => byId(id, Type, base),\n (id) => byId(id, Type, baseNull)\n )\n}\n\n/**\n * @param {string} tagName\n * @param {ReturnType<typeof normalizeConfig>} base\n * @param {ReturnType<typeof normalizeConfig>} baseNull\n */\nfunction makeTagHelper(tagName, base, baseNull) {\n if (!tagName) {\n throw new TypeError('id-dom: makeTagHelper received an invalid tagName')\n }\n\n return attachOptional(\n (id) => tag(id, tagName, base),\n (id) => tag(id, tagName, baseNull)\n )\n}\n// -----------------------------------------------------------------------------\n// Factory\n// -----------------------------------------------------------------------------\n\n/**\n * Factory: scope getters to a specific root + default policy.\n *\n * @param {any} root\n * @param {Omit<DomConfig, 'root'>} [config]\n * @returns {DomApi}\n */\nexport function createDom(root, config) {\n const base = normalizeConfig({ ...config, root })\n const baseNull = { ...base, mode: 'null' }\n\n /** @type {any} */\n const api = {}\n\n api.byId = attachOptional(\n (id, Type) => byId(id, Type, base),\n (id, Type) => byId(id, Type, baseNull)\n )\n\n api.tag = attachOptional(\n (id, name) => tag(id, name, base),\n (id, name) => tag(id, name, baseNull)\n )\n\n for (const [name, Type] of Object.entries(TYPE_HELPERS)) {\n if (!Type) continue\n api[name] = makeTypedHelper(Type, base, baseNull)\n }\n\n for (const [name, tagName] of Object.entries(TAG_HELPERS)) {\n api[name] = makeTagHelper(tagName, base, baseNull)\n }\n\n return api\n}\n\n// -----------------------------------------------------------------------------\n// Default-root config (shared by the default export and the named typed helpers)\n// -----------------------------------------------------------------------------\n\nconst DEFAULT_BASE = normalizeConfig({ mode: 'throw', root: DEFAULT_ROOT })\nconst DEFAULT_BASE_NULL = { ...DEFAULT_BASE, mode: 'null' }\n\n/**\n * Build a typed helper bound to the default root.\n * Internal \u2014 exposed via the per-helper named exports below.\n *\n * SSR-safe: when `Type` is null (the global constructor isn't defined \u2014\n * Node without jsdom, edge runtimes, etc.) we return an *always-callable*\n * shim rather than the raw `null` that pre-0.0.6 returned. The shim\n * throws a clear \"DOM required\" error on the base call (matches the\n * browser's `mode: 'throw'` semantic) and returns `null` on `.optional` /\n * `.opt` (matches the browser's `mode: 'null'` semantic for opt-in\n * tolerant callers). Closes the historical footgun where SSR consumers\n * hit `TypeError: input is not a function` instead of an actionable\n * message. See host carry-forward #6 for the full context.\n *\n * @param {any} Type\n * @returns {TypedHelper<any>}\n */\nfunction defaultTypedHelper(Type) {\n if (Type) return makeTypedHelper(Type, DEFAULT_BASE, DEFAULT_BASE_NULL)\n\n const ssrThrow = /** @type {any} */ (function ssrUnavailable() {\n throw new Error(\n 'id-dom: typed-element helper requires a DOM. The corresponding ' +\n 'HTMLElement constructor is undefined in this environment ' +\n '(Node without jsdom, edge runtime, etc.). Use createDom() with ' +\n 'a custom root, or guard SSR call sites, or use the .optional ' +\n 'variant which returns null in non-DOM environments.'\n )\n })\n const ssrNull = () => null\n ssrThrow.optional = ssrNull\n ssrThrow.opt = ssrNull\n return ssrThrow\n}\n\n/**\n * Build a tag-name helper bound to the default root.\n *\n * @param {string} tagName\n */\nfunction defaultTagHelper(tagName) {\n return makeTagHelper(tagName, DEFAULT_BASE, DEFAULT_BASE_NULL)\n}\n\n// -----------------------------------------------------------------------------\n// Named typed-element helpers (per-helper exports \u2014 tree-shakeable)\n//\n// Each one is a `const` initialized to a tiny closure produced by\n// makeTypedHelper. Modern bundlers (esbuild, rollup, vite) drop the\n// unused ones because the package declares sideEffects: false.\n//\n// SSR-safe: in environments where the corresponding global constructor\n// isn't defined (Node without jsdom, etc.), the export is `null` rather\n// than a thrown construction error.\n// -----------------------------------------------------------------------------\n\n/** @type {TypedHelper<HTMLElement>} */\nexport const el = defaultTypedHelper(typeof HTMLElement !== 'undefined' ? HTMLElement : null)\n/** @type {TypedHelper<HTMLInputElement>} */\nexport const input = defaultTypedHelper(typeof HTMLInputElement !== 'undefined' ? HTMLInputElement : null)\n/** @type {TypedHelper<HTMLButtonElement>} */\nexport const button = defaultTypedHelper(typeof HTMLButtonElement !== 'undefined' ? HTMLButtonElement : null)\n/** @type {TypedHelper<HTMLTextAreaElement>} */\nexport const textarea = defaultTypedHelper(typeof HTMLTextAreaElement !== 'undefined' ? HTMLTextAreaElement : null)\n/** @type {TypedHelper<HTMLSelectElement>} */\nexport const select = defaultTypedHelper(typeof HTMLSelectElement !== 'undefined' ? HTMLSelectElement : null)\n/** @type {TypedHelper<HTMLFormElement>} */\nexport const form = defaultTypedHelper(typeof HTMLFormElement !== 'undefined' ? HTMLFormElement : null)\n/** @type {TypedHelper<HTMLDivElement>} */\nexport const div = defaultTypedHelper(typeof HTMLDivElement !== 'undefined' ? HTMLDivElement : null)\n/** @type {TypedHelper<HTMLSpanElement>} */\nexport const span = defaultTypedHelper(typeof HTMLSpanElement !== 'undefined' ? HTMLSpanElement : null)\n/** @type {TypedHelper<HTMLLabelElement>} */\nexport const label = defaultTypedHelper(typeof HTMLLabelElement !== 'undefined' ? HTMLLabelElement : null)\n/** @type {TypedHelper<HTMLCanvasElement>} */\nexport const canvas = defaultTypedHelper(typeof HTMLCanvasElement !== 'undefined' ? HTMLCanvasElement : null)\n/** @type {TypedHelper<HTMLTemplateElement>} */\nexport const template = defaultTypedHelper(typeof HTMLTemplateElement !== 'undefined' ? HTMLTemplateElement : null)\n/** @type {TypedHelper<SVGSVGElement>} */\nexport const svg = defaultTypedHelper(typeof SVGSVGElement !== 'undefined' ? SVGSVGElement : null)\n/** @type {TypedHelper<HTMLBodyElement>} */\nexport const body = defaultTypedHelper(typeof HTMLBodyElement !== 'undefined' ? HTMLBodyElement : null)\n\n// Named tag-name helpers (no dedicated constructor \u2014 return base Element)\n/** @type {TypedHelper<HTMLElement>} */\nexport const main = defaultTagHelper('main')\n/** @type {TypedHelper<HTMLElement>} */\nexport const section = defaultTagHelper('section')\n/** @type {TypedHelper<HTMLElement>} */\nexport const small = defaultTagHelper('small')\n\n// -----------------------------------------------------------------------------\n// Default export \u2014 the convenience object aggregating every helper. Use\n// named imports above for tree-shake-friendly bundles; use this default\n// when you want all helpers under one namespace (`dom.button(\u2026)`).\n// -----------------------------------------------------------------------------\n\nconst dom = createDom(DEFAULT_ROOT, { mode: 'throw' })\nexport default dom"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["el"]
|
|
7
7
|
}
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const m=typeof document<"u"&&document?document:null,a={INVALID_ID:"invalid-id",INVALID_TYPE:"invalid-type",INVALID_TAG:"invalid-tag",MISSING:"missing",WRONG_TYPE:"wrong-type",WRONG_TAG:"wrong-tag"},
|
|
1
|
+
const m=typeof document<"u"&&document?document:null,a={INVALID_ID:"invalid-id",INVALID_TYPE:"invalid-type",INVALID_TAG:"invalid-tag",MISSING:"missing",WRONG_TYPE:"wrong-type",WRONG_TAG:"wrong-tag"},v=/^[A-Za-z_][A-Za-z0-9_-]*$/,_=/^(?:\d|-\d)/;function E(e){return{mode:e?.mode??"throw",warn:e?.warn??!1,onError:typeof e?.onError=="function"?e.onError:null,root:e?.root??m}}function b(e){return!!e&&typeof e=="object"&&typeof e.getElementById=="function"}function G(e){return!!e&&typeof e=="object"&&typeof e.querySelector=="function"}function C(e){const n=String(e);if(typeof CSS<"u"&&typeof CSS.escape=="function")return CSS.escape(n);if(!_.test(n)&&v.test(n))return n;let o="";for(let t=0;t<n.length;){const r=n.codePointAt(t),l=String.fromCodePoint(r),i=r>=48&&r<=57||r>=65&&r<=90||r>=97&&r<=122||r===95||r===45,M=n.codePointAt(t+1),D=r>=48&&r<=57,H=r===45&&n.length>1&&M>=48&&M<=57;!(t===0&&(D||H))&&(i||r>=160)?o+=l:t===0&&H?o+="\\-":o+=`\\${r.toString(16).toUpperCase()} `,t+=l.length}return o}function N(e){return!e||typeof e!="object"?!1:typeof Element<"u"?e instanceof Element:e.nodeType===1}function V(e,n){if(!e)return null;if(b(e))return e.getElementById(n);if(G(e)){const o=e.querySelector(`#${C(n)}`);return N(o)?o:null}return null}function S(e){return typeof e=="string"&&e.length>0}function O(e){return typeof e=="string"&&e.trim().length>0}function B(e){return typeof e=="function"}function d(e){return e.startsWith("#")?e:`#${e}`}function x(e,n){return new Error(`id-dom: missing ${n} element ${d(e)}`)}function h(e,n,o){return new Error(`id-dom: expected ${n} for ${d(e)}, got ${o}`)}function T(e,n,o){try{o.onError?.(e,n)}catch{}if(o.warn&&console.warn(e,n),o.mode==="throw")throw e;return null}function s(e,n,o,t){return{id:e,root:n,reason:o,...t||{}}}function I(e,n){const o=E(e),t=n.validateInput(o);if(t)return T(t.err,t.ctx,o);const r=V(o.root,n.id);if(!r){const l=n.onMissing(o);return T(l.err,l.ctx,o)}if(!n.matches(r,o)){const l=n.onMismatch(r,o);return T(l.err,l.ctx,o)}return r}function c(e,n,o){return I(o,{id:e,validateInput(t){return S(e)?B(n)?null:{err:new Error(`id-dom: invalid Type for ${d(e)}`),ctx:s(e,t.root,a.INVALID_TYPE,{Type:n})}:{err:new Error("id-dom: invalid id (expected non-empty string)"),ctx:s(String(e),t.root,a.INVALID_ID,{Type:n})}},onMissing(t){return{err:x(e,n.name),ctx:s(e,t.root,a.MISSING,{Type:n})}},matches(t){return t instanceof n},onMismatch(t,r){const l=t?.constructor?.name||typeof t;return{err:h(e,n.name,l),ctx:s(e,r.root,a.WRONG_TYPE,{Type:n,got:l})}}})}c.optional=function(n,o,t){return c(n,o,{...t,mode:"null"})},c.opt=c.optional;function f(e,n,o){return I(o,{id:e,validateInput(t){return S(e)?O(n)?null:{err:new Error(`id-dom: invalid tagName for ${d(e)}`),ctx:s(e,t.root,a.INVALID_TAG,{tagName:n})}:{err:new Error("id-dom: invalid id (expected non-empty string)"),ctx:s(String(e),t.root,a.INVALID_ID,{tagName:n})}},onMissing(t){return{err:x(e,`<${n}>`),ctx:s(e,t.root,a.MISSING,{tagName:n})}},matches(t){return String(t.tagName||"").toUpperCase()===String(n).toUpperCase()},onMismatch(t,r){const l=String(n).toUpperCase(),i=String(t.tagName||"").toUpperCase();return{err:h(e,`<${l.toLowerCase()}>`,`<${i.toLowerCase()}>`),ctx:s(e,r.root,a.WRONG_TAG,{tagName:n,got:i})}}})}f.optional=function(n,o,t){return f(n,o,{...t,mode:"null"})},f.opt=f.optional;const $={el:typeof HTMLElement<"u"?HTMLElement:null,input:typeof HTMLInputElement<"u"?HTMLInputElement:null,button:typeof HTMLButtonElement<"u"?HTMLButtonElement:null,textarea:typeof HTMLTextAreaElement<"u"?HTMLTextAreaElement:null,select:typeof HTMLSelectElement<"u"?HTMLSelectElement:null,form:typeof HTMLFormElement<"u"?HTMLFormElement:null,div:typeof HTMLDivElement<"u"?HTMLDivElement:null,span:typeof HTMLSpanElement<"u"?HTMLSpanElement:null,label:typeof HTMLLabelElement<"u"?HTMLLabelElement:null,canvas:typeof HTMLCanvasElement<"u"?HTMLCanvasElement:null,template:typeof HTMLTemplateElement<"u"?HTMLTemplateElement:null,svg:typeof SVGSVGElement<"u"?SVGSVGElement:null,body:typeof HTMLBodyElement<"u"?HTMLBodyElement:null},R={main:"main",section:"section",small:"small"};function p(e,n){if(typeof e!="function")throw new TypeError("id-dom: attachOptional expected fn to be a function");if(typeof n!="function")throw new TypeError("id-dom: attachOptional expected optionalFn to be a function");return e.optional=n,e.opt=n,e}function g(e,n,o){if(!e)throw new TypeError("id-dom: makeTypedHelper received an invalid Type");return p(t=>c(t,e,n),t=>c(t,e,o))}function w(e,n,o){if(!e)throw new TypeError("id-dom: makeTagHelper received an invalid tagName");return p(t=>f(t,e,n),t=>f(t,e,o))}function P(e,n){const o=E({...n,root:e}),t={...o,mode:"null"},r={};r.byId=p((l,i)=>c(l,i,o),(l,i)=>c(l,i,t)),r.tag=p((l,i)=>f(l,i,o),(l,i)=>f(l,i,t));for(const[l,i]of Object.entries($))i&&(r[l]=g(i,o,t));for(const[l,i]of Object.entries(R))r[l]=w(i,o,t);return r}const L=E({mode:"throw",root:m}),A={...L,mode:"null"};function u(e){if(e)return g(e,L,A);const n=(function(){throw new Error("id-dom: typed-element helper requires a DOM. The corresponding HTMLElement constructor is undefined in this environment (Node without jsdom, edge runtime, etc.). Use createDom() with a custom root, or guard SSR call sites, or use the .optional variant which returns null in non-DOM environments.")}),o=()=>null;return n.optional=o,n.opt=o,n}function y(e){return w(e,L,A)}const W=u(typeof HTMLElement<"u"?HTMLElement:null),j=u(typeof HTMLInputElement<"u"?HTMLInputElement:null),k=u(typeof HTMLButtonElement<"u"?HTMLButtonElement:null),Y=u(typeof HTMLTextAreaElement<"u"?HTMLTextAreaElement:null),q=u(typeof HTMLSelectElement<"u"?HTMLSelectElement:null),z=u(typeof HTMLFormElement<"u"?HTMLFormElement:null),Z=u(typeof HTMLDivElement<"u"?HTMLDivElement:null),Q=u(typeof HTMLSpanElement<"u"?HTMLSpanElement:null),J=u(typeof HTMLLabelElement<"u"?HTMLLabelElement:null),K=u(typeof HTMLCanvasElement<"u"?HTMLCanvasElement:null),X=u(typeof HTMLTemplateElement<"u"?HTMLTemplateElement:null),ee=u(typeof SVGSVGElement<"u"?SVGSVGElement:null),ne=u(typeof HTMLBodyElement<"u"?HTMLBodyElement:null),te=y("main"),oe=y("section"),re=y("small"),U=P(m,{mode:"throw"});var le=U;export{ne as body,k as button,c as byId,K as canvas,P as createDom,le as default,Z as div,W as el,z as form,j as input,J as label,te as main,oe as section,q as select,re as small,Q as span,ee as svg,f as tag,X as template,Y as textarea};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed lookup by ID.
|
|
3
|
+
*
|
|
4
|
+
* @template {Element} T
|
|
5
|
+
* @param {string} id
|
|
6
|
+
* @param {{ new (...args: any[]): T }} Type
|
|
7
|
+
* @param {DomConfig} [config]
|
|
8
|
+
* @returns {T | null}
|
|
9
|
+
*/
|
|
10
|
+
export function byId<T extends Element>(id: string, Type: {
|
|
11
|
+
new (...args: any[]): T;
|
|
12
|
+
}, config?: DomConfig): T | null;
|
|
13
|
+
export namespace byId {
|
|
14
|
+
/**
|
|
15
|
+
* Optional typed lookup: always returns T | null.
|
|
16
|
+
*
|
|
17
|
+
* @template {Element} T
|
|
18
|
+
* @param {string} id
|
|
19
|
+
* @param {{ new (...args: any[]): T }} Type
|
|
20
|
+
* @param {DomConfig} [config]
|
|
21
|
+
* @returns {T | null}
|
|
22
|
+
*/
|
|
23
|
+
export function optional<T extends Element>(id: string, Type: {
|
|
24
|
+
new (...args: any[]): T;
|
|
25
|
+
}, config?: DomConfig): T | null;
|
|
26
|
+
import opt = optional;
|
|
27
|
+
export { opt };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Tag-name lookup by element tag.
|
|
31
|
+
* Useful when constructor checks are not the right fit.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} id
|
|
34
|
+
* @param {string} tagName
|
|
35
|
+
* @param {DomConfig} [config]
|
|
36
|
+
* @returns {Element | null}
|
|
37
|
+
*/
|
|
38
|
+
export function tag(id: string, tagName: string, config?: DomConfig): Element | null;
|
|
39
|
+
export namespace tag {
|
|
40
|
+
/**
|
|
41
|
+
* Optional tag lookup: always returns Element | null.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} id
|
|
44
|
+
* @param {string} tagName
|
|
45
|
+
* @param {DomConfig} [config]
|
|
46
|
+
* @returns {Element | null}
|
|
47
|
+
*/
|
|
48
|
+
export function optional(id: string, tagName: string, config?: DomConfig): Element | null;
|
|
49
|
+
import opt_1 = optional;
|
|
50
|
+
export { opt_1 as opt };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Factory: scope getters to a specific root + default policy.
|
|
54
|
+
*
|
|
55
|
+
* @param {any} root
|
|
56
|
+
* @param {Omit<DomConfig, 'root'>} [config]
|
|
57
|
+
* @returns {DomApi}
|
|
58
|
+
*/
|
|
59
|
+
export function createDom(root: any, config?: Omit<DomConfig, "root">): DomApi;
|
|
60
|
+
/** @type {TypedHelper<HTMLElement>} */
|
|
61
|
+
export const el: TypedHelper<HTMLElement>;
|
|
62
|
+
/** @type {TypedHelper<HTMLInputElement>} */
|
|
63
|
+
export const input: TypedHelper<HTMLInputElement>;
|
|
64
|
+
/** @type {TypedHelper<HTMLButtonElement>} */
|
|
65
|
+
export const button: TypedHelper<HTMLButtonElement>;
|
|
66
|
+
/** @type {TypedHelper<HTMLTextAreaElement>} */
|
|
67
|
+
export const textarea: TypedHelper<HTMLTextAreaElement>;
|
|
68
|
+
/** @type {TypedHelper<HTMLSelectElement>} */
|
|
69
|
+
export const select: TypedHelper<HTMLSelectElement>;
|
|
70
|
+
/** @type {TypedHelper<HTMLFormElement>} */
|
|
71
|
+
export const form: TypedHelper<HTMLFormElement>;
|
|
72
|
+
/** @type {TypedHelper<HTMLDivElement>} */
|
|
73
|
+
export const div: TypedHelper<HTMLDivElement>;
|
|
74
|
+
/** @type {TypedHelper<HTMLSpanElement>} */
|
|
75
|
+
export const span: TypedHelper<HTMLSpanElement>;
|
|
76
|
+
/** @type {TypedHelper<HTMLLabelElement>} */
|
|
77
|
+
export const label: TypedHelper<HTMLLabelElement>;
|
|
78
|
+
/** @type {TypedHelper<HTMLCanvasElement>} */
|
|
79
|
+
export const canvas: TypedHelper<HTMLCanvasElement>;
|
|
80
|
+
/** @type {TypedHelper<HTMLTemplateElement>} */
|
|
81
|
+
export const template: TypedHelper<HTMLTemplateElement>;
|
|
82
|
+
/** @type {TypedHelper<SVGSVGElement>} */
|
|
83
|
+
export const svg: TypedHelper<SVGSVGElement>;
|
|
84
|
+
/** @type {TypedHelper<HTMLBodyElement>} */
|
|
85
|
+
export const body: TypedHelper<HTMLBodyElement>;
|
|
86
|
+
/** @type {TypedHelper<HTMLElement>} */
|
|
87
|
+
export const main: TypedHelper<HTMLElement>;
|
|
88
|
+
/** @type {TypedHelper<HTMLElement>} */
|
|
89
|
+
export const section: TypedHelper<HTMLElement>;
|
|
90
|
+
/** @type {TypedHelper<HTMLElement>} */
|
|
91
|
+
export const small: TypedHelper<HTMLElement>;
|
|
92
|
+
export default dom;
|
|
93
|
+
export type DomMode = "throw" | "null";
|
|
94
|
+
export type DomConfig = {
|
|
95
|
+
mode?: DomMode;
|
|
96
|
+
warn?: boolean;
|
|
97
|
+
onError?: (error: Error, ctx: any) => void;
|
|
98
|
+
root?: any;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* The callable shape exposed by every typed helper (`input`, `button`, …)
|
|
102
|
+
* and tag helper (`main`, `section`, …). The base call follows the helper's
|
|
103
|
+
* default `mode` (typically `'throw'`); `.optional`/`.opt` always return `T | null`.
|
|
104
|
+
*/
|
|
105
|
+
export type TypedHelper<T> = ((id: string) => T) & {
|
|
106
|
+
optional: (id: string) => T | null;
|
|
107
|
+
opt: (id: string) => T | null;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Aggregate API returned by {@link createDom}. Mirrors the named exports
|
|
111
|
+
* but is scoped to the configured root.
|
|
112
|
+
*
|
|
113
|
+
* SSR behavior (0.0.6+): typed-element helpers are *always callable*.
|
|
114
|
+
* In a non-DOM environment where the corresponding global constructor
|
|
115
|
+
* is undefined (Node without jsdom, edge runtimes), the base call
|
|
116
|
+
* throws a clear "DOM required" error and `.optional` / `.opt` return
|
|
117
|
+
* `null`. This matches the throw / null semantics consumers already
|
|
118
|
+
* expect from the browser path.
|
|
119
|
+
*/
|
|
120
|
+
export type DomApi = {
|
|
121
|
+
byId: (<T extends Element>(id: string, Type: {
|
|
122
|
+
new (...args: any[]): T;
|
|
123
|
+
}) => T) & {
|
|
124
|
+
optional: <T extends Element>(id: string, Type: {
|
|
125
|
+
new (...args: any[]): T;
|
|
126
|
+
}) => T | null;
|
|
127
|
+
opt: <T extends Element>(id: string, Type: {
|
|
128
|
+
new (...args: any[]): T;
|
|
129
|
+
}) => T | null;
|
|
130
|
+
};
|
|
131
|
+
tag: ((id: string, tagName: string) => Element) & {
|
|
132
|
+
optional: (id: string, tagName: string) => Element | null;
|
|
133
|
+
opt: (id: string, tagName: string) => Element | null;
|
|
134
|
+
};
|
|
135
|
+
el: TypedHelper<HTMLElement>;
|
|
136
|
+
input: TypedHelper<HTMLInputElement>;
|
|
137
|
+
button: TypedHelper<HTMLButtonElement>;
|
|
138
|
+
textarea: TypedHelper<HTMLTextAreaElement>;
|
|
139
|
+
select: TypedHelper<HTMLSelectElement>;
|
|
140
|
+
form: TypedHelper<HTMLFormElement>;
|
|
141
|
+
div: TypedHelper<HTMLDivElement>;
|
|
142
|
+
span: TypedHelper<HTMLSpanElement>;
|
|
143
|
+
label: TypedHelper<HTMLLabelElement>;
|
|
144
|
+
canvas: TypedHelper<HTMLCanvasElement>;
|
|
145
|
+
template: TypedHelper<HTMLTemplateElement>;
|
|
146
|
+
svg: TypedHelper<SVGSVGElement>;
|
|
147
|
+
body: TypedHelper<HTMLBodyElement>;
|
|
148
|
+
main: TypedHelper<HTMLElement>;
|
|
149
|
+
section: TypedHelper<HTMLElement>;
|
|
150
|
+
small: TypedHelper<HTMLElement>;
|
|
151
|
+
};
|
|
152
|
+
declare const dom: DomApi;
|
package/package.json
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "id-dom",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Deterministic DOM element getters by ID (typed, tiny, modern).",
|
|
5
5
|
"author": "WATT3D <WATT3D@protonmail.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./dist/index.cjs",
|
|
9
9
|
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/types/id-dom.d.ts",
|
|
10
11
|
"exports": {
|
|
11
12
|
".": {
|
|
13
|
+
"types": "./dist/types/id-dom.d.ts",
|
|
12
14
|
"import": "./dist/index.js",
|
|
13
15
|
"require": "./dist/index.cjs",
|
|
14
16
|
"default": "./dist/index.js"
|
|
15
17
|
},
|
|
16
18
|
"./min": {
|
|
19
|
+
"types": "./dist/types/id-dom.d.ts",
|
|
17
20
|
"import": "./dist/index.min.js",
|
|
18
21
|
"default": "./dist/index.min.js"
|
|
19
22
|
}
|
|
@@ -46,13 +49,15 @@
|
|
|
46
49
|
],
|
|
47
50
|
"scripts": {
|
|
48
51
|
"build": "node build.js",
|
|
49
|
-
"
|
|
52
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
53
|
+
"prepublishOnly": "npm run build && npm run build:types",
|
|
50
54
|
"test": "vitest run --environment jsdom",
|
|
51
55
|
"test:watch": "vitest --environment jsdom"
|
|
52
56
|
},
|
|
53
57
|
"devDependencies": {
|
|
54
58
|
"esbuild": "^0.27.3",
|
|
55
59
|
"jsdom": "^24.0.0",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
56
61
|
"vitest": "^3.1.2"
|
|
57
62
|
},
|
|
58
63
|
"engines": {
|