@university/liascript-interactive-components (0.0.8-build.57)
Installation
@university:registry=npm install @university/liascript-interactive-components@0.0.8-build.57"@university/liascript-interactive-components": "0.0.8-build.57"About this package
LiaScript Interactive Components
Custom components for LiaScript built with the Web Components API.
π Quick Start
Authoring in a course
Just write the standardized HTML tags in your course content β no LiaScript macros, no imports:
<accordion-element allow-multiple="true">
<accordion-item title="Section 1" data-icon="Zap">Content</accordion-item>
</accordion-element>
How delivery works
This package is not consumed as one big markdown import anymore. It publishes a granular,
ready-to-run distribution; the course build pipeline scans each course, then bundles only the
components it actually uses (in the right language) into a plain .js loaded via LiaScript's
script: directive. No runtime markdown parsing, minimal bytes.
dist/
shared.js window.ICONS + window.LiaMarkdown + window.MarkdownMixin (loaded once)
manifest.json tag -> component folder + available languages (drives the build-time scanner)
components/
accordion.js English variant (styles.css + en strings inlined)
accordion.de.js German variant (same code body, German strings inlined)
Consumers read dist/manifest.json to map authored tags back to the files they need to include.
Component status
Every component declares a maturity status in its src/components/<folder>/meta.json:
{ "status": "shipped" }
shippedβ production-eligible. Included in course bundles as normal.experimentalβ built and tested in this repo (realdist/artifacts, runs undernpm test), but the course build pipeline excludes it from every bundle so it can never leak into a published course. To opt an experimental component into a local build, setINCLUDE_EXPERIMENTAL_COMPONENTS=1.
The status is emitted per component into dist/manifest.json (components.<folder>.status). A missing or
invalid meta.json defaults to shipped with a build warning. The build compiles all components
regardless of status β gating happens only at course-bundle time.
Experimental components (not bundled into courses yet): image-juxtapose-element,
parameter-sandbox-element.
π¦ Components
Comprehensive suite of interactive components available:
| Component | HTML Tag | Description | Use Case |
|---|---|---|---|
| Accordion | <accordion-element> |
Collapsible content sections | FAQs, course modules |
| Category Sorter | <category-sorter-element> |
Drag items into correct categories | Classification, grouping |
| Comparison | <comparison-element> |
Side-by-side comparison table | Evaluating trade-offs, pros/cons |
| Content Explorer | <content-explorer-element> |
Interactive expandable cards | Revealing detailed content |
| Content Slider | <content-slider-element> |
Slide through HTML content | Storytelling, timelines, presentations |
| Contrast Split | <contrast-split-element> |
"Before vs After" comparison | Old vs New, Legacy vs Modern |
| Fill Blanks | <fill-blanks-element> |
Drag words into sentence gaps | Language learning, comprehension |
| Flashcard | <flashcard-element> |
Single card - click to flip | Quick Q&A, definitions |
| Flashcard Deck | <flashcard-deck-element> |
Multiple cards with navigation | Study decks, vocabulary lists |
| Flow Circuit | <flow-circuit-element> |
Visual pipeline of lifecycles | Workflows, data pipelines |
| Hero Banner | <hero-banner-element> |
Image-heavy hero section with blur effect | Chapter intros, narrative entrance |
| Interaction Center | <interaction-center-element> |
Command lab terminal visualizer | Terminal commands, system logic |
| Labeled Image | <labeled-image-element> |
Interactive image with clickable hotspots | Diagrams, anatomy, maps |
| Level System | <levels-element> |
3D layered exploration | Stacks, architecture, layers |
| Logic Mapper | <logic-mapper-element> |
Map code to explanations | Code analysis, detailed breakdowns |
| Memory Match | <memory-element> |
Flip cards to find matching pairs | Associations, vocabulary |
| Quote | <quote-element> |
Visually styled quote | Key takeaways, citations |
| Refractive Split | <refractive-split-element> |
Split layout with glass overlay | Pedagogical resonance, visual authority |
| Roadmap | <roadmap-element> |
3D perspective roadmap | Learning paths, milestones |
| Scenario Chat | <scenario-chat-element> |
Branching dialogue simulator | Soft skills, roleplay |
| Sequence Quiz | <sequence-quiz-element> |
Drag to order items correctly | Processes, timelines, rankings |
| Stage Scroller | <stage-synced-scroller-element> |
Scrollytelling visualizer | Storytelling, progressive explanation |
| Stage Transition | <stage-transition-element> |
Perspective transition between stages | Evolution, scaling, growth |
| Tabs | <tabs-element> |
"Command-Deck" style tabbed content | Code examples, rich HTML content |
| Timeline | <timeline-element> |
Visual chronological timeline | History, project milestones |
| YouTube Card | <youtube-card-element> |
Styled YouTube link card | Video links, resources |
π οΈ Development
Build Commands
# Package all components into dist/ (per-component files + shared.js + manifest.json)
npm run build
# Rebuild on every source change
npm run watch
# Run the test suite (jsdom smoke + i18n checks for every component)
npm test
Testing
Every component has a co-located spec at src/components/<folder>/index.test.js. The suite
(jest + jsdom) builds dist/ once, then for each component asserts:
- its custom-element tag registers,
- a real fixture mounts and populates a shadow root without throwing,
- each language's built bundle inlines the expected strings (proves
{{COMPONENT_STRINGS}}injection per locale), and - the
locales/*.jsonfiles share identical keys (no drift between languages).
Each spec is a thin call to the shared harness (test/harness.js) β no per-component boilerplate:
const { defineComponentTests } = require('../../../test/harness');
defineComponentTests({
folder: 'quiz-element',
tag: 'quiz-element',
fixture: '<quiz-element question="Is this a test?" options="*Yes|No"></quiz-element>',
langs: ['en', 'de'],
strings: { en: 'CHECK', de: 'PRΓFEN' }, // asserted present in the built en/de bundles
shadowContains: 'CHECK', // optional: text expected in the rendered shadow
});
jsdom polyfills (matchMedia, IntersectionObserver, ResizeObserver, rAF, β¦) live in test/setup.js.
Development Workflow
-
Edit source files in
src/components/[component-name]/index.js- The single, language-agnostic web component. Reads every user-facing string from anI18Nobject and uses two build placeholders:{{COMPONENT_CSS}}(styles) and{{COMPONENT_STRINGS}}(the active language's strings).locales/en.json,locales/de.json, β¦ - UI strings per language (same keys in each).en.jsonis required (it backs the English fallback). Adding a language = drop one JSON file; no JavaScript is duplicated. A component with no user-facing text needs nolocales/.styles.css- Component styles (shared across languages; injected at{{COMPONENT_CSS}})
At the top of the component's IIFE, declare
const I18N = {{COMPONENT_STRINGS}};and reference strings asI18N.<key>/${I18N.<key>}. The packager emits one<folder>.<lang>.jsper locale file, inlining that language's JSON β no runtime i18n library, strings baked in per build.Legacy
index-<lang>.jsfull-duplicate files are still supported for incremental migration, butlocales/is preferred β a folder is treated as locale-based the momentlocales/exists. -
Build the distribution
npm run build -
Verify the output in
dist/: each component emits<folder>.js(+<folder>.<lang>.js),manifest.jsonmaps the tag + langs, andshared.jsholds the global helpers. All language variants of a component share one identical code body β only the inlined strings differ.
See CONTRIBUTING.md for detailed guidelines.
π Documentation
- Component Library - Component source code with README for each
- Example Demo - Comprehensive showcase of all components
- LiaScript Docs - LiaScript information
- Macros Guide - LiaScript macro system
- Contributing - How to contribute
π Adding New Components
- Create component folder in
src/components/my-component/ - Add
index.js(use the{{COMPONENT_CSS}}placeholder in the shadow root; read UI text fromI18N.<key>with aconst I18N = {{COMPONENT_STRINGS}};at the top of the IIFE),styles.css, alocales/en.json(+de.json, β¦) for any user-facing strings, andREADME.md - Add a co-located
index.test.jsβ onedefineComponentTests({...})call with a fixture that actually populates the shadow (see Testing above) - Build with
npm run build - Verify the generated
dist/components/my-component.js(+.de.js) and itsmanifest.jsonentry, and thatnpm testis green
See CONTRIBUTING.md for details.
π€ Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
π License
MIT License - feel free to use in your projects!
π Acknowledgments
Built for LiaScript - an open-source Markdown interpreter for creating interactive educational content.
Ready to build amazing interactive courses? Import the components and start creating! π
For questions or issues, please open an issue.
Dependencies
Development dependencies
| ID | Version |
|---|---|
| jest | ^29.7.0 |
| jest-environment-jsdom | ^29.7.0 |
| npm-run-all | ^4.1.5 |