Observable Inputs

repository·main·Indexed 41 days ago

https://github.com/observablehq/inputs

A lightweight JavaScript library (v0.12.0) providing interactive UI components such as sliders, buttons, tables, and checkboxes. Designed for high reactivity, it integrates seamlessly with Observable Framework and Observable notebooks, returning HTML elements that expose a .value property and emit input events.

Tokens
10.5K
Snippets
33
Records
42
Agent score
51%

What's inside Observable Inputs

  1. What are Observable Inputs and how do they work

    main

    Observable Inputs are lightweight UI components (buttons, sliders, dropdowns, etc.) used to build interactive displays.

    Core Behavior:

    • Each input returns an HTML element.
    • The element exposes a .value property that reflects the current state.
    • The element emits an input event whenever the value changes.

    This makes them compatible with standard DOM event listeners and reactive frameworks.

  2. Use Observable Inputs in Observable Framework

    main

    In Observable Framework, use the view function to display an input and expose its value as a top-level reactive variable. This allows other code cells to automatically re-run when the input value changes.

    const x = view(Inputs.range([0, 100]));
  3. Use Observable Inputs in a vanilla web environment

    main

    To use Observable Inputs in a standard web page without a build step, load the CSS from a CDN and import the library as an ES module. You can then create an input, append it to the DOM, and listen for the input event to react to changes.

    <!DOCTYPE html>
    <body>
    <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@observablehq/inputs@0.12/dist/index.css">
    <script type="module">
    
    import * as Inputs from "https://cdn.jsdelivr.net/npm/@observablehq/inputs@0.12/+esm";
    
    // Create a numeric slider allowing a value between 0 and 100 (inclusive).
    const slider = Inputs.range([0, 100], {label: "x"});
    
    // Display the slider on the page.
    document.body.append(slider);
    
    // Listen and respond to the user dragging the slider.
    slider.addEventListener("input", (event) => {
      console.log(event.target.value);
    });
    
    </script>
    </body>
    </html>
  4. Use Observable Inputs API

    main

    The @observablehq/inputs library provides a collection of UI input components and utility functions for handling user input, formatting, and data binding. You can import specific input types (like button, checkbox, range, text, etc.) or utility functions (like form, bind, and disposal) directly from the package.

    import {
      button, 
      checkbox, 
      range, 
      text, 
      form, 
      bind
    } from "@observablehq/inputs";
  5. How search filtering works

    main

    The search component uses two primary filtering strategies depending on whether columns are provided:

    1. Global Search (searchFilter)

    When no columns are specified, searchFilter performs a multi-term search. It splits the query by whitespace and ensures that every term matches at least one property value in the data object. It uses a case-insensitive regular expression that matches terms at word boundaries or start of strings.

    2. Column-Specific Search (columnFilter)

    When columns are provided, the component uses columnFilter. This restricts the search to only the specified keys. For a match to occur, every term in the query must match at least one of the specified columns.

    Custom Filters

    You can provide a custom filter function in the options. The function should follow the signature: (query) => (item) => boolean.

  6. Format and align table columns

    main

    You can customize how data is displayed in each column using the format and align options.

    Formatting: Pass an object where keys are column names and values are functions that take (value, index, data) and return a string or a Node.

    Alignment: Pass an object where keys are column names and values are one of "left", "right", or "center".

    Automatic Type Detection: If you don't provide a formatter, the table attempts to detect types (number, date, etc.) and applies locale-aware formatting based on the provided locale option.

    const options = {
      format: {
        // Custom string formatting
        price: (d) => `$${d.toFixed(2)}`,
        // Returning an HTML element
        status: (d) => {
          const el = document.createElement("span");
          el.textContent = d;
          el.style.color = d === "Active" ? "green" : "red";
          return el;
        }
      },
      align: {
        price: "right",
        status: "center"
      }
    };
    
    const myTable = table(data, options);
  7. Use Inputs.range and Inputs.number for numeric input

    main

    Inputs.range

    Specifies a number within an extent [min, max]. Users can use a slider or type a number.

    Options:

    • label: String or HTML element.
    • step: The interval between values.
    • format: Function to format the number (defaults to formatTrim).
    • placeholder: Placeholder for empty input.
    • transform: Non-linear transform function.
    • invert: Inverse of transform (strongly recommended if transform is used).
    • validate: Function to check if the input is valid.
    • value: Initial value (defaults to (min + max) / 2).
    • width: Width of the input.
    • disabled: Boolean to disable.

    Inputs.number

    Equivalent to Inputs.range, but the slider is suppressed, showing only a number input. If no extent is provided, it defaults to [-Infinity, Infinity].

    // Range slider
    Inputs.range([0, 100], {step: 1, label: "Intensity"})
    
    // Number input only
    Inputs.number({step: 0.1, label: "Precision"})
  8. Use Inputs.text and Inputs.textarea for freeform text

    main

    Inputs.text

    Single-line text input.

    • Immediate vs Deliberate: By default, it reports value immediately. Set submit: true to wait for the Enter key or a button click.
    • Types: Can be configured via type (e.g., password, email, tel, url, color).
    • Options: label, placeholder, pattern, minlength, maxlength, min, max, required, validate, submit, datalist.

    Inputs.textarea

    Multi-line text input.

    • Options: label, value, placeholder, rows, resize (boolean), monospace (boolean), submit, validate.
    Inputs.text({label: "Name", placeholder: "Enter your name"})
    
    Inputs.textarea({label: "Biography", placeholder: "Tell us about yourself..."})
  9. Use Inputs.search for full-text filtering

    main

    The Inputs.search allows freeform, full-text search of an in-memory tabular dataset (array of objects) or an iterable of values (array of strings). The value is an array of elements that match the query. If the query is empty, all elements are returned.

    Tabular Search: By default, all properties of objects in data are searched. Use the columns option to limit search to specific properties.

    Options:

    • label: String or HTML element.
    • query: Initial search terms.
    • placeholder: Placeholder for empty query.
    • columns: Array of property names to search.
    • filter: A factory function that returns a filter function (element, index) => boolean.
    • format: Function to show the number of results.
    • required: If true, value is all data when query is empty (defaults to true).
    • datalist: Iterable of suggested values.
    // Search in tabular data with specific columns
    Inputs.search(athletes, {label: "Athletes", columns: ["sport", "nationality"]})
    
    // Search in a simple array of strings
    Inputs.search(["Alabama", "Alaska", "Arizona"], {label: "State"})
  10. Use Inputs.checkbox for multi-selection

    main

    The Inputs.checkbox allows users to select any number of values from a provided iterable data. The value is an array of the selected elements.

    Customizing Display and Values:

    • Use keyof to define how an element is displayed.
    • Use valueof to define what value is returned when selected.
    • If data is a Map, keyof defaults to the key and valueof defaults to the value.
    • Use sort (true, "ascending", "descending", or a comparator) and unique (true) to organize the list.
    • Use format to customize the display of elements.

    Options:

    • label: String or HTML element.
    • sort: Sorting configuration.
    • unique: Boolean to show only unique keys.
    • locale: Current locale (defaults to English).
    • format: Function to format elements.
    • keyof: Function to extract the display key.
    • valueof: Function to extract the value.
    • value: Initial array of selected elements.
    • disabled: Boolean or array of disabled values.
    // Basic checkbox
    Inputs.checkbox(["Salty", "Spicy", "Sour", "Umami"], {label: "Flavor"})
    
    // Using a Map (e.g., from d3.group)
    Inputs.checkbox(d3.group(athletes, (d) => d.sport))