npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@texaryn/react-bootstrap

v0.8.0

Published

Bootstrap 5 widgets for Texaryn: native markup and Bootstrap classes on top of @texaryn/react

Downloads

1,030

Readme

@texaryn/react-bootstrap

Bootstrap 5 widgets for Texaryn: native HTML with Bootstrap classes, on top of @texaryn/react.

Status: pre-1.0. Public APIs may change before 1.0.

Install

pnpm add @texaryn/core @texaryn/schema-json @texaryn/react @texaryn/react-bootstrap react react-dom bootstrap

@texaryn/react and react (18 or newer) are peer dependencies. bootstrap is an optional peer (^5.3) that records the compatible Bootstrap line: the package reads no Bootstrap JavaScript and imports no stylesheet, so the page loads Bootstrap 5.3 CSS itself, either from the installed bootstrap package as the quick start does, or from a CDN link, in which case bootstrap can be left out of the install.

Quick start

Swap createDefaultRegistry() for createBootstrapRegistry(). Nothing else about the form changes:

import { createJsonSchemaAdapter } from '@texaryn/schema-json'
import { FormProvider, FormRoot, ErrorSummary, useForm } from '@texaryn/react'
import { createBootstrapRegistry } from '@texaryn/react-bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'

// schema as in the @texaryn/react quick start
const adapter = await createJsonSchemaAdapter(schema)
const registry = createBootstrapRegistry()

function App() {
  const form = useForm(adapter, { initialData: { name: '' } })

  return (
    <FormProvider value={form.runtime}>
      <ErrorSummary />
      <FormRoot registry={registry} />
    </FormProvider>
  )
}

The CSS import above assumes a bundler that resolves stylesheet imports. A page without one adds the equivalent <link> tag instead.

What this package renders

createBootstrapRegistry() returns a RendererRegistry<WidgetComponent> with seven widgets. Each field widget sits in a mb-3 wrapper, adds is-invalid to its control while the field shows errors, and renders the description as form-text and every visible error as invalid-feedback d-block inside the binding's live region, which stays mounted and empty while the field is valid.

| Widget | Node it matches | Classes | | --- | --- | --- | | BootstrapTextInput | string field with no enum | form-label, form-control with type="text" | | BootstrapNumberInput | number or integer field | form-label, form-control with type="number" | | BootstrapTextarea | field with the textarea widget hint | form-label, form-control | | BootstrapSelect | field with enum values | form-label, form-select | | BootstrapCheckbox | boolean field | form-check, form-check-input, form-check-label | | BootstrapObjectLayout | object container | a nested object is a fieldset named by its legend; the root is a plain div | | BootstrapArrayControl | array container | btn btn-primary to add, btn btn-outline-secondary btn-sm to move up or down when canReorder is true, btn btn-outline-danger btn-sm to remove |

Enum outranks the primitive type, so a string field with an enum renders as a select, and the textarea hint outranks both.

invalid-feedback is hidden by Bootstrap unless it directly follows an .is-invalid sibling. The error lines sit inside the live region rather than beside the control, so each one carries d-block.

Composing your own registry

Every widget is exported, so a registry can mix these with your own. A widget is markup around useFieldBinding, which supplies the label, description, display-gated errors and a DOM surface to spread: domInputProps for text, number, textarea and select controls, domCheckboxProps for checkboxes.

import { createRendererRegistry } from '@texaryn/core'
import type { FieldNode, UINode } from '@texaryn/core'
import { useFieldBinding } from '@texaryn/react'
import type { WidgetComponent } from '@texaryn/react'
import { BootstrapTextInput, BootstrapObjectLayout } from '@texaryn/react-bootstrap'

function EmailInput({ node }: { node: UINode }) {
  const field = useFieldBinding(node as FieldNode)
  return (
    <div className="mb-3">
      <label {...field.labelProps} className="form-label">{field.label}</label>
      <input {...field.domInputProps} type="email" className="form-control" />
    </div>
  )
}

const registry = createRendererRegistry<WidgetComponent>()
registry.register({ test: (n) => n.type === 'container' && n.containerType === 'object', rank: 1 }, BootstrapObjectLayout)
registry.register({ test: (n) => n.type === 'field' && n.fieldType === 'string', rank: 1 }, BootstrapTextInput)
registry.register({ test: (n) => n.type === 'field' && n.format === 'email', rank: 10 }, EmailInput)

BootstrapFeedback is exported too, so a custom widget can render the same description and error block as the built-in ones.

What this package does not do

  • It does not depend on react-bootstrap or any other component library. The widgets render input, select, textarea, label, div and button elements directly.
  • It does not load or bundle Bootstrap CSS. The page is responsible for having Bootstrap 5.3 on it; without the stylesheet the form still works and still carries the classes, it is just unstyled.
  • It does not load Bootstrap's JavaScript. No widget uses a Bootstrap component that needs it.
  • It does not own form state. Values, validation, touched state and error display all come from the runtime through @texaryn/react.

Related packages

See the repository README for the complete architecture.

License

Apache-2.0