klods-js 1.6.0 → 1.8.0

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.d.ts CHANGED
@@ -85,6 +85,7 @@ declare function alert(props?: (AlertProps & KlodsAttrs) | null, children?: Klod
85
85
  declare const prose: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
86
86
  declare const muted: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
87
87
  declare const lead: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
88
+ declare const textCenter: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
88
89
  type TableProps = {
89
90
  striped?: boolean;
90
91
  dense?: boolean;
@@ -95,6 +96,72 @@ declare const tbody: (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsCh
95
96
  declare const tr: (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]) => KlodsNode;
96
97
  declare const th: (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]) => KlodsNode;
97
98
  declare const td: (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]) => KlodsNode;
99
+ declare const form: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
100
+ type FieldProps = {
101
+ /** Label text shown above the control. */
102
+ label: string;
103
+ /** Explicit id for the control. Auto-generated when omitted. */
104
+ id?: string;
105
+ /** Hint text shown below the control. Hidden when the field is invalid. */
106
+ help?: string;
107
+ /** Validation error. When present the field is rendered in its invalid state. */
108
+ error?: string;
109
+ /** Appends a * marker to the label. */
110
+ required?: boolean;
111
+ /** Force invalid state without providing error text. */
112
+ invalid?: boolean;
113
+ };
114
+ /**
115
+ * Opinionated field wrapper. Renders a label, the control, and optional
116
+ * help / error text. Automatically wires `for`, `id`, `aria-describedby`,
117
+ * and `aria-invalid` so you don't have to.
118
+ *
119
+ * Pass a render function that receives the generated (or explicit) `id`:
120
+ * ```ts
121
+ * field({ label: "Email", required: true }, (id) =>
122
+ * input({ id, type: "email" }),
123
+ * )
124
+ * ```
125
+ */
126
+ declare function field(props: FieldProps & KlodsAttrs, renderInput: (id: string) => KlodsNode): KlodsNode;
127
+ type InputProps = {
128
+ type?: "text" | "email" | "password" | "number" | "tel" | "url" | "search" | "date" | "time" | "datetime-local" | "range" | "color" | "file" | "hidden";
129
+ };
130
+ declare function input(props: InputProps & KlodsAttrs): KlodsNode;
131
+ declare function select(attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode;
132
+ declare const option: (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]) => KlodsNode;
133
+ declare const textarea: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
134
+ type CheckboxProps = {
135
+ label: string;
136
+ name?: string;
137
+ value?: string;
138
+ checked?: boolean;
139
+ disabled?: boolean;
140
+ };
141
+ declare function checkbox(props: CheckboxProps & KlodsAttrs): KlodsNode;
142
+ type RadioProps = {
143
+ label: string;
144
+ name?: string;
145
+ value?: string;
146
+ checked?: boolean;
147
+ disabled?: boolean;
148
+ };
149
+ declare function radio(props: RadioProps & KlodsAttrs): KlodsNode;
150
+ type RadioGroupProps = {
151
+ /** Text shown as the group heading (maps to a styled `<p>` with aria-labelledby). */
152
+ legend?: string;
153
+ };
154
+ declare function radioGroup(props: RadioGroupProps & KlodsAttrs, children: KlodsNode[]): KlodsNode;
155
+ type SwitchProps = {
156
+ label: string;
157
+ name?: string;
158
+ value?: string;
159
+ checked?: boolean;
160
+ disabled?: boolean;
161
+ /** Flips the layout: label on the left, track on the right. Ideal for settings panels. */
162
+ reverse?: boolean;
163
+ };
164
+ declare function switchInput(props: SwitchProps & KlodsAttrs): KlodsNode;
98
165
  declare function codeBlock(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode;
99
166
  declare function inlineCode(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode;
100
167
  declare const box: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
@@ -142,4 +209,4 @@ declare function text(value: string | number): KlodsNode;
142
209
  declare const push: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
143
210
  declare const fill: (props?: (Record<never, never> & KlodsAttrs) | null | undefined, children?: KlodsChild | KlodsChild[]) => KlodsNode;
144
211
 
145
- export { type AlertProps, type BadgeProps, type ButtonProps, type CardProps, type ContentProps, type GridProps, type KlodsAttrs, type KlodsChild, KlodsNode, type NavLinkProps, type PageProps, type TableProps, type TocProps, alert, badge, box, builder, button, buttonGroup, card, cardBody, cardFooter, cardTitle, center, classNames, cluster, codeBlock, content, el, fill, footer, grid, header, inlineCode, lead, mergeClasses, muted, nav, navLink, navList, page, prose, push, raw, row, section, sidebar, spread, stack, table, tbody, td, text, th, thead, toc, tocItem, tocLink, tr };
212
+ export { type AlertProps, type BadgeProps, type ButtonProps, type CardProps, type CheckboxProps, type ContentProps, type FieldProps, type GridProps, type InputProps, type KlodsAttrs, type KlodsChild, KlodsNode, type NavLinkProps, type PageProps, type RadioGroupProps, type RadioProps, type SwitchProps, type TableProps, type TocProps, alert, badge, box, builder, button, buttonGroup, card, cardBody, cardFooter, cardTitle, center, checkbox, classNames, cluster, codeBlock, content, el, field, fill, footer, form, grid, header, inlineCode, input, lead, mergeClasses, muted, nav, navLink, navList, option, page, prose, push, radio, radioGroup, raw, row, section, select, sidebar, spread, stack, switchInput, table, tbody, td, text, textCenter, textarea, th, thead, toc, tocItem, tocLink, tr };
package/dist/index.js CHANGED
@@ -27,11 +27,11 @@ function escapeHtml(str) {
27
27
  function escapeAttr(str) {
28
28
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
29
29
  }
30
- function classNames(input) {
31
- if (!input) return "";
32
- if (typeof input === "string") return input.trim();
33
- if (Array.isArray(input)) return input.filter(Boolean).join(" ").trim();
34
- return Object.entries(input).filter(([, v]) => Boolean(v)).map(([k]) => k).join(" ").trim();
30
+ function classNames(input2) {
31
+ if (!input2) return "";
32
+ if (typeof input2 === "string") return input2.trim();
33
+ if (Array.isArray(input2)) return input2.filter(Boolean).join(" ").trim();
34
+ return Object.entries(input2).filter(([, v]) => Boolean(v)).map(([k]) => k).join(" ").trim();
35
35
  }
36
36
  function mergeClasses(...inputs) {
37
37
  return inputs.map((c) => classNames(c)).filter(Boolean).join(" ");
@@ -224,6 +224,7 @@ function alert(props, children) {
224
224
  var prose = builder({ tag: "div", base: "klods-prose" });
225
225
  var muted = builder({ tag: "span", base: "klods-muted" });
226
226
  var lead = builder({ tag: "p", base: "klods-lead" });
227
+ var textCenter = builder({ tag: "div", base: "klods-text-center" });
227
228
  var table = builder({
228
229
  tag: "table",
229
230
  base: "klods-table",
@@ -237,6 +238,193 @@ var tbody = (attrs, children) => el("tbody", attrs ?? {}, children);
237
238
  var tr = (attrs, children) => el("tr", attrs ?? {}, children);
238
239
  var th = (attrs, children) => el("th", attrs ?? {}, children);
239
240
  var td = (attrs, children) => el("td", attrs ?? {}, children);
241
+ function slugId(prefix, text2) {
242
+ const safe = text2 ?? "";
243
+ const slug = safe.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
244
+ if (slug) return `${prefix}-${slug}`;
245
+ let h = 5381;
246
+ for (let i = 0; i < safe.length; i++) h = (h << 5) + h + safe.charCodeAt(i) | 0;
247
+ return `${prefix}-${(h >>> 0).toString(36)}`;
248
+ }
249
+ var form = builder({ tag: "form", base: "klods-form" });
250
+ var FORM_CONTROLS = /* @__PURE__ */ new Set(["input", "select", "textarea"]);
251
+ function patchAriaAttrs(node, attrs) {
252
+ if (FORM_CONTROLS.has(node.tag)) {
253
+ return new KlodsNode(node.tag, { ...node.attrs, ...attrs }, node.children);
254
+ }
255
+ const patchedChildren = node.children.map(
256
+ (child) => child instanceof KlodsNode && FORM_CONTROLS.has(child.tag) ? new KlodsNode(child.tag, { ...child.attrs, ...attrs }, child.children) : child
257
+ );
258
+ return new KlodsNode(node.tag, node.attrs, patchedChildren);
259
+ }
260
+ function field(props, renderInput) {
261
+ const { label: labelText, id: explicitId, help, error, required, invalid, class: extraClass, ...rest } = props;
262
+ const id = explicitId ?? slugId("klods-field", labelText);
263
+ const helpId = help ? `${id}-help` : void 0;
264
+ const errorId = error ? `${id}-error` : void 0;
265
+ const isInvalid = invalid ?? !!error;
266
+ const describedBy = isInvalid ? errorId : helpId;
267
+ const inputNode = renderInput(id);
268
+ const patchedInput = patchAriaAttrs(inputNode, {
269
+ ...describedBy ? { "aria-describedby": describedBy } : {},
270
+ ...isInvalid ? { "aria-invalid": "true" } : {}
271
+ });
272
+ const fieldClass = classNames([
273
+ "klods-field",
274
+ isInvalid ? "klods-field--invalid" : "",
275
+ classNames(extraClass)
276
+ ]);
277
+ const children = [
278
+ el("label", { for: id, class: `klods-label${required ? " klods-label--required" : ""}` }, labelText),
279
+ patchedInput
280
+ ];
281
+ if (help) children.push(el("p", { id: helpId, class: "klods-help" }, help));
282
+ if (error) children.push(el("p", { id: errorId, class: "klods-error", role: "alert" }, error));
283
+ return el("div", { ...rest, class: fieldClass || void 0 }, children);
284
+ }
285
+ function input(props) {
286
+ const { type, class: extraClass, oninput: userOninput, ...rest } = props;
287
+ const cls = (extra) => classNames(["klods-input", extra, classNames(extraClass)]) || void 0;
288
+ const id = rest.id ?? slugId(
289
+ "klods-input",
290
+ rest["aria-label"] ?? rest.placeholder ?? type ?? "field"
291
+ );
292
+ if (type === "range") {
293
+ const initial = rest.value ?? "50";
294
+ return el("span", { class: cls("klods-input--range") }, [
295
+ el("input", {
296
+ type: "range",
297
+ ...rest,
298
+ id,
299
+ oninput: (e) => {
300
+ const inp = e.target;
301
+ inp.closest(".klods-input--range")?.querySelector("output")?.textContent !== void 0 && (inp.closest(".klods-input--range").querySelector("output").textContent = inp.value);
302
+ userOninput?.(e);
303
+ }
304
+ }),
305
+ el("output", { for: id }, initial)
306
+ ]);
307
+ }
308
+ if (type === "color") {
309
+ const initial = rest.value ?? "#000000";
310
+ return el("span", { class: cls("klods-input--color") }, [
311
+ el("input", {
312
+ type: "color",
313
+ ...rest,
314
+ id,
315
+ oninput: (e) => {
316
+ const inp = e.target;
317
+ inp.closest(".klods-input--color")?.querySelector("output")?.textContent !== void 0 && (inp.closest(".klods-input--color").querySelector("output").textContent = inp.value);
318
+ userOninput?.(e);
319
+ }
320
+ }),
321
+ el("output", { for: id }, initial)
322
+ ]);
323
+ }
324
+ return new KlodsNode("input", {
325
+ type,
326
+ ...rest,
327
+ id,
328
+ class: cls("")
329
+ });
330
+ }
331
+ var selectEl = builder({ tag: "select", base: "klods-select" });
332
+ function select(attrs, children) {
333
+ return el("div", { class: "klods-select-wrapper" }, selectEl(attrs, children));
334
+ }
335
+ var option = (attrs, children) => el("option", attrs ?? {}, children);
336
+ var textarea = builder({ tag: "textarea", base: "klods-textarea" });
337
+ function checkbox(props) {
338
+ const {
339
+ label: labelText,
340
+ name,
341
+ value,
342
+ checked,
343
+ disabled,
344
+ required,
345
+ form: form2,
346
+ autofocus,
347
+ class: extraClass,
348
+ ...rest
349
+ } = props;
350
+ const inputAttrs = { type: "checkbox" };
351
+ if (name !== void 0) inputAttrs.name = name;
352
+ if (value !== void 0) inputAttrs.value = value;
353
+ if (checked) inputAttrs.checked = true;
354
+ if (disabled) inputAttrs.disabled = true;
355
+ if (required) inputAttrs.required = true;
356
+ if (form2 !== void 0) inputAttrs.form = form2;
357
+ if (autofocus) inputAttrs.autofocus = true;
358
+ return el(
359
+ "label",
360
+ { ...rest, class: classNames(["klods-checkbox", classNames(extraClass)]) || void 0 },
361
+ [el("input", inputAttrs), el("span", {}, labelText)]
362
+ );
363
+ }
364
+ function radio(props) {
365
+ const {
366
+ label: labelText,
367
+ name,
368
+ value,
369
+ checked,
370
+ disabled,
371
+ required,
372
+ form: form2,
373
+ autofocus,
374
+ class: extraClass,
375
+ ...rest
376
+ } = props;
377
+ const inputAttrs = { type: "radio" };
378
+ if (name !== void 0) inputAttrs.name = name;
379
+ if (value !== void 0) inputAttrs.value = value;
380
+ if (checked) inputAttrs.checked = true;
381
+ if (disabled) inputAttrs.disabled = true;
382
+ if (required) inputAttrs.required = true;
383
+ if (form2 !== void 0) inputAttrs.form = form2;
384
+ if (autofocus) inputAttrs.autofocus = true;
385
+ return el(
386
+ "label",
387
+ { ...rest, class: classNames(["klods-radio", classNames(extraClass)]) || void 0 },
388
+ [el("input", inputAttrs), el("span", {}, labelText)]
389
+ );
390
+ }
391
+ function radioGroup(props, children) {
392
+ const { legend: legendText, class: extraClass, ...rest } = props;
393
+ const legendId = legendText ? slugId("klods-rg", legendText) : void 0;
394
+ const cls = classNames(["klods-field", classNames(extraClass)]) || void 0;
395
+ return el("div", { ...rest, class: cls, role: "group", ...legendId ? { "aria-labelledby": legendId } : {} }, [
396
+ legendText ? el("p", { id: legendId, class: "klods-label" }, legendText) : null,
397
+ ...children
398
+ ]);
399
+ }
400
+ function switchInput(props) {
401
+ const { label: labelText, name, value, checked, disabled, reverse, class: extraClass, ...rest } = props;
402
+ const inputAttrs = {
403
+ type: "checkbox",
404
+ class: "klods-switch__input",
405
+ role: "switch"
406
+ };
407
+ if (name !== void 0) inputAttrs.name = name;
408
+ if (value !== void 0) inputAttrs.value = value;
409
+ if (checked) inputAttrs.checked = true;
410
+ if (disabled) inputAttrs.disabled = true;
411
+ return el(
412
+ "label",
413
+ {
414
+ ...rest,
415
+ class: classNames([
416
+ "klods-switch",
417
+ reverse ? "klods-switch--reverse" : "",
418
+ classNames(extraClass)
419
+ ]) || void 0
420
+ },
421
+ [
422
+ el("input", inputAttrs),
423
+ el("span", { class: "klods-switch__track" }),
424
+ el("span", { class: "klods-switch__label" }, labelText)
425
+ ]
426
+ );
427
+ }
240
428
  function codeBlock(attrs, content2) {
241
429
  return el("pre", attrs ?? {}, el("code", {}, content2));
242
430
  }
@@ -311,35 +499,46 @@ export {
311
499
  cardFooter,
312
500
  cardTitle,
313
501
  center,
502
+ checkbox,
314
503
  classNames,
315
504
  cluster,
316
505
  codeBlock,
317
506
  content,
318
507
  el,
508
+ field,
319
509
  fill,
320
510
  footer,
511
+ form,
321
512
  grid,
322
513
  header,
323
514
  inlineCode,
515
+ input,
324
516
  lead,
325
517
  mergeClasses,
326
518
  muted,
327
519
  nav,
328
520
  navLink,
329
521
  navList,
522
+ option,
330
523
  page,
331
524
  prose,
332
525
  push,
526
+ radio,
527
+ radioGroup,
333
528
  raw,
334
529
  row,
335
530
  section,
531
+ select,
336
532
  sidebar,
337
533
  spread,
338
534
  stack,
535
+ switchInput,
339
536
  table,
340
537
  tbody,
341
538
  td,
342
539
  text,
540
+ textCenter,
541
+ textarea,
343
542
  th,
344
543
  thead,
345
544
  toc,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core.ts","../src/components.ts","../src/layout.ts","../src/utilities.ts"],"sourcesContent":["// Core — a tiny VDOM-ish node with two faces:\n// - .render(target?) → HTMLElement (uses real DOM)\n// - .toString() → HTML string (works in Node / Rails / SSR)\n//\n// Both are produced from the same KlodsNode tree, so the docs site can show the\n// TS source, the rendered HTML and the live preview from one source of truth.\n\nexport type KlodsChild = string | number | bigint | boolean | null | undefined | KlodsNode | Node | KlodsChild[];\n\nexport type KlodsAttrs = {\n class?: string | string[] | Record<string, boolean | undefined> | undefined;\n id?: string | undefined;\n style?: string | Partial<CSSStyleDeclaration> | undefined;\n [key: `data-${string}`]: string | number | boolean | undefined;\n [key: `aria-${string}`]: string | number | boolean | undefined;\n // Allow any other HTML attribute or DOM event handler (onClick, onInput, …).\n [key: string]: unknown;\n};\n\nconst VOID_TAGS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\nconst RAW = Symbol(\"klods.raw\");\n\ntype RawHtml = { [RAW]: true; html: string };\n\n/** Mark a string as already-escaped HTML; pass it as a child to inject as-is. */\nexport function raw(html: string): RawHtml {\n return { [RAW]: true, html };\n}\n\nfunction isRaw(value: unknown): value is RawHtml {\n return typeof value === \"object\" && value !== null && (value as { [RAW]?: unknown })[RAW] === true;\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\nfunction escapeAttr(str: string): string {\n return str.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\");\n}\n\n/** Normalise a `class` value (string | array | record) into a clean string. */\nexport function classNames(input: KlodsAttrs[\"class\"]): string {\n if (!input) return \"\";\n if (typeof input === \"string\") return input.trim();\n if (Array.isArray(input)) return input.filter(Boolean).join(\" \").trim();\n return Object.entries(input)\n .filter(([, v]) => Boolean(v))\n .map(([k]) => k)\n .join(\" \")\n .trim();\n}\n\n/** Merge two class values (used internally to combine builder defaults + user-supplied). */\nexport function mergeClasses(...inputs: Array<KlodsAttrs[\"class\"]>): string {\n return inputs\n .map((c) => classNames(c))\n .filter(Boolean)\n .join(\" \");\n}\n\nfunction styleToString(style: string | Partial<CSSStyleDeclaration>): string {\n if (typeof style === \"string\") return style;\n return Object.entries(style)\n .filter(([, v]) => v !== undefined && v !== null && v !== \"\")\n .map(([k, v]) => `${k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}:${String(v)}`)\n .join(\";\");\n}\n\nfunction flattenChildren(children: KlodsChild | KlodsChild[]): Array<Exclude<KlodsChild, KlodsChild[]>> {\n const out: Array<Exclude<KlodsChild, KlodsChild[]>> = [];\n const stack: KlodsChild[] = Array.isArray(children) ? [...children] : [children];\n while (stack.length) {\n const next = stack.shift();\n if (Array.isArray(next)) stack.unshift(...next);\n else if (next !== null && next !== undefined && next !== false && next !== true) out.push(next);\n }\n return out;\n}\n\nexport class KlodsNode {\n readonly tag: string;\n readonly attrs: KlodsAttrs;\n readonly children: KlodsChild[];\n\n constructor(tag: string, attrs: KlodsAttrs = {}, children: KlodsChild | KlodsChild[] = []) {\n this.tag = tag;\n this.attrs = attrs;\n this.children = Array.isArray(children) ? children : [children];\n }\n\n /** Render to a real DOM element. If `target` is given, append to it. */\n render(target?: Element | null): HTMLElement {\n const el = document.createElement(this.tag);\n for (const [name, value] of Object.entries(this.attrs)) {\n if (value === undefined || value === null || value === false) continue;\n if (name === \"children\") continue;\n if (name === \"class\") {\n const cls = classNames(value as KlodsAttrs[\"class\"]);\n if (cls) el.setAttribute(\"class\", cls);\n continue;\n }\n if (name === \"style\") {\n el.setAttribute(\"style\", styleToString(value as string | Partial<CSSStyleDeclaration>));\n continue;\n }\n if (name.startsWith(\"on\") && typeof value === \"function\") {\n el.addEventListener(name.slice(2).toLowerCase(), value as EventListener);\n continue;\n }\n if (value === true) {\n el.setAttribute(name, \"\");\n continue;\n }\n el.setAttribute(name, String(value));\n }\n for (const child of flattenChildren(this.children)) {\n if (child instanceof KlodsNode) el.appendChild(child.render());\n else if (typeof child === \"object\" && child !== null && \"nodeType\" in child) {\n el.appendChild(child as Node);\n } else if (isRaw(child)) {\n const tpl = document.createElement(\"template\");\n tpl.innerHTML = child.html;\n el.appendChild(tpl.content);\n } else {\n el.appendChild(document.createTextNode(String(child)));\n }\n }\n if (target) target.appendChild(el);\n return el;\n }\n\n /** Render to a string of HTML. */\n toString(): string {\n const parts: string[] = [`<${this.tag}`];\n for (const [name, value] of Object.entries(this.attrs)) {\n if (value === undefined || value === null || value === false) continue;\n if (name === \"children\") continue;\n if (name.startsWith(\"on\") && typeof value === \"function\") continue;\n if (name === \"class\") {\n const cls = classNames(value as KlodsAttrs[\"class\"]);\n if (cls) parts.push(` class=\"${escapeAttr(cls)}\"`);\n continue;\n }\n if (name === \"style\") {\n parts.push(` style=\"${escapeAttr(styleToString(value as string | Partial<CSSStyleDeclaration>))}\"`);\n continue;\n }\n if (value === true) {\n parts.push(` ${name}`);\n continue;\n }\n parts.push(` ${name}=\"${escapeAttr(String(value))}\"`);\n }\n if (VOID_TAGS.has(this.tag)) {\n parts.push(\" />\");\n return parts.join(\"\");\n }\n parts.push(\">\");\n for (const child of flattenChildren(this.children)) {\n if (child instanceof KlodsNode) parts.push(child.toString());\n else if (isRaw(child)) parts.push(child.html);\n else if (typeof child === \"object\" && child !== null && \"outerHTML\" in child) {\n parts.push((child as Element).outerHTML);\n } else {\n parts.push(escapeHtml(String(child)));\n }\n }\n parts.push(`</${this.tag}>`);\n return parts.join(\"\");\n }\n}\n\n/**\n * Generic element builder. Most consumers use the named builders (page, header, …)\n * rather than calling `el` directly, but it's exported as an escape hatch.\n */\nexport function el(tag: string, attrs: KlodsAttrs = {}, children: KlodsChild | KlodsChild[] = []): KlodsNode {\n return new KlodsNode(tag, attrs, children);\n}\n\n/**\n * Factory that produces a typed builder for a tag with a base class. Modifier\n * props are converted into `--modifier` BEM classes and stripped from the output\n * attributes; everything else passes through untouched, so consumers can attach\n * arbitrary `id`, `data-*`, `aria-*`, event handlers, `style`, etc.\n */\nexport function builder<P extends Record<string, unknown> = Record<never, never>>(options: {\n tag: string;\n base: string;\n /** Map of prop name → class (or function returning a class) when the prop is truthy. */\n modifiers?: { [K in keyof P]?: string | ((value: P[K]) => string | undefined) };\n}): (props?: (P & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]) => KlodsNode {\n const { tag, base, modifiers = {} } = options;\n const modifierMap = modifiers as Record<string, string | ((value: unknown) => string | undefined) | undefined>;\n return (props, children) => {\n const userProps = (props ?? {}) as P & KlodsAttrs;\n const modClasses: string[] = [];\n const passthrough: KlodsAttrs = {};\n for (const [key, value] of Object.entries(userProps)) {\n const m = modifierMap[key];\n if (m !== undefined) {\n if (typeof m === \"function\") {\n const c = m(value);\n if (c) modClasses.push(c);\n } else if (value) {\n modClasses.push(m);\n }\n } else {\n passthrough[key] = value;\n }\n }\n const finalClass = mergeClasses(base, ...modClasses, userProps.class);\n const resolvedChildren =\n children !== undefined ? children : ((userProps.children as KlodsChild | KlodsChild[] | undefined) ?? []);\n delete passthrough.children;\n return new KlodsNode(tag, { ...passthrough, class: finalClass || undefined }, resolvedChildren);\n };\n}\n","// First wave of components: nav, card, button, badge, alert, prose helpers.\n// All match the BEM classes shipped by klods-css.\n\nimport type { KlodsAttrs, KlodsChild } from \"./core.js\";\nimport { builder, el, KlodsNode } from \"./core.js\";\n\n// ── Nav ──────────────────────────────────────────────────────────────────\nexport const nav = builder({ tag: \"nav\", base: \"klods-nav\" });\nexport const navList = builder({ tag: \"ul\", base: \"klods-nav__list\" });\nexport const buttonGroup = builder({ tag: \"div\", base: \"klods-button-group\" });\nexport type TocProps = { sub?: boolean };\nexport const toc = builder<TocProps>({ tag: \"ul\", base: \"klods-toc\", modifiers: { sub: \"klods-toc--sub\" } });\nexport const tocItem = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"li\", attrs ?? {}, children);\nexport const tocLink = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"a\", attrs ?? {}, children);\n\nexport type NavLinkProps = {\n href?: string;\n active?: boolean;\n};\nconst navLinkBuilder = builder<NavLinkProps>({\n tag: \"a\",\n base: \"klods-nav__link\",\n modifiers: { active: \"klods-nav__link--active\" },\n});\nexport function navLink(props?: (NavLinkProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // Wrap each link in <li> so it's idiomatic inside <ul class=\"klods-nav__list\">.\n return el(\"li\", {}, [navLinkBuilder(props ?? null, children)]);\n}\n\n// ── Card ─────────────────────────────────────────────────────────────────\nexport type CardProps = {\n elevated?: boolean;\n};\nexport const card = builder<CardProps>({\n tag: \"div\",\n base: \"klods-card\",\n modifiers: { elevated: \"klods-card--elevated\" },\n});\nexport const cardTitle = builder({ tag: \"h3\", base: \"klods-card__title\" });\nexport const cardBody = builder({ tag: \"div\", base: \"klods-card__body\" });\nexport const cardFooter = builder({ tag: \"div\", base: \"klods-card__footer\" });\n\n// ── Button ───────────────────────────────────────────────────────────────\nexport type ButtonProps = {\n variant?: \"default\" | \"primary\" | \"danger\" | \"ghost\";\n type?: \"button\" | \"submit\" | \"reset\";\n};\nconst buttonBase = builder<ButtonProps>({\n tag: \"button\",\n base: \"klods-button\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-button--${v}` : undefined),\n },\n});\nexport function button(props?: (ButtonProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // Default `type=\"button\"` so it never accidentally submits a form.\n const merged = { type: \"button\", ...(props ?? {}) } as ButtonProps & KlodsAttrs;\n return buttonBase(merged, children);\n}\n\n// ── Badge ────────────────────────────────────────────────────────────────\nexport type BadgeProps = {\n variant?: \"default\" | \"accent\" | \"success\" | \"danger\";\n};\nexport const badge = builder<BadgeProps>({\n tag: \"span\",\n base: \"klods-badge\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-badge--${v}` : undefined),\n },\n});\n\n// ── Alert ────────────────────────────────────────────────────────────────\nexport type AlertProps = {\n variant?: \"default\" | \"info\" | \"success\" | \"warning\" | \"danger\";\n};\nconst alertBase = builder<AlertProps>({\n tag: \"div\",\n base: \"klods-alert\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-alert--${v}` : undefined),\n },\n});\nexport function alert(props?: (AlertProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // role=alert by default for assistive tech, overridable.\n const merged = { role: \"alert\", ...(props ?? {}) } as AlertProps & KlodsAttrs;\n return alertBase(merged, children);\n}\n\n// ── Prose helpers ────────────────────────────────────────────────────────\nexport const prose = builder({ tag: \"div\", base: \"klods-prose\" });\nexport const muted = builder({ tag: \"span\", base: \"klods-muted\" });\nexport const lead = builder({ tag: \"p\", base: \"klods-lead\" });\n\n// ── Table ────────────────────────────────────────────────────────────────\nexport type TableProps = {\n striped?: boolean;\n dense?: boolean;\n};\nexport const table = builder<TableProps>({\n tag: \"table\",\n base: \"klods-table\",\n modifiers: {\n striped: \"klods-table--striped\",\n dense: \"klods-table--dense\",\n },\n});\nexport const thead = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"thead\", attrs ?? {}, children);\nexport const tbody = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"tbody\", attrs ?? {}, children);\nexport const tr = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"tr\", attrs ?? {}, children);\nexport const th = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"th\", attrs ?? {}, children);\nexport const td = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"td\", attrs ?? {}, children);\n\n// ── Code ─────────────────────────────────────────────────────────────────\nexport function codeBlock(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode {\n return el(\"pre\", attrs ?? {}, el(\"code\", {}, content));\n}\nexport function inlineCode(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode {\n return el(\"code\", attrs ?? {}, content);\n}\n\n// ── Box ──────────────────────────────────────────────────────────────────\nexport const box = builder({ tag: \"div\", base: \"klods-box\" });\n","// Layout builders — the four corners and the \"I-always-forget\" utilities.\n// Each builder is a thin wrapper around `builder()` from core.ts.\n\nimport type { KlodsAttrs, KlodsChild } from \"./core.js\";\nimport { builder, KlodsNode } from \"./core.js\";\n\n// ── Page ─────────────────────────────────────────────────────────────────\nexport type PageProps = {\n /** Render with a sidebar column. */\n sidebar?: boolean;\n /** Which side the sidebar appears on. Defaults to `\"leading\"` (inline-start). */\n sidebarPosition?: \"leading\" | \"trailing\";\n /** Keep the header pinned to the top of the viewport while the page scrolls. */\n stickyHeader?: boolean;\n};\n\nexport const page = builder<PageProps>({\n tag: \"div\",\n base: \"klods-page\",\n modifiers: {\n sidebar: \"klods-page--with-sidebar\",\n sidebarPosition: (v) => (v === \"trailing\" ? \"klods-page--sidebar-trailing\" : undefined),\n stickyHeader: \"klods-page--sticky-header\",\n },\n});\n\n// ── Page slots ───────────────────────────────────────────────────────────\nexport const header = builder({ tag: \"header\", base: \"klods-header\" });\nexport const sidebar = builder({ tag: \"aside\", base: \"klods-sidebar\" });\n\nexport type ContentProps = {\n /** Cap content width to --klods-content-max and centre it. */\n narrow?: boolean;\n};\nexport const content = builder<ContentProps>({\n tag: \"main\",\n base: \"klods-content\",\n modifiers: { narrow: \"klods-content--narrow\" },\n});\n\nexport const footer = builder({ tag: \"footer\", base: \"klods-footer\" });\nexport const section = builder({ tag: \"section\", base: \"klods-section\" });\n\n// ── Layout utilities ─────────────────────────────────────────────────────\ntype GapProp = { gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 };\n\nconst gapModifier = (prefix: string) => (v: number | undefined) =>\n v === undefined ? undefined : `${prefix}--gap-${v}`;\n\nexport const stack = builder<GapProp>({\n tag: \"div\",\n base: \"klods-stack\",\n modifiers: { gap: gapModifier(\"klods-stack\") },\n});\n\nexport const cluster = builder<GapProp>({\n tag: \"div\",\n base: \"klods-cluster\",\n modifiers: { gap: gapModifier(\"klods-cluster\") },\n});\n\ntype RowProps = GapProp & { inline?: boolean };\nexport const row = builder<RowProps>({\n tag: \"div\",\n base: \"klods-row\",\n modifiers: { gap: gapModifier(\"klods-row\"), inline: \"klods-row--inline\" },\n});\n\nexport type GridProps = GapProp & {\n cols?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Auto-fit responsive columns; pair with `--klods-grid-min` if you want a custom minimum. */\n fit?: boolean;\n};\nexport const grid = builder<GridProps>({\n tag: \"div\",\n base: \"klods-grid\",\n modifiers: {\n gap: gapModifier(\"klods-grid\"),\n cols: (v) => (v === undefined ? undefined : `klods-grid--cols-${v}`),\n fit: \"klods-grid--fit\",\n },\n});\n\nexport const center = builder({ tag: \"div\", base: \"klods-center\" });\nexport const spread = builder({ tag: \"div\", base: \"klods-spread\" });\n\n// ── Convenience: empty fragment-ish wrapper for quick text + nodes ──────\nexport function text(value: string | number): KlodsNode {\n // Wrap loose text in a span so it composes anywhere a KlodsNode is expected.\n return new KlodsNode(\"span\", {}, [String(value)]);\n}\n\n// Re-export attribute / child types so consumers can extend a builder neatly.\nexport type { KlodsAttrs, KlodsChild };\n","// Utility builders — thin wrappers over the most-reached-for klods-css utility classes.\n\nimport { builder } from \"./core.js\";\n\n// ── Push ─────────────────────────────────────────────────────────────────\n// Renders a <span class=\"klods-push\">.\n// Pushes siblings to the end of a flex/grid row by consuming all remaining\n// inline space (margin-inline-start: auto).\nexport const push = builder({ tag: \"span\", base: \"klods-push\" });\n\n// ── Fill ─────────────────────────────────────────────────────────────────\n// Renders a <div class=\"klods-fill\">.\n// Grows to fill available flex/grid space (flex: 1 1 auto).\n// Useful as a wrapper when you need one slot to absorb leftover room —\n// e.g. equal-width side groups in a header to centre a middle item.\nexport const fill = builder({ tag: \"div\", base: \"klods-fill\" });\n"],"mappings":"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","names":["stack","el","content"]}
1
+ {"version":3,"sources":["../src/core.ts","../src/components.ts","../src/layout.ts","../src/utilities.ts"],"sourcesContent":["// Core — a tiny VDOM-ish node with two faces:\n// - .render(target?) → HTMLElement (uses real DOM)\n// - .toString() → HTML string (works in Node / Rails / SSR)\n//\n// Both are produced from the same KlodsNode tree, so the docs site can show the\n// TS source, the rendered HTML and the live preview from one source of truth.\n\nexport type KlodsChild = string | number | bigint | boolean | null | undefined | KlodsNode | Node | KlodsChild[];\n\nexport type KlodsAttrs = {\n class?: string | string[] | Record<string, boolean | undefined> | undefined;\n id?: string | undefined;\n style?: string | Partial<CSSStyleDeclaration> | undefined;\n [key: `data-${string}`]: string | number | boolean | undefined;\n [key: `aria-${string}`]: string | number | boolean | undefined;\n // Allow any other HTML attribute or DOM event handler (onClick, onInput, …).\n [key: string]: unknown;\n};\n\nconst VOID_TAGS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"source\",\n \"track\",\n \"wbr\",\n]);\n\nconst RAW = Symbol(\"klods.raw\");\n\ntype RawHtml = { [RAW]: true; html: string };\n\n/** Mark a string as already-escaped HTML; pass it as a child to inject as-is. */\nexport function raw(html: string): RawHtml {\n return { [RAW]: true, html };\n}\n\nfunction isRaw(value: unknown): value is RawHtml {\n return typeof value === \"object\" && value !== null && (value as { [RAW]?: unknown })[RAW] === true;\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n\nfunction escapeAttr(str: string): string {\n return str.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\");\n}\n\n/** Normalise a `class` value (string | array | record) into a clean string. */\nexport function classNames(input: KlodsAttrs[\"class\"]): string {\n if (!input) return \"\";\n if (typeof input === \"string\") return input.trim();\n if (Array.isArray(input)) return input.filter(Boolean).join(\" \").trim();\n return Object.entries(input)\n .filter(([, v]) => Boolean(v))\n .map(([k]) => k)\n .join(\" \")\n .trim();\n}\n\n/** Merge two class values (used internally to combine builder defaults + user-supplied). */\nexport function mergeClasses(...inputs: Array<KlodsAttrs[\"class\"]>): string {\n return inputs\n .map((c) => classNames(c))\n .filter(Boolean)\n .join(\" \");\n}\n\nfunction styleToString(style: string | Partial<CSSStyleDeclaration>): string {\n if (typeof style === \"string\") return style;\n return Object.entries(style)\n .filter(([, v]) => v !== undefined && v !== null && v !== \"\")\n .map(([k, v]) => `${k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`)}:${String(v)}`)\n .join(\";\");\n}\n\nfunction flattenChildren(children: KlodsChild | KlodsChild[]): Array<Exclude<KlodsChild, KlodsChild[]>> {\n const out: Array<Exclude<KlodsChild, KlodsChild[]>> = [];\n const stack: KlodsChild[] = Array.isArray(children) ? [...children] : [children];\n while (stack.length) {\n const next = stack.shift();\n if (Array.isArray(next)) stack.unshift(...next);\n else if (next !== null && next !== undefined && next !== false && next !== true) out.push(next);\n }\n return out;\n}\n\nexport class KlodsNode {\n readonly tag: string;\n readonly attrs: KlodsAttrs;\n readonly children: KlodsChild[];\n\n constructor(tag: string, attrs: KlodsAttrs = {}, children: KlodsChild | KlodsChild[] = []) {\n this.tag = tag;\n this.attrs = attrs;\n this.children = Array.isArray(children) ? children : [children];\n }\n\n /** Render to a real DOM element. If `target` is given, append to it. */\n render(target?: Element | null): HTMLElement {\n const el = document.createElement(this.tag);\n for (const [name, value] of Object.entries(this.attrs)) {\n if (value === undefined || value === null || value === false) continue;\n if (name === \"children\") continue;\n if (name === \"class\") {\n const cls = classNames(value as KlodsAttrs[\"class\"]);\n if (cls) el.setAttribute(\"class\", cls);\n continue;\n }\n if (name === \"style\") {\n el.setAttribute(\"style\", styleToString(value as string | Partial<CSSStyleDeclaration>));\n continue;\n }\n if (name.startsWith(\"on\") && typeof value === \"function\") {\n el.addEventListener(name.slice(2).toLowerCase(), value as EventListener);\n continue;\n }\n if (value === true) {\n el.setAttribute(name, \"\");\n continue;\n }\n el.setAttribute(name, String(value));\n }\n for (const child of flattenChildren(this.children)) {\n if (child instanceof KlodsNode) el.appendChild(child.render());\n else if (typeof child === \"object\" && child !== null && \"nodeType\" in child) {\n el.appendChild(child as Node);\n } else if (isRaw(child)) {\n const tpl = document.createElement(\"template\");\n tpl.innerHTML = child.html;\n el.appendChild(tpl.content);\n } else {\n el.appendChild(document.createTextNode(String(child)));\n }\n }\n if (target) target.appendChild(el);\n return el;\n }\n\n /** Render to a string of HTML. */\n toString(): string {\n const parts: string[] = [`<${this.tag}`];\n for (const [name, value] of Object.entries(this.attrs)) {\n if (value === undefined || value === null || value === false) continue;\n if (name === \"children\") continue;\n if (name.startsWith(\"on\") && typeof value === \"function\") continue;\n if (name === \"class\") {\n const cls = classNames(value as KlodsAttrs[\"class\"]);\n if (cls) parts.push(` class=\"${escapeAttr(cls)}\"`);\n continue;\n }\n if (name === \"style\") {\n parts.push(` style=\"${escapeAttr(styleToString(value as string | Partial<CSSStyleDeclaration>))}\"`);\n continue;\n }\n if (value === true) {\n parts.push(` ${name}`);\n continue;\n }\n parts.push(` ${name}=\"${escapeAttr(String(value))}\"`);\n }\n if (VOID_TAGS.has(this.tag)) {\n parts.push(\" />\");\n return parts.join(\"\");\n }\n parts.push(\">\");\n for (const child of flattenChildren(this.children)) {\n if (child instanceof KlodsNode) parts.push(child.toString());\n else if (isRaw(child)) parts.push(child.html);\n else if (typeof child === \"object\" && child !== null && \"outerHTML\" in child) {\n parts.push((child as Element).outerHTML);\n } else {\n parts.push(escapeHtml(String(child)));\n }\n }\n parts.push(`</${this.tag}>`);\n return parts.join(\"\");\n }\n}\n\n/**\n * Generic element builder. Most consumers use the named builders (page, header, …)\n * rather than calling `el` directly, but it's exported as an escape hatch.\n */\nexport function el(tag: string, attrs: KlodsAttrs = {}, children: KlodsChild | KlodsChild[] = []): KlodsNode {\n return new KlodsNode(tag, attrs, children);\n}\n\n/**\n * Factory that produces a typed builder for a tag with a base class. Modifier\n * props are converted into `--modifier` BEM classes and stripped from the output\n * attributes; everything else passes through untouched, so consumers can attach\n * arbitrary `id`, `data-*`, `aria-*`, event handlers, `style`, etc.\n */\nexport function builder<P extends Record<string, unknown> = Record<never, never>>(options: {\n tag: string;\n base: string;\n /** Map of prop name → class (or function returning a class) when the prop is truthy. */\n modifiers?: { [K in keyof P]?: string | ((value: P[K]) => string | undefined) };\n}): (props?: (P & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]) => KlodsNode {\n const { tag, base, modifiers = {} } = options;\n const modifierMap = modifiers as Record<string, string | ((value: unknown) => string | undefined) | undefined>;\n return (props, children) => {\n const userProps = (props ?? {}) as P & KlodsAttrs;\n const modClasses: string[] = [];\n const passthrough: KlodsAttrs = {};\n for (const [key, value] of Object.entries(userProps)) {\n const m = modifierMap[key];\n if (m !== undefined) {\n if (typeof m === \"function\") {\n const c = m(value);\n if (c) modClasses.push(c);\n } else if (value) {\n modClasses.push(m);\n }\n } else {\n passthrough[key] = value;\n }\n }\n const finalClass = mergeClasses(base, ...modClasses, userProps.class);\n const resolvedChildren =\n children !== undefined ? children : ((userProps.children as KlodsChild | KlodsChild[] | undefined) ?? []);\n delete passthrough.children;\n return new KlodsNode(tag, { ...passthrough, class: finalClass || undefined }, resolvedChildren);\n };\n}\n","// First wave of components: nav, card, button, badge, alert, prose helpers.\n// All match the BEM classes shipped by klods-css.\n\nimport type { KlodsAttrs, KlodsChild } from \"./core.js\";\nimport { builder, classNames, el, KlodsNode } from \"./core.js\";\n\n// ── Nav ──────────────────────────────────────────────────────────────────\nexport const nav = builder({ tag: \"nav\", base: \"klods-nav\" });\nexport const navList = builder({ tag: \"ul\", base: \"klods-nav__list\" });\nexport const buttonGroup = builder({ tag: \"div\", base: \"klods-button-group\" });\nexport type TocProps = { sub?: boolean };\nexport const toc = builder<TocProps>({ tag: \"ul\", base: \"klods-toc\", modifiers: { sub: \"klods-toc--sub\" } });\nexport const tocItem = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"li\", attrs ?? {}, children);\nexport const tocLink = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"a\", attrs ?? {}, children);\n\nexport type NavLinkProps = {\n href?: string;\n active?: boolean;\n};\nconst navLinkBuilder = builder<NavLinkProps>({\n tag: \"a\",\n base: \"klods-nav__link\",\n modifiers: { active: \"klods-nav__link--active\" },\n});\nexport function navLink(props?: (NavLinkProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // Wrap each link in <li> so it's idiomatic inside <ul class=\"klods-nav__list\">.\n return el(\"li\", {}, [navLinkBuilder(props ?? null, children)]);\n}\n\n// ── Card ─────────────────────────────────────────────────────────────────\nexport type CardProps = {\n elevated?: boolean;\n};\nexport const card = builder<CardProps>({\n tag: \"div\",\n base: \"klods-card\",\n modifiers: { elevated: \"klods-card--elevated\" },\n});\nexport const cardTitle = builder({ tag: \"h3\", base: \"klods-card__title\" });\nexport const cardBody = builder({ tag: \"div\", base: \"klods-card__body\" });\nexport const cardFooter = builder({ tag: \"div\", base: \"klods-card__footer\" });\n\n// ── Button ───────────────────────────────────────────────────────────────\nexport type ButtonProps = {\n variant?: \"default\" | \"primary\" | \"danger\" | \"ghost\";\n type?: \"button\" | \"submit\" | \"reset\";\n};\nconst buttonBase = builder<ButtonProps>({\n tag: \"button\",\n base: \"klods-button\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-button--${v}` : undefined),\n },\n});\nexport function button(props?: (ButtonProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // Default `type=\"button\"` so it never accidentally submits a form.\n const merged = { type: \"button\", ...(props ?? {}) } as ButtonProps & KlodsAttrs;\n return buttonBase(merged, children);\n}\n\n// ── Badge ────────────────────────────────────────────────────────────────\nexport type BadgeProps = {\n variant?: \"default\" | \"accent\" | \"success\" | \"danger\";\n};\nexport const badge = builder<BadgeProps>({\n tag: \"span\",\n base: \"klods-badge\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-badge--${v}` : undefined),\n },\n});\n\n// ── Alert ────────────────────────────────────────────────────────────────\nexport type AlertProps = {\n variant?: \"default\" | \"info\" | \"success\" | \"warning\" | \"danger\";\n};\nconst alertBase = builder<AlertProps>({\n tag: \"div\",\n base: \"klods-alert\",\n modifiers: {\n variant: (v) => (v && v !== \"default\" ? `klods-alert--${v}` : undefined),\n },\n});\nexport function alert(props?: (AlertProps & KlodsAttrs) | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // role=alert by default for assistive tech, overridable.\n const merged = { role: \"alert\", ...(props ?? {}) } as AlertProps & KlodsAttrs;\n return alertBase(merged, children);\n}\n\n// ── Prose helpers ────────────────────────────────────────────────────────\nexport const prose = builder({ tag: \"div\", base: \"klods-prose\" });\nexport const muted = builder({ tag: \"span\", base: \"klods-muted\" });\nexport const lead = builder({ tag: \"p\", base: \"klods-lead\" });\nexport const textCenter = builder({ tag: \"div\", base: \"klods-text-center\" });\n\n// ── Table ────────────────────────────────────────────────────────────────\nexport type TableProps = {\n striped?: boolean;\n dense?: boolean;\n};\nexport const table = builder<TableProps>({\n tag: \"table\",\n base: \"klods-table\",\n modifiers: {\n striped: \"klods-table--striped\",\n dense: \"klods-table--dense\",\n },\n});\nexport const thead = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"thead\", attrs ?? {}, children);\nexport const tbody = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"tbody\", attrs ?? {}, children);\nexport const tr = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"tr\", attrs ?? {}, children);\nexport const th = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"th\", attrs ?? {}, children);\nexport const td = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"td\", attrs ?? {}, children);\n\n// ── Forms ────────────────────────────────────────────────────────────────\n\n// Converts a label string to a stable, URL-safe id segment.\n// \"Email address\" → \"email-address\", \"First name\" → \"first-name\"\n// Falls back to a djb2 hash when the label produces no alphanumeric slug\n// (e.g. empty string or all-symbol text), keeping IDs deterministic.\nfunction slugId(prefix: string, text: string): string {\n const safe = text ?? \"\";\n const slug = safe\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n if (slug) return `${prefix}-${slug}`;\n let h = 5381;\n for (let i = 0; i < safe.length; i++) h = ((h << 5) + h + safe.charCodeAt(i)) | 0;\n return `${prefix}-${(h >>> 0).toString(36)}`;\n}\n\nexport const form = builder({ tag: \"form\", base: \"klods-form\" });\n\nexport type FieldProps = {\n /** Label text shown above the control. */\n label: string;\n /** Explicit id for the control. Auto-generated when omitted. */\n id?: string;\n /** Hint text shown below the control. Hidden when the field is invalid. */\n help?: string;\n /** Validation error. When present the field is rendered in its invalid state. */\n error?: string;\n /** Appends a * marker to the label. */\n required?: boolean;\n /** Force invalid state without providing error text. */\n invalid?: boolean;\n};\n\n// Form controls that can directly carry aria-describedby / aria-invalid.\nconst FORM_CONTROLS = new Set([\"input\", \"select\", \"textarea\"]);\n\n// Injects aria attrs onto the node itself if it's a form control, or onto the\n// first form-control child if it's a wrapper (e.g. the range / color wrappers).\nfunction patchAriaAttrs(node: KlodsNode, attrs: KlodsAttrs): KlodsNode {\n if (FORM_CONTROLS.has(node.tag)) {\n return new KlodsNode(node.tag, { ...node.attrs, ...attrs }, node.children);\n }\n const patchedChildren = node.children.map((child) =>\n child instanceof KlodsNode && FORM_CONTROLS.has(child.tag)\n ? new KlodsNode(child.tag, { ...child.attrs, ...attrs }, child.children)\n : child\n );\n return new KlodsNode(node.tag, node.attrs, patchedChildren);\n}\n\n/**\n * Opinionated field wrapper. Renders a label, the control, and optional\n * help / error text. Automatically wires `for`, `id`, `aria-describedby`,\n * and `aria-invalid` so you don't have to.\n *\n * Pass a render function that receives the generated (or explicit) `id`:\n * ```ts\n * field({ label: \"Email\", required: true }, (id) =>\n * input({ id, type: \"email\" }),\n * )\n * ```\n */\nexport function field(props: FieldProps & KlodsAttrs, renderInput: (id: string) => KlodsNode): KlodsNode {\n const { label: labelText, id: explicitId, help, error, required, invalid, class: extraClass, ...rest } = props;\n const id = explicitId ?? slugId(\"klods-field\", labelText);\n const helpId = help ? `${id}-help` : undefined;\n const errorId = error ? `${id}-error` : undefined;\n const isInvalid = invalid ?? !!error;\n\n // When invalid, .klods-help is hidden by CSS — only reference the visible error.\n // When valid, .klods-error is absent — only reference help text if present.\n const describedBy = isInvalid ? errorId : helpId;\n\n // Inject aria attrs onto the control (or its first form-control child for wrappers).\n const inputNode = renderInput(id);\n const patchedInput = patchAriaAttrs(inputNode, {\n ...(describedBy ? { \"aria-describedby\": describedBy } : {}),\n ...(isInvalid ? { \"aria-invalid\": \"true\" } : {}),\n });\n\n const fieldClass = classNames([\n \"klods-field\",\n isInvalid ? \"klods-field--invalid\" : \"\",\n classNames(extraClass as KlodsAttrs[\"class\"]),\n ]);\n\n const children: KlodsNode[] = [\n el(\"label\", { for: id, class: `klods-label${required ? \" klods-label--required\" : \"\"}` }, labelText),\n patchedInput,\n ];\n if (help) children.push(el(\"p\", { id: helpId, class: \"klods-help\" }, help));\n if (error) children.push(el(\"p\", { id: errorId, class: \"klods-error\", role: \"alert\" }, error));\n\n return el(\"div\", { ...rest, class: fieldClass || undefined }, children);\n}\n\nexport type InputProps = {\n type?:\n | \"text\"\n | \"email\"\n | \"password\"\n | \"number\"\n | \"tel\"\n | \"url\"\n | \"search\"\n | \"date\"\n | \"time\"\n | \"datetime-local\"\n | \"range\"\n | \"color\"\n | \"file\"\n | \"hidden\";\n};\nexport function input(props: InputProps & KlodsAttrs): KlodsNode {\n const { type, class: extraClass, oninput: userOninput, ...rest } = props;\n const cls = (extra: string) =>\n classNames([\"klods-input\", extra, classNames(extraClass as KlodsAttrs[\"class\"])]) || undefined;\n\n const id =\n (rest.id as string | undefined) ??\n slugId(\n \"klods-input\",\n (rest[\"aria-label\"] as string | undefined) ?? (rest.placeholder as string | undefined) ?? type ?? \"field\"\n );\n\n if (type === \"range\") {\n const initial = (rest.value as string) ?? \"50\";\n return el(\"span\", { class: cls(\"klods-input--range\") }, [\n el(\"input\", {\n type: \"range\",\n ...rest,\n id,\n oninput: (e: Event) => {\n const inp = e.target as HTMLInputElement;\n inp.closest(\".klods-input--range\")?.querySelector(\"output\")?.textContent !== undefined &&\n (inp.closest(\".klods-input--range\")!.querySelector(\"output\")!.textContent = inp.value);\n (userOninput as ((e: Event) => void) | undefined)?.(e);\n },\n }),\n el(\"output\", { for: id }, initial),\n ]);\n }\n\n if (type === \"color\") {\n const initial = (rest.value as string) ?? \"#000000\";\n return el(\"span\", { class: cls(\"klods-input--color\") }, [\n el(\"input\", {\n type: \"color\",\n ...rest,\n id,\n oninput: (e: Event) => {\n const inp = e.target as HTMLInputElement;\n inp.closest(\".klods-input--color\")?.querySelector(\"output\")?.textContent !== undefined &&\n (inp.closest(\".klods-input--color\")!.querySelector(\"output\")!.textContent = inp.value);\n (userOninput as ((e: Event) => void) | undefined)?.(e);\n },\n }),\n el(\"output\", { for: id }, initial),\n ]);\n }\n\n return new KlodsNode(\"input\", {\n type,\n ...rest,\n id,\n class: cls(\"\"),\n });\n}\n\nconst selectEl = builder({ tag: \"select\", base: \"klods-select\" });\nexport function select(attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode {\n // Wrap in a positioning parent so ::after can render the chevron arrow\n // via mask-image + var(--klods-color-muted) without a baked-in color.\n return el(\"div\", { class: \"klods-select-wrapper\" }, selectEl(attrs, children));\n}\n\nexport const option = (attrs?: KlodsAttrs | null, children?: KlodsChild | KlodsChild[]): KlodsNode =>\n el(\"option\", attrs ?? {}, children);\n\nexport const textarea = builder({ tag: \"textarea\", base: \"klods-textarea\" });\n\n// ── Checkbox ─────────────────────────────────────────────────────────────\n\nexport type CheckboxProps = {\n label: string;\n name?: string;\n value?: string;\n checked?: boolean;\n disabled?: boolean;\n};\nexport function checkbox(props: CheckboxProps & KlodsAttrs): KlodsNode {\n const {\n label: labelText,\n name,\n value,\n checked,\n disabled,\n required,\n form,\n autofocus,\n class: extraClass,\n ...rest\n } = props as CheckboxProps & KlodsAttrs & { required?: boolean; form?: string; autofocus?: boolean };\n const inputAttrs: KlodsAttrs = { type: \"checkbox\" };\n if (name !== undefined) inputAttrs.name = name;\n if (value !== undefined) inputAttrs.value = value;\n if (checked) inputAttrs.checked = true;\n if (disabled) inputAttrs.disabled = true;\n if (required) inputAttrs.required = true;\n if (form !== undefined) inputAttrs.form = form;\n if (autofocus) inputAttrs.autofocus = true;\n\n return el(\n \"label\",\n { ...rest, class: classNames([\"klods-checkbox\", classNames(extraClass as KlodsAttrs[\"class\"])]) || undefined },\n [el(\"input\", inputAttrs), el(\"span\", {}, labelText)]\n );\n}\n\n// ── Radio ─────────────────────────────────────────────────────────────────\n\nexport type RadioProps = {\n label: string;\n name?: string;\n value?: string;\n checked?: boolean;\n disabled?: boolean;\n};\nexport function radio(props: RadioProps & KlodsAttrs): KlodsNode {\n const {\n label: labelText,\n name,\n value,\n checked,\n disabled,\n required,\n form,\n autofocus,\n class: extraClass,\n ...rest\n } = props as RadioProps & KlodsAttrs & { required?: boolean; form?: string; autofocus?: boolean };\n const inputAttrs: KlodsAttrs = { type: \"radio\" };\n if (name !== undefined) inputAttrs.name = name;\n if (value !== undefined) inputAttrs.value = value;\n if (checked) inputAttrs.checked = true;\n if (disabled) inputAttrs.disabled = true;\n if (required) inputAttrs.required = true;\n if (form !== undefined) inputAttrs.form = form;\n if (autofocus) inputAttrs.autofocus = true;\n\n return el(\n \"label\",\n { ...rest, class: classNames([\"klods-radio\", classNames(extraClass as KlodsAttrs[\"class\"])]) || undefined },\n [el(\"input\", inputAttrs), el(\"span\", {}, labelText)]\n );\n}\n\n// ── Radio group ───────────────────────────────────────────────────────────\n\nexport type RadioGroupProps = {\n /** Text shown as the group heading (maps to a styled `<p>` with aria-labelledby). */\n legend?: string;\n};\nexport function radioGroup(props: RadioGroupProps & KlodsAttrs, children: KlodsNode[]): KlodsNode {\n const { legend: legendText, class: extraClass, ...rest } = props;\n const legendId = legendText ? slugId(\"klods-rg\", legendText) : undefined;\n const cls = classNames([\"klods-field\", classNames(extraClass as KlodsAttrs[\"class\"])]) || undefined;\n return el(\"div\", { ...rest, class: cls, role: \"group\", ...(legendId ? { \"aria-labelledby\": legendId } : {}) }, [\n legendText ? el(\"p\", { id: legendId, class: \"klods-label\" }, legendText) : null,\n ...children,\n ]);\n}\n\n// ── Switch ────────────────────────────────────────────────────────────────\n\nexport type SwitchProps = {\n label: string;\n name?: string;\n value?: string;\n checked?: boolean;\n disabled?: boolean;\n /** Flips the layout: label on the left, track on the right. Ideal for settings panels. */\n reverse?: boolean;\n};\nexport function switchInput(props: SwitchProps & KlodsAttrs): KlodsNode {\n const { label: labelText, name, value, checked, disabled, reverse, class: extraClass, ...rest } = props;\n const inputAttrs: KlodsAttrs = {\n type: \"checkbox\",\n class: \"klods-switch__input\",\n role: \"switch\",\n };\n if (name !== undefined) inputAttrs.name = name;\n if (value !== undefined) inputAttrs.value = value;\n if (checked) inputAttrs.checked = true;\n if (disabled) inputAttrs.disabled = true;\n\n return el(\n \"label\",\n {\n ...rest,\n class:\n classNames([\n \"klods-switch\",\n reverse ? \"klods-switch--reverse\" : \"\",\n classNames(extraClass as KlodsAttrs[\"class\"]),\n ]) || undefined,\n },\n [\n el(\"input\", inputAttrs),\n el(\"span\", { class: \"klods-switch__track\" }),\n el(\"span\", { class: \"klods-switch__label\" }, labelText),\n ]\n );\n}\n\n// ── Code ─────────────────────────────────────────────────────────────────\nexport function codeBlock(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode {\n return el(\"pre\", attrs ?? {}, el(\"code\", {}, content));\n}\nexport function inlineCode(attrs?: KlodsAttrs | null, content?: KlodsChild | KlodsChild[]): KlodsNode {\n return el(\"code\", attrs ?? {}, content);\n}\n\n// ── Box ──────────────────────────────────────────────────────────────────\nexport const box = builder({ tag: \"div\", base: \"klods-box\" });\n","// Layout builders — the four corners and the \"I-always-forget\" utilities.\n// Each builder is a thin wrapper around `builder()` from core.ts.\n\nimport type { KlodsAttrs, KlodsChild } from \"./core.js\";\nimport { builder, KlodsNode } from \"./core.js\";\n\n// ── Page ─────────────────────────────────────────────────────────────────\nexport type PageProps = {\n /** Render with a sidebar column. */\n sidebar?: boolean;\n /** Which side the sidebar appears on. Defaults to `\"leading\"` (inline-start). */\n sidebarPosition?: \"leading\" | \"trailing\";\n /** Keep the header pinned to the top of the viewport while the page scrolls. */\n stickyHeader?: boolean;\n};\n\nexport const page = builder<PageProps>({\n tag: \"div\",\n base: \"klods-page\",\n modifiers: {\n sidebar: \"klods-page--with-sidebar\",\n sidebarPosition: (v) => (v === \"trailing\" ? \"klods-page--sidebar-trailing\" : undefined),\n stickyHeader: \"klods-page--sticky-header\",\n },\n});\n\n// ── Page slots ───────────────────────────────────────────────────────────\nexport const header = builder({ tag: \"header\", base: \"klods-header\" });\nexport const sidebar = builder({ tag: \"aside\", base: \"klods-sidebar\" });\n\nexport type ContentProps = {\n /** Cap content width to --klods-content-max and centre it. */\n narrow?: boolean;\n};\nexport const content = builder<ContentProps>({\n tag: \"main\",\n base: \"klods-content\",\n modifiers: { narrow: \"klods-content--narrow\" },\n});\n\nexport const footer = builder({ tag: \"footer\", base: \"klods-footer\" });\nexport const section = builder({ tag: \"section\", base: \"klods-section\" });\n\n// ── Layout utilities ─────────────────────────────────────────────────────\ntype GapProp = { gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 };\n\nconst gapModifier = (prefix: string) => (v: number | undefined) =>\n v === undefined ? undefined : `${prefix}--gap-${v}`;\n\nexport const stack = builder<GapProp>({\n tag: \"div\",\n base: \"klods-stack\",\n modifiers: { gap: gapModifier(\"klods-stack\") },\n});\n\nexport const cluster = builder<GapProp>({\n tag: \"div\",\n base: \"klods-cluster\",\n modifiers: { gap: gapModifier(\"klods-cluster\") },\n});\n\ntype RowProps = GapProp & { inline?: boolean };\nexport const row = builder<RowProps>({\n tag: \"div\",\n base: \"klods-row\",\n modifiers: { gap: gapModifier(\"klods-row\"), inline: \"klods-row--inline\" },\n});\n\nexport type GridProps = GapProp & {\n cols?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Auto-fit responsive columns; pair with `--klods-grid-min` if you want a custom minimum. */\n fit?: boolean;\n};\nexport const grid = builder<GridProps>({\n tag: \"div\",\n base: \"klods-grid\",\n modifiers: {\n gap: gapModifier(\"klods-grid\"),\n cols: (v) => (v === undefined ? undefined : `klods-grid--cols-${v}`),\n fit: \"klods-grid--fit\",\n },\n});\n\nexport const center = builder({ tag: \"div\", base: \"klods-center\" });\nexport const spread = builder({ tag: \"div\", base: \"klods-spread\" });\n\n// ── Convenience: empty fragment-ish wrapper for quick text + nodes ──────\nexport function text(value: string | number): KlodsNode {\n // Wrap loose text in a span so it composes anywhere a KlodsNode is expected.\n return new KlodsNode(\"span\", {}, [String(value)]);\n}\n\n// Re-export attribute / child types so consumers can extend a builder neatly.\nexport type { KlodsAttrs, KlodsChild };\n","// Utility builders — thin wrappers over the most-reached-for klods-css utility classes.\n\nimport { builder } from \"./core.js\";\n\n// ── Push ─────────────────────────────────────────────────────────────────\n// Renders a <span class=\"klods-push\">.\n// Pushes siblings to the end of a flex/grid row by consuming all remaining\n// inline space (margin-inline-start: auto).\nexport const push = builder({ tag: \"span\", base: \"klods-push\" });\n\n// ── Fill ─────────────────────────────────────────────────────────────────\n// Renders a <div class=\"klods-fill\">.\n// Grows to fill available flex/grid space (flex: 1 1 auto).\n// Useful as a wrapper when you need one slot to absorb leftover room —\n// e.g. equal-width side groups in a header to centre a middle item.\nexport const fill = builder({ tag: \"div\", base: \"klods-fill\" });\n"],"mappings":"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","names":["input","stack","el","text","form","content"]}
package/dist/klods.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var Klods=(()=>{var c=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var B=(t,e,o)=>e in t?c(t,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):t[e]=o;var R=(t,e)=>{for(var o in e)c(t,o,{get:e[o],enumerable:!0})},T=(t,e,o,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of j(e))!L.call(t,n)&&n!==o&&c(t,n,{get:()=>e[n],enumerable:!(s=$(e,n))||s.enumerable});return t};var _=t=>T(c({},"__esModule",{value:!0}),t);var p=(t,e,o)=>B(t,typeof e!="symbol"?e+"":e,o);var $t={};R($t,{KlodsNode:()=>d,alert:()=>et,badge:()=>Y,box:()=>ft,builder:()=>r,button:()=>X,buttonGroup:()=>D,card:()=>Z,cardBody:()=>J,cardFooter:()=>Q,cardTitle:()=>z,center:()=>Pt,classNames:()=>u,cluster:()=>Ct,codeBlock:()=>pt,content:()=>Kt,el:()=>l,fill:()=>St,footer:()=>kt,grid:()=>At,header:()=>bt,inlineCode:()=>ut,lead:()=>rt,mergeClasses:()=>w,muted:()=>st,nav:()=>M,navLink:()=>V,navList:()=>O,page:()=>gt,prose:()=>ot,push:()=>Nt,raw:()=>E,row:()=>yt,section:()=>mt,sidebar:()=>ht,spread:()=>vt,stack:()=>xt,table:()=>nt,tbody:()=>dt,td:()=>ct,text:()=>wt,th:()=>at,thead:()=>lt,toc:()=>W,tocItem:()=>q,tocLink:()=>I,tr:()=>it});var H=new Set(["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"]),v=Symbol("klods.raw");function E(t){return{[v]:!0,html:t}}function y(t){return typeof t=="object"&&t!==null&&t[v]===!0}function G(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function k(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function u(t){return t?typeof t=="string"?t.trim():Array.isArray(t)?t.filter(Boolean).join(" ").trim():Object.entries(t).filter(([,e])=>!!e).map(([e])=>e).join(" ").trim():""}function w(...t){return t.map(e=>u(e)).filter(Boolean).join(" ")}function A(t){return typeof t=="string"?t:Object.entries(t).filter(([,e])=>e!=null&&e!=="").map(([e,o])=>`${e.replace(/[A-Z]/g,s=>`-${s.toLowerCase()}`)}:${String(o)}`).join(";")}function P(t){let e=[],o=Array.isArray(t)?[...t]:[t];for(;o.length;){let s=o.shift();Array.isArray(s)?o.unshift(...s):s!=null&&s!==!1&&s!==!0&&e.push(s)}return e}var d=class t{constructor(e,o={},s=[]){p(this,"tag");p(this,"attrs");p(this,"children");this.tag=e,this.attrs=o,this.children=Array.isArray(s)?s:[s]}render(e){let o=document.createElement(this.tag);for(let[s,n]of Object.entries(this.attrs))if(!(n==null||n===!1)&&s!=="children"){if(s==="class"){let i=u(n);i&&o.setAttribute("class",i);continue}if(s==="style"){o.setAttribute("style",A(n));continue}if(s.startsWith("on")&&typeof n=="function"){o.addEventListener(s.slice(2).toLowerCase(),n);continue}if(n===!0){o.setAttribute(s,"");continue}o.setAttribute(s,String(n))}for(let s of P(this.children))if(s instanceof t)o.appendChild(s.render());else if(typeof s=="object"&&s!==null&&"nodeType"in s)o.appendChild(s);else if(y(s)){let n=document.createElement("template");n.innerHTML=s.html,o.appendChild(n.content)}else o.appendChild(document.createTextNode(String(s)));return e&&e.appendChild(o),o}toString(){let e=[`<${this.tag}`];for(let[o,s]of Object.entries(this.attrs))if(!(s==null||s===!1)&&o!=="children"&&!(o.startsWith("on")&&typeof s=="function")){if(o==="class"){let n=u(s);n&&e.push(` class="${k(n)}"`);continue}if(o==="style"){e.push(` style="${k(A(s))}"`);continue}if(s===!0){e.push(` ${o}`);continue}e.push(` ${o}="${k(String(s))}"`)}if(H.has(this.tag))return e.push(" />"),e.join("");e.push(">");for(let o of P(this.children))o instanceof t?e.push(o.toString()):y(o)?e.push(o.html):typeof o=="object"&&o!==null&&"outerHTML"in o?e.push(o.outerHTML):e.push(G(String(o)));return e.push(`</${this.tag}>`),e.join("")}};function l(t,e={},o=[]){return new d(t,e,o)}function r(t){let{tag:e,base:o,modifiers:s={}}=t,n=s;return(i,m)=>{let g=i??{},b=[],h={};for(let[x,K]of Object.entries(g)){let a=n[x];if(a!==void 0)if(typeof a=="function"){let C=a(K);C&&b.push(C)}else K&&b.push(a);else h[x]=K}let N=w(o,...b,g.class),S=m!==void 0?m:g.children??[];return delete h.children,new d(e,{...h,class:N||void 0},S)}}var M=r({tag:"nav",base:"klods-nav"}),O=r({tag:"ul",base:"klods-nav__list"}),D=r({tag:"div",base:"klods-button-group"}),W=r({tag:"ul",base:"klods-toc",modifiers:{sub:"klods-toc--sub"}}),q=(t,e)=>l("li",t??{},e),I=(t,e)=>l("a",t??{},e),F=r({tag:"a",base:"klods-nav__link",modifiers:{active:"klods-nav__link--active"}});function V(t,e){return l("li",{},[F(t??null,e)])}var Z=r({tag:"div",base:"klods-card",modifiers:{elevated:"klods-card--elevated"}}),z=r({tag:"h3",base:"klods-card__title"}),J=r({tag:"div",base:"klods-card__body"}),Q=r({tag:"div",base:"klods-card__footer"}),U=r({tag:"button",base:"klods-button",modifiers:{variant:t=>t&&t!=="default"?`klods-button--${t}`:void 0}});function X(t,e){let o={type:"button",...t??{}};return U(o,e)}var Y=r({tag:"span",base:"klods-badge",modifiers:{variant:t=>t&&t!=="default"?`klods-badge--${t}`:void 0}}),tt=r({tag:"div",base:"klods-alert",modifiers:{variant:t=>t&&t!=="default"?`klods-alert--${t}`:void 0}});function et(t,e){let o={role:"alert",...t??{}};return tt(o,e)}var ot=r({tag:"div",base:"klods-prose"}),st=r({tag:"span",base:"klods-muted"}),rt=r({tag:"p",base:"klods-lead"}),nt=r({tag:"table",base:"klods-table",modifiers:{striped:"klods-table--striped",dense:"klods-table--dense"}}),lt=(t,e)=>l("thead",t??{},e),dt=(t,e)=>l("tbody",t??{},e),it=(t,e)=>l("tr",t??{},e),at=(t,e)=>l("th",t??{},e),ct=(t,e)=>l("td",t??{},e);function pt(t,e){return l("pre",t??{},l("code",{},e))}function ut(t,e){return l("code",t??{},e)}var ft=r({tag:"div",base:"klods-box"});var gt=r({tag:"div",base:"klods-page",modifiers:{sidebar:"klods-page--with-sidebar",sidebarPosition:t=>t==="trailing"?"klods-page--sidebar-trailing":void 0,stickyHeader:"klods-page--sticky-header"}}),bt=r({tag:"header",base:"klods-header"}),ht=r({tag:"aside",base:"klods-sidebar"}),Kt=r({tag:"main",base:"klods-content",modifiers:{narrow:"klods-content--narrow"}}),kt=r({tag:"footer",base:"klods-footer"}),mt=r({tag:"section",base:"klods-section"}),f=t=>e=>e===void 0?void 0:`${t}--gap-${e}`,xt=r({tag:"div",base:"klods-stack",modifiers:{gap:f("klods-stack")}}),Ct=r({tag:"div",base:"klods-cluster",modifiers:{gap:f("klods-cluster")}}),yt=r({tag:"div",base:"klods-row",modifiers:{gap:f("klods-row"),inline:"klods-row--inline"}}),At=r({tag:"div",base:"klods-grid",modifiers:{gap:f("klods-grid"),cols:t=>t===void 0?void 0:`klods-grid--cols-${t}`,fit:"klods-grid--fit"}}),Pt=r({tag:"div",base:"klods-center"}),vt=r({tag:"div",base:"klods-spread"});function wt(t){return new d("span",{},[String(t)])}var Nt=r({tag:"span",base:"klods-push"}),St=r({tag:"div",base:"klods-fill"});return _($t);})();
1
+ "use strict";var Klods=(()=>{var m=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var B=(e,t,s)=>t in e?m(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s;var I=(e,t)=>{for(var s in t)m(e,s,{get:t[s],enumerable:!0})},G=(e,t,s,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of E(t))!q.call(e,r)&&r!==s&&m(e,r,{get:()=>t[r],enumerable:!(o=j(t,r))||o.enumerable});return e};var H=e=>G(m({},"__esModule",{value:!0}),e);var C=(e,t,s)=>B(e,typeof t!="symbol"?t+"":t,s);var Ve={};I(Ve,{KlodsNode:()=>g,alert:()=>le,badge:()=>re,box:()=>Re,builder:()=>n,button:()=>oe,buttonGroup:()=>z,card:()=>X,cardBody:()=>ee,cardFooter:()=>te,cardTitle:()=>Y,center:()=>Me,checkbox:()=>Pe,classNames:()=>f,cluster:()=>Ge,codeBlock:()=>$e,content:()=>Ee,el:()=>l,field:()=>xe,fill:()=>ze,footer:()=>qe,form:()=>Ke,grid:()=>Oe,header:()=>_e,inlineCode:()=>Te,input:()=>me,lead:()=>ae,mergeClasses:()=>T,muted:()=>ie,nav:()=>W,navLink:()=>U,navList:()=>F,option:()=>Ae,page:()=>Le,prose:()=>de,push:()=>Fe,radio:()=>we,radioGroup:()=>Ne,raw:()=>M,row:()=>He,section:()=>Be,select:()=>ye,sidebar:()=>je,spread:()=>De,stack:()=>Ie,switchInput:()=>Se,table:()=>ue,tbody:()=>fe,td:()=>he,text:()=>We,textCenter:()=>ce,textarea:()=>ve,th:()=>be,thead:()=>pe,toc:()=>V,tocItem:()=>Z,tocLink:()=>J,tr:()=>ge});var O=new Set(["area","base","br","col","embed","hr","img","input","link","meta","source","track","wbr"]),$=Symbol("klods.raw");function M(e){return{[$]:!0,html:e}}function w(e){return typeof e=="object"&&e!==null&&e[$]===!0}function D(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function v(e){return e.replace(/&/g,"&amp;").replace(/"/g,"&quot;")}function f(e){return e?typeof e=="string"?e.trim():Array.isArray(e)?e.filter(Boolean).join(" ").trim():Object.entries(e).filter(([,t])=>!!t).map(([t])=>t).join(" ").trim():""}function T(...e){return e.map(t=>f(t)).filter(Boolean).join(" ")}function N(e){return typeof e=="string"?e:Object.entries(e).filter(([,t])=>t!=null&&t!=="").map(([t,s])=>`${t.replace(/[A-Z]/g,o=>`-${o.toLowerCase()}`)}:${String(s)}`).join(";")}function S(e){let t=[],s=Array.isArray(e)?[...e]:[e];for(;s.length;){let o=s.shift();Array.isArray(o)?s.unshift(...o):o!=null&&o!==!1&&o!==!0&&t.push(o)}return t}var g=class e{constructor(t,s={},o=[]){C(this,"tag");C(this,"attrs");C(this,"children");this.tag=t,this.attrs=s,this.children=Array.isArray(o)?o:[o]}render(t){let s=document.createElement(this.tag);for(let[o,r]of Object.entries(this.attrs))if(!(r==null||r===!1)&&o!=="children"){if(o==="class"){let d=f(r);d&&s.setAttribute("class",d);continue}if(o==="style"){s.setAttribute("style",N(r));continue}if(o.startsWith("on")&&typeof r=="function"){s.addEventListener(o.slice(2).toLowerCase(),r);continue}if(r===!0){s.setAttribute(o,"");continue}s.setAttribute(o,String(r))}for(let o of S(this.children))if(o instanceof e)s.appendChild(o.render());else if(typeof o=="object"&&o!==null&&"nodeType"in o)s.appendChild(o);else if(w(o)){let r=document.createElement("template");r.innerHTML=o.html,s.appendChild(r.content)}else s.appendChild(document.createTextNode(String(o)));return t&&t.appendChild(s),s}toString(){let t=[`<${this.tag}`];for(let[s,o]of Object.entries(this.attrs))if(!(o==null||o===!1)&&s!=="children"&&!(s.startsWith("on")&&typeof o=="function")){if(s==="class"){let r=f(o);r&&t.push(` class="${v(r)}"`);continue}if(s==="style"){t.push(` style="${v(N(o))}"`);continue}if(o===!0){t.push(` ${s}`);continue}t.push(` ${s}="${v(String(o))}"`)}if(O.has(this.tag))return t.push(" />"),t.join("");t.push(">");for(let s of S(this.children))s instanceof e?t.push(s.toString()):w(s)?t.push(s.html):typeof s=="object"&&s!==null&&"outerHTML"in s?t.push(s.outerHTML):t.push(D(String(s)));return t.push(`</${this.tag}>`),t.join("")}};function l(e,t={},s=[]){return new g(e,t,s)}function n(e){let{tag:t,base:s,modifiers:o={}}=e,r=o;return(d,u)=>{let c=d??{},p=[],i={};for(let[k,h]of Object.entries(c)){let K=r[k];if(K!==void 0)if(typeof K=="function"){let x=K(h);x&&p.push(x)}else h&&p.push(K);else i[k]=h}let b=T(s,...p,c.class),a=u!==void 0?u:c.children??[];return delete i.children,new g(t,{...i,class:b||void 0},a)}}var W=n({tag:"nav",base:"klods-nav"}),F=n({tag:"ul",base:"klods-nav__list"}),z=n({tag:"div",base:"klods-button-group"}),V=n({tag:"ul",base:"klods-toc",modifiers:{sub:"klods-toc--sub"}}),Z=(e,t)=>l("li",e??{},t),J=(e,t)=>l("a",e??{},t),Q=n({tag:"a",base:"klods-nav__link",modifiers:{active:"klods-nav__link--active"}});function U(e,t){return l("li",{},[Q(e??null,t)])}var X=n({tag:"div",base:"klods-card",modifiers:{elevated:"klods-card--elevated"}}),Y=n({tag:"h3",base:"klods-card__title"}),ee=n({tag:"div",base:"klods-card__body"}),te=n({tag:"div",base:"klods-card__footer"}),se=n({tag:"button",base:"klods-button",modifiers:{variant:e=>e&&e!=="default"?`klods-button--${e}`:void 0}});function oe(e,t){let s={type:"button",...e??{}};return se(s,t)}var re=n({tag:"span",base:"klods-badge",modifiers:{variant:e=>e&&e!=="default"?`klods-badge--${e}`:void 0}}),ne=n({tag:"div",base:"klods-alert",modifiers:{variant:e=>e&&e!=="default"?`klods-alert--${e}`:void 0}});function le(e,t){let s={role:"alert",...e??{}};return ne(s,t)}var de=n({tag:"div",base:"klods-prose"}),ie=n({tag:"span",base:"klods-muted"}),ae=n({tag:"p",base:"klods-lead"}),ce=n({tag:"div",base:"klods-text-center"}),ue=n({tag:"table",base:"klods-table",modifiers:{striped:"klods-table--striped",dense:"klods-table--dense"}}),pe=(e,t)=>l("thead",e??{},t),fe=(e,t)=>l("tbody",e??{},t),ge=(e,t)=>l("tr",e??{},t),be=(e,t)=>l("th",e??{},t),he=(e,t)=>l("td",e??{},t);function P(e,t){let s=t??"",o=s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"");if(o)return`${e}-${o}`;let r=5381;for(let d=0;d<s.length;d++)r=(r<<5)+r+s.charCodeAt(d)|0;return`${e}-${(r>>>0).toString(36)}`}var Ke=n({tag:"form",base:"klods-form"}),R=new Set(["input","select","textarea"]);function ke(e,t){if(R.has(e.tag))return new g(e.tag,{...e.attrs,...t},e.children);let s=e.children.map(o=>o instanceof g&&R.has(o.tag)?new g(o.tag,{...o.attrs,...t},o.children):o);return new g(e.tag,e.attrs,s)}function xe(e,t){let{label:s,id:o,help:r,error:d,required:u,invalid:c,class:p,...i}=e,b=o??P("klods-field",s),a=r?`${b}-help`:void 0,k=d?`${b}-error`:void 0,h=c??!!d,K=h?k:a,x=t(b),L=ke(x,{...K?{"aria-describedby":K}:{},...h?{"aria-invalid":"true"}:{}}),_=f(["klods-field",h?"klods-field--invalid":"",f(p)]),A=[l("label",{for:b,class:`klods-label${u?" klods-label--required":""}`},s),L];return r&&A.push(l("p",{id:a,class:"klods-help"},r)),d&&A.push(l("p",{id:k,class:"klods-error",role:"alert"},d)),l("div",{...i,class:_||void 0},A)}function me(e){let{type:t,class:s,oninput:o,...r}=e,d=c=>f(["klods-input",c,f(s)])||void 0,u=r.id??P("klods-input",r["aria-label"]??r.placeholder??t??"field");if(t==="range"){let c=r.value??"50";return l("span",{class:d("klods-input--range")},[l("input",{type:"range",...r,id:u,oninput:p=>{let i=p.target;i.closest(".klods-input--range")?.querySelector("output")?.textContent!==void 0&&(i.closest(".klods-input--range").querySelector("output").textContent=i.value),o?.(p)}}),l("output",{for:u},c)])}if(t==="color"){let c=r.value??"#000000";return l("span",{class:d("klods-input--color")},[l("input",{type:"color",...r,id:u,oninput:p=>{let i=p.target;i.closest(".klods-input--color")?.querySelector("output")?.textContent!==void 0&&(i.closest(".klods-input--color").querySelector("output").textContent=i.value),o?.(p)}}),l("output",{for:u},c)])}return new g("input",{type:t,...r,id:u,class:d("")})}var Ce=n({tag:"select",base:"klods-select"});function ye(e,t){return l("div",{class:"klods-select-wrapper"},Ce(e,t))}var Ae=(e,t)=>l("option",e??{},t),ve=n({tag:"textarea",base:"klods-textarea"});function Pe(e){let{label:t,name:s,value:o,checked:r,disabled:d,required:u,form:c,autofocus:p,class:i,...b}=e,a={type:"checkbox"};return s!==void 0&&(a.name=s),o!==void 0&&(a.value=o),r&&(a.checked=!0),d&&(a.disabled=!0),u&&(a.required=!0),c!==void 0&&(a.form=c),p&&(a.autofocus=!0),l("label",{...b,class:f(["klods-checkbox",f(i)])||void 0},[l("input",a),l("span",{},t)])}function we(e){let{label:t,name:s,value:o,checked:r,disabled:d,required:u,form:c,autofocus:p,class:i,...b}=e,a={type:"radio"};return s!==void 0&&(a.name=s),o!==void 0&&(a.value=o),r&&(a.checked=!0),d&&(a.disabled=!0),u&&(a.required=!0),c!==void 0&&(a.form=c),p&&(a.autofocus=!0),l("label",{...b,class:f(["klods-radio",f(i)])||void 0},[l("input",a),l("span",{},t)])}function Ne(e,t){let{legend:s,class:o,...r}=e,d=s?P("klods-rg",s):void 0,u=f(["klods-field",f(o)])||void 0;return l("div",{...r,class:u,role:"group",...d?{"aria-labelledby":d}:{}},[s?l("p",{id:d,class:"klods-label"},s):null,...t])}function Se(e){let{label:t,name:s,value:o,checked:r,disabled:d,reverse:u,class:c,...p}=e,i={type:"checkbox",class:"klods-switch__input",role:"switch"};return s!==void 0&&(i.name=s),o!==void 0&&(i.value=o),r&&(i.checked=!0),d&&(i.disabled=!0),l("label",{...p,class:f(["klods-switch",u?"klods-switch--reverse":"",f(c)])||void 0},[l("input",i),l("span",{class:"klods-switch__track"}),l("span",{class:"klods-switch__label"},t)])}function $e(e,t){return l("pre",e??{},l("code",{},t))}function Te(e,t){return l("code",e??{},t)}var Re=n({tag:"div",base:"klods-box"});var Le=n({tag:"div",base:"klods-page",modifiers:{sidebar:"klods-page--with-sidebar",sidebarPosition:e=>e==="trailing"?"klods-page--sidebar-trailing":void 0,stickyHeader:"klods-page--sticky-header"}}),_e=n({tag:"header",base:"klods-header"}),je=n({tag:"aside",base:"klods-sidebar"}),Ee=n({tag:"main",base:"klods-content",modifiers:{narrow:"klods-content--narrow"}}),qe=n({tag:"footer",base:"klods-footer"}),Be=n({tag:"section",base:"klods-section"}),y=e=>t=>t===void 0?void 0:`${e}--gap-${t}`,Ie=n({tag:"div",base:"klods-stack",modifiers:{gap:y("klods-stack")}}),Ge=n({tag:"div",base:"klods-cluster",modifiers:{gap:y("klods-cluster")}}),He=n({tag:"div",base:"klods-row",modifiers:{gap:y("klods-row"),inline:"klods-row--inline"}}),Oe=n({tag:"div",base:"klods-grid",modifiers:{gap:y("klods-grid"),cols:e=>e===void 0?void 0:`klods-grid--cols-${e}`,fit:"klods-grid--fit"}}),Me=n({tag:"div",base:"klods-center"}),De=n({tag:"div",base:"klods-spread"});function We(e){return new g("span",{},[String(e)])}var Fe=n({tag:"span",base:"klods-push"}),ze=n({tag:"div",base:"klods-fill"});return H(Ve);})();
2
2
  //# sourceMappingURL=klods.umd.js.map