haori-bootstrap
v0.5.5
Published
Bootstrap-based UI extension library for Haori.js.
Maintainers
Readme
Haori.js Bootstrap
Haori.js Bootstrap is a Bootstrap-based UI extension library for Haori.js.
Version: 0.5.5
Overview
- Official name: Haori.js Bootstrap
- Package identifier: haori-bootstrap
- Upstream Haori.js repository: https://github.com/meibinlab/haori-js
- GitHub repository: https://github.com/meibinlab/haori-js-bootstrap
- Supported Bootstrap version: 5.3.x
- Distributed formats: ESM and IIFE
The npm package has been renamed from haori-js-bootstrap to haori-bootstrap, and the previous package is now deprecated. Existing installations should migrate to the new package name. The GitHub repository name remains unchanged.
The library replaces Haori.js static UI methods such as dialog, confirm, toast, openDialog, closeDialog, addErrorMessage, and clearMessages with Bootstrap-based behavior while keeping existing Procedure integration intact.
Installation
Install from npm:
npm install haori-bootstrapThis package expects Haori.js and Bootstrap CSS/JS to be available in the application.
CDN Usage
Load dependencies in this order for browser direct loading:
- Haori.js
- Bootstrap CSS
- bootstrap.bundle.js
- haori-bootstrap
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
/>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/haori.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/haori-bootstrap.iife.js"></script>The IIFE build auto-enables when both window.Haori and window.bootstrap are available.
ESM Usage
The ESM build also auto-enables on import when window.Haori and window.bootstrap are available.
import 'haori-bootstrap';When you need to override default options, call install explicitly.
import { install } from 'haori-bootstrap';
install({
fallbackToNative: true,
runtime: 'demo',
});Public API
| API | Purpose | Return value |
| ---- | ---- | ---- |
| dialog(message) | Informational dialog | Promise |
| confirm(message) | Confirmation dialog | Promise |
| toast(message, level) | Toast notification | Promise |
| openDialog(element) | Open the target's modal (pass the .modal itself or a descendant; a non-.modal element resolves to its nearest ancestor .modal). Managed messages and is-invalid / is-valid state under the modal are cleared before it is shown, so a reopened form starts clean. | Promise |
| closeDialog(element) | Close the target's modal (pass the .modal itself or a descendant; a non-.modal element resolves to its nearest ancestor .modal) | Promise |
| addErrorMessage(target, message) | Append managed error messages | Promise |
| addMessage(target, message, level?) | Append a level-aware managed message ('error' | 'success' | 'warning' | 'info'). Switches Bootstrap validation classes (is-invalid / is-valid) on re-call. | Promise |
| clearMessages(parentOrTarget) | Remove only managed messages | Promise |
| install(options) | Re-apply Bootstrap-backed Haori with overridden options, including runtime | void |
| uninstall() | Restore the original Haori implementation | void |
install options
| Option | Type | Default | Description |
| ---- | ---- | ---- | ---- |
| toastPosition | 'top-start' \| 'top-center' \| 'top-end' \| 'bottom-start' \| 'bottom-center' \| 'bottom-end' | 'bottom-end' | Toast container position. The new position takes effect the next time a toast is shown. |
| toastDelay | number | Bootstrap default (5000ms) | Auto-hide delay in milliseconds for toast notifications. |
Procedure Integration Example
Existing Procedure flows can keep using data-click-* and data-click-*-message attributes.
<button
type="button"
data-click-confirm="deleteUser"
data-click-confirm-message="Delete this user?\nThis action cannot be undone."
>
Delete
</button>
<button
type="button"
data-click-toast="notifySaved"
data-click-toast-message="Saved successfully.\nPlease refresh the list."
>
Show saved toast
</button>- Messages are rendered as plain text, not HTML.
- Literal
\nsequences are normalized to line breaks for dialog, confirm, and toast. - Haori.js and Procedure remain responsible for interpreting data-click-* attributes and dispatching static method calls.
Persisting collapse state
Add data-haori-persist="key" to a Bootstrap collapse element to persist its open/closed state in sessionStorage and restore it on the next visit.
<button data-bs-toggle="collapse" data-bs-target="#sideMenu">Menu</button>
<div class="collapse" id="sideMenu" data-haori-persist="side-menu">
...
</div>- Listens to
shown.bs.collapse/hidden.bs.collapseand storesshown/hidden. install()restores existing elements and applies restoration to fragments inserted later (e.g. viadata-import) through aMutationObserver.- On restore it also syncs the associated toggles (
data-bs-toggle="collapse"whosedata-bs-target/hrefpoints to the collapse) — theiraria-expandedandcollapsedclass. Toggle syncing requires the collapse element to have anid. - State is keyed by the attribute value; reusing a key across elements shares their state.
- When storage is unavailable (e.g. private mode) the feature silently disables itself and never throws.
uninstall()removes the listeners and observer.
Passing row context to a shared modal
When you open a single shared Bootstrap modal from per-row buttons (inside data-each) and need the row's context (e.g. a target id or type) inside the modal, use Haori core's declarative data-{event}-copy. No hand-written show.bs.modal listener or per-row modal duplication is required.
data-{event}-copy copies binding values into the target element's scope and runs independently of data-{event}-fetch. When data-{event}-form is absent, the copy source is the trigger element's own / inherited binding data — i.e. the current row scope. data-{event}-copy-params selects which keys to forward (&-separated; a leading ! excludes), and existing keys on the target are preserved while same-named keys are overwritten.
<!-- Row button (inside data-each): open the shared modal and copy the row scope -->
<button
data-bs-toggle="modal"
data-bs-target="#acceptModal"
data-click-copy="#acceptModal"
data-click-copy-params="appealId&targetType"
>
Approve
</button>
<!-- Shared modal: give it data-bind to make it a scope root, then reference copied values -->
<div class="modal" id="acceptModal" data-bind="{}">
<input type="hidden" name="appealId" data-attr-value="{{appealId}}" />
<p>{{ targetType == 'account' ? 'Lift the suspension.' : 'Restore the content.' }}</p>
</div>data-{event}-copy/-copy-params/-copy-sourceare Haori core features (not specific to this package); see the haori-js documentation for full semantics.- Give the shared modal a
data-bind(an empty{}is fine) so it acts as a binding scope root the copied values merge into. - Wording can be branched on the copied keys directly in the modal via
{{ ... }}, so renaming/computing keys is usually unnecessary. - See
demo/modal-copy.htmlfor a working example.
Stable selectors for e2e
The elements rendered by dialog / confirm / toast carry stable identifier attributes that do not depend on wording or locale. In e2e tests (e.g. Playwright), prefer building selectors from these attributes instead of visible text or button names — they survive copy changes and localization.
| Element | Attribute | Value |
| ---- | ---- | ---- |
| Toast root | data-haori-toast | "true" |
| Toast level | data-haori-toast-level | "success" | "warning" | "error" | "info" |
| Toast dismiss button | data-haori-toast-dismiss | "true" |
| Toast container | data-haori-toast-container | "true" |
| Info dialog root | data-haori-dialog | "true" |
| Info dialog OK button | data-haori-dialog-ok | "true" |
| Confirm dialog root | data-haori-confirm | "true" |
| Confirm dialog OK button | data-haori-confirm-ok | "true" |
| Confirm dialog cancel button | data-haori-confirm-cancel | "true" |
| Dialog title | data-haori-dialog-title | "true" |
| Managed message container | data-haori-message-container | "true" |
// Operate the confirm dialog without depending on wording
await page.locator('[data-haori-confirm-ok="true"]').click();
// Assert the toast level
await expect(page.locator('[data-haori-toast="true"]').last())
.toHaveAttribute('data-haori-toast-level', 'success');These attributes are maintained as a stable public contract. Info dialogs (
data-haori-dialog) and confirm dialogs (data-haori-confirm) are distinguished by their root attribute.
Build & Publish
Local verification:
npm install
npm run compile
npm run test
npm run build
npm pack --dry-runRegular release flow:
npm version patch
git push origin main --follow-tagsAfter pushing, publish a GitHub Release from the generated version tag. The release workflow then publishes the package and uploads dist.zip automatically.
Example next patch release after 0.5.5:
# version becomes 0.5.6
npm version patch
git push origin main --follow-tagsCreate and publish the GitHub Release for the pushed tag such as 0.5.6.
Release automation:
npm version patchalso keeps the exportedversionconstant, README examples, CDN demo, and Playwright CDN checks in sync.- publish-on-release.yml builds the package and runs npm publish.
- release-archive.yml builds dist/ and uploads dist.zip to the same GitHub Release.
First release only:
- If the current version is not published yet, skip
npm version patchand create/push the tag for that version directly. - Create a granular npm access token with
Read and writepermission and register it as the repository secretNPM_TOKEN. - If npm account 2FA is enabled, create the token with bypass 2FA for write actions.
- The package does not need to be published already to create
NPM_TOKEN.
Example for the first 0.3.1 release after the package rename:
git push origin main
git tag 0.3.1
git push origin 0.3.1First release checklist:
- Confirm the npm package name
haori-bootstrapis still available. - Create and register
NPM_TOKENin GitHub repository secrets. - Run local verification and
npm pack --dry-run. - Push the release tag.
- Publish a GitHub Release from that tag.
Documents
- Japanese README: README.ja.md
- Initial design: [doc/Haori.js Bootstrap初期設計書.md](doc/Haori.js Bootstrap初期設計書.md)
- Browser demo procedure proposal: doc/ブラウザデモ時Procedure挙動仕様提案.md
- Changelog: CHANGELOG.md
Notes
- Bootstrap CSS and JS are provided by the application side.
- Haori.js is treated as a prerequisite and is not bundled into this package.
- Browser direct loading for CDN consumers uses dist/haori-bootstrap.iife.js.
- The published npm entry is dist/haori-bootstrap.js with types at dist/index.d.ts.
- Browser demo transport normalization is discussed in the proposal document above and is not part of the current public API.
