OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
 
master @ 88 LINES
 
[ HISTORY ]  [ UP ]
 

---
import Pre from "../Pre/Pre.astro";
import TextField from "../TextField/TextField.astro";
import Select from "../Select/Select.astro";
import { selectWidth } from "../Select/Select";
import Radio from "../Radio/Radio.astro";
import { radioWidth } from "../Radio/Radio";
import Checkbox from "../Checkbox/Checkbox.astro";
import { checkboxWidth } from "../Checkbox/Checkbox";
import Button from "../Button/Button.astro";
import { buttonWidth } from "../Button/Button";
import { G, checkGrid, len, pad } from "../../lib/ascii";
import { MOBILE_FRAME_W } from "../../lib/config";
import { formGeometry, FORM_LABEL_W, FORM_INDENT, type Props } from "./FormFrame";
import "./FormFrame.scss";

const { title, fields, width = MOBILE_FRAME_W, action, method } = Astro.props as P
rops;
const { inner, contentW, defaultCells, textareaCells } = formGeometry(width);

const ctx = `FormFrame(${title})`;
const open = `${G.V}${" ".repeat(FORM_INDENT)}`;
const close = (used: number) => `${" ".repeat(Math.max(0, contentW - used))}${G.V}
`;
const lbl = (s: string) => pad(s, FORM_LABEL_W);

