selectflat
v0.2.0
Published
A reimplementation of Fil's ObservableHQ selectFlat input.
Maintainers
Readme
selectflat
selectflat is a dependency-free browser ESM reimplementation of Fil's Observable notebook @fil/selectflat.
It keeps the same core interaction model:
- hover or focus an option to preview it
- click to commit it
- read the current state from
form.value - listen to
inputfor live previews andchangefor committed updates
Install
From npm:
npm install selectflatThen import it in your app:
import { selectFlat } from "selectflat";For local development in this repository, you can import the file directly:
import { selectFlat } from "./selectflat.js";Basic usage
<div id="app"></div>
<script type="module">
import { selectFlat } from "selectflat";
const control = selectFlat({
options: ["A", "B", "C", "D"],
value: "B",
output: true,
description: "your choice"
});
control.addEventListener("input", () => {
console.log("preview or current value", control.value);
});
document.querySelector("#app").append(control);
</script>Programmatic selection
You can set or reset the value from code:
import { selectFlat } from "selectflat";
const control = selectFlat({
options: ["A", "B", "C", "D"],
value: "C"
});
control.setValue("A");
control.resetValue();Setting control.value = "A" also updates the component and dispatches input and change.
Multiple selection
import { selectFlat } from "selectflat";
const control = selectFlat({
multiple: true,
value: ["warm", "bright"],
options: [
{ label: "warm", value: "warm" },
{ label: "cool", value: "cool" },
{ label: "bright", value: "bright" },
{ label: "muted", value: "muted" }
]
});
console.log(control.value); // ["warm", "bright"]When multiple: true, hovering an option previews that option together with the values that are already selected.
Custom layout
You can customize the square size and strip layout with the layout option:
import { selectFlat } from "selectflat";
const control = selectFlat({
value: "D",
layout: {
size: "1.4rem",
gap: "0.25rem",
direction: "row",
wrap: "nowrap"
},
options: ["A", "B", "C", "D", "E", "F"]
});Touch interaction
On touch devices:
- tap once to preview a value
- tap the same cell again to commit it
- drag across cells to preview continuously and commit on release
In multiple mode, drag gestures act like painting:
- start on an unselected cell to add cells across the drag path
- start on a selected cell to remove cells across the drag path
- forced and disabled cells are skipped
API
selectFlat(config) or selectFlat(optionsArray)
Config
options: array of primitive values or option objectsvalue: initial value, or an array whenmultiple: truetitle: optional heading shown above the controldescription: optional text shown next to the outputoutput: whentrue, show the current label next to the descriptionmultiple: whentrue, allow toggling several values and return an arraylayout: optional layout object controlling option size and arrangementsubmit: optional submit button label, ortruefor a defaultApplybutton
layout supports:
size: square width and height, as a CSS length or number of pixelsgap: spacing between cells, as a CSS length or number of pixelsdirection:row,row-reverse,column, orcolumn-reversewrap:true/false, orwrap,nowrap,wrap-reverse
Option objects support:
value: underlying value returned fromform.valuelabel: visible label used for tooltips and output textdisabled: disable selection for that optionforced: whenmultiple: true, keep this option selected and do not allow it to be toggled off
Return value
selectFlat() returns a <form> element with:
form.value: current value, or an array whenmultiple: trueform.initialValue: the initial committed valueform.options: normalized option snapshotform.layout: normalized layout snapshotform.output: the<output>node used whenoutput: trueform.setValue(value, options?): programmatically commit a valueform.resetValue(options?): restore the initial committed value
Both setValue() and resetValue() dispatch input and change by default. Pass { dispatch: false } to update silently.
Events
input: fires during hover and focus previews, and after committed updateschange: fires after committed click-based updates, programmatic updates, and resets
Notes
- This module is browser-only. It creates DOM nodes and expects
documentto exist. - The component injects scoped styles into the returned form, so no extra stylesheet is required.
- The control uses
touch-action: noneon the option strip so drag gestures work reliably on mobile. - This rewrite uses buttons instead of a styled native
<select>, but keeps the same flat strip interaction from the original notebook.
Examples
The demo page lives at examples/index.html.
To run it locally:
python3 -m http.serverThen open http://localhost:8000/examples/.
Publish
This package is configured as a plain ESM npm module. A typical publish flow is:
npm test
npm publishIf selectflat is already taken on npm, update the name field in package.json before publishing.