const top = checkGrid(
  `${G.TL}${G.H} ${title} ${G.H.repeat(Math.max(0, inner - 3 - len(title)))}${G.TR
}`,
  width,
  ctx,
);
const blank = `${G.V}${" ".repeat(inner)}${G.V}`;
const bottom = `${G.BL}${G.H.repeat(inner)}${G.BR}`;
---
<form class="form-frame" action={action} method={method}>
  <Pre>{top}</Pre>
  <Pre>{blank}</Pre>
  {fields.map((f) => {
    if (f.kind === "gap") return <Pre>{blank}</Pre>;

    if (f.kind === "text" || f.kind === "password") {
      const cells = f.cells ?? defaultCells;
      return <Pre>{open}{lbl(f.label)}<TextField name={f.name} cells={cells} type=
{f.kind} />{close(FORM_LABEL_W + cells)}</Pre>;
    }

    if (f.kind === "select") {
      const cells = f.cells ?? defaultCells - 6;
      return <Pre>{open}{lbl(f.label)}<Select name={f.name} options={f.options} ce
lls={cells} value={f.value} />{close(FORM_LABEL_W + selectWidth(cells))}</Pre>;
    }

    if (f.kind === "radios") {
      return f.options.map((opt, i) => (
        <Pre>{open}{i === 0 ? lbl(f.label) : " ".repeat(FORM_LABEL_W)}<Radio label
={opt} name={f.name} value={opt.toLowerCase()} checked={f.value === opt} />{close(
FORM_LABEL_W + radioWidth(opt))}</Pre>
      ));
    }

    if (f.kind === "checkbox") {
      return <Pre>{open}<Checkbox label={f.label} name={f.name} checked={f.checked
} />{close(checkboxWidth(f.label))}</Pre>;
    }

    if (f.kind === "textarea") {
      const rows = f.rows ?? 4;
      return (
        <Fragment>
          <Pre>{open}{checkGrid(f.label, contentW, ctx)}{close(len(f.label))}</Pre
>
          <div class="form-textarea">
            {Array.from({ length: rows }, () => (
              <Pre>{blank}</Pre>
            ))}
            <textarea
              name={f.name}
              rows={rows}
              spellcheck="false"
              aria-label={f.label}
              style={`left: calc(var(--cell-w) * ${1 + FORM_INDENT}); width: calc(
var(--cell-w) * ${textareaCells}); height: calc(var(--cell-h) * ${rows})`}
            ></textarea>
          </div>
        </Fragment>
      );
    }

    const used = f.buttons.reduce((s, b, i) => s + buttonWidth(b.label) + (i ? 2 :
 0), 0);
    return <Pre>{open}{f.buttons.map((b, i) => (
      <Fragment>{i > 0 ? "  " : ""}<Button label={b.label} type={b.type ?? "button
"} variant={b.variant} /></Fragment>
    ))}{close(used)}</Pre>;
  })}
  <Pre>{blank}</Pre>
  <Pre>{bottom}</Pre>
</form>

---
import Pre from "../Pre/Pre.astro";
import TextField from "../TextField/TextFiel
d.astro";
import Select from "../Select/Select.astro";
import { selectWidth } from "../Select/Selec
t";
import Radio from "../Radio/Radio.astro";
import { radioWidth } from "../Radio/Radio";
import Checkbox from "../Checkbox/Checkbox.a
stro";
import { checkboxWidth } from "../Checkbox/C
heckbox";
import Button from "../Button/Button.astro";
import { buttonWidth } from "../Button/Butto
n";
import { G, checkGrid, len, pad } from "../.
./lib/ascii";
import { MOBILE_FRAME_W } from "../../lib/co
nfig";
import { formGeometry, FORM_LABEL_W, FORM_IN
DENT, type Props } from "./FormFrame";
import "./FormFrame.scss";

const { title, fields, width = MOBILE_FRAME_
W, action, method } = Astro.props as Props;
const { inner, contentW, defaultCells, texta
reaCells } = formGeometry(width);

const ctx = `FormFrame(${title})`;
const open = `${G.V}${" ".repeat(FORM_INDENT
)}`;
const close = (used: number) => `${" ".repea
t(Math.max(0, contentW - used))}${G.V}`;
const lbl = (s: string) => pad(s, FORM_LABEL
_W);

const top = checkGrid(
  `${G.TL}${G.H} ${title} ${G.H.repeat(Math.
max(0, inner - 3 - len(title)))}${G.TR}`,
  width,
  ctx,
);
const blank = `${G.V}${" ".repeat(inner)}${G
.V}`;
const bottom = `${G.BL}${G.H.repeat(inner)}$
{G.BR}`;
---
<form class="form-frame" action={action} met
hod={method}>
  <Pre>{top}</Pre>
  <Pre>{blank}</Pre>
  {fields.map((f) => {
    if (f.kind === "gap") return <Pre>{blank
}</Pre>;

    if (f.kind === "text" || f.kind === "pas
sword") {
      const cells = f.cells ?? defaultCells;
      return <Pre>{open}{lbl(f.label)}<TextF
ield name={f.name} cells={cells} type={f.kin
d} />{close(FORM_LABEL_W + cells)}</Pre>;
    }

    if (f.kind === "select") {
      const cells = f.cells ?? defaultCells 
- 6;
      return <Pre>{open}{lbl(f.label)}<Selec
t name={f.name} options={f.options} cells={c
ells} value={f.value} />{close(FORM_LABEL_W 
+ selectWidth(cells))}</Pre>;
    }

    if (f.kind === "radios") {
      return f.options.map((opt, i) => (
        <Pre>{open}{i === 0 ? lbl(f.label) :
 " ".repeat(FORM_LABEL_W)}<Radio label={opt}
 name={f.name} value={opt.toLowerCase()} che
cked={f.value === opt} />{close(FORM_LABEL_W
 + radioWidth(opt))}</Pre>
      ));
    }

    if (f.kind === "checkbox") {
      return <Pre>{open}<Checkbox label={f.l
abel} name={f.name} checked={f.checked} />{c
lose(checkboxWidth(f.label))}</Pre>;
    }

    if (f.kind === "textarea") {
      const rows = f.rows ?? 4;
      return (
        <Fragment>
          <Pre>{open}{checkGrid(f.label, con
tentW, ctx)}{close(len(f.label))}</Pre>
          <div class="form-textarea">
            {Array.from({ length: rows }, ()
 => (
              <Pre>{blank}</Pre>
            ))}
            <textarea
              name={f.name}
              rows={rows}
              spellcheck="false"
              aria-label={f.label}
              style={`left: calc(var(--cell-
w) * ${1 + FORM_INDENT}); width: calc(var(--
cell-w) * ${textareaCells}); height: calc(va
r(--cell-h) * ${rows})`}
            ></textarea>
          </div>
        </Fragment>
      );
    }

    const used = f.buttons.reduce((s, b, i) 
=> s + buttonWidth(b.label) + (i ? 2 : 0), 0
);
    return <Pre>{open}{f.buttons.map((b, i) 
=> (
      <Fragment>{i > 0 ? "  " : ""}<Button l
abel={b.label} type={b.type ?? "button"} var
iant={b.variant} /></Fragment>
    ))}{close(used)}</Pre>;
  })}
  <Pre>{blank}</Pre>
  <Pre>{bottom}</Pre>
</form>
 
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET