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

@aquera/nile-ai-elements

v0.0.5

Published

AI webcomponents for nile following open-wc recommendations

Readme

<nile-ai-elements>

AI-focused web components for Nile, following the open-wc recommendation. Built with Lit and styled with the Nile / NxtGen (--ng-*) design tokens.

Components

| Tag | Description | | --- | --- | | <nile-ai-chat-bubble> | A chat bubble for an AI conversation (user / ai roles, agent header, reasoning pill, loader). Driven by a single data object. | | <nile-ai-token-stream> | Reveals text token-by-token (typewriter style) with jitter, looping, a caret, and live API streaming. | | <nile-wibbling-spinner> | A whimsical text spinner: a rotating glyph + a (re-rolling) verb + optional info. | | <nile-ai-chat> | A scrollable conversation thread — lays out bubbles, autoscrolls to the latest, with header / footer / empty slots. Emits nile-scroll-state. | | <nile-ai-prompt-input> | A chat composer: auto-growing textarea + send / stop button, Enter-to-send. Emits nile-submit, nile-input, nile-stop. | | <nile-ai-prompt> | A rich composer: auto-growing textarea + toolbar (add-context, model picker, mic, send). The + button can open a customizable attachment menu (default "Add photos or files") via attach-menu / attachItems. Speech-to-text dictation via the Web Speech API with a live mic waveform. Emits nile-submit, nile-change, nile-model-change, nile-add-context, nile-attach, nile-voice*, nile-stop. | | <nile-ai-prompts> | A predefined set of clickable prompt suggestions (icon / label / description), with nesting, a title, vertical / wrap layouts and fade-in. Emits nile-item-click. | | <nile-ai-message-actions> | A per-message toolbar (copy / regenerate / like / dislike). Emits nile-action. | | <nile-ai-suggestion> | A horizontal row of clickable suggestion pills — predefined prompts a user can tap to send to an LLM. Scrolls when it overflows, or wraps with wrap; supports plain strings or { label, value, icon, disabled } items. Emits nile-suggestion-click. | | <nile-ai-attachments> | Displays file attachments and source documents with grid / inline / list layouts, automatic media-type detection, previews, and an optional remove affordance. Emits nile-remove, nile-item-click. | | <nile-ai-image> | Renders an AI-generated image from the AI SDK — accepts an Experimental_GeneratedImage (base64 / uint8Array + mediaType) or a plain src, assembles the data: URL, and shows a loading shimmer then an error fallback. Emits nile-load, nile-error. | | <nile-ai-citation> | An inline citation pill that reveals source details on hover / click; multiple sources become a carousel. Emits nile-toggle, nile-navigate, nile-source-click. | | <nile-ai-checkpoint> | A marker between messages that lets the user restore the chat back to that point (bookmark icon + restore trigger + separator). Emits nile-restore. | | <nile-ai-context> | Visualizes an LLM context-window's usage — a circular percentage ring that reveals a token / cost breakdown (input / output / reasoning / cache) on hover or click. Emits nile-toggle. | | <nile-ai-temperature> | A reasoning-effort slider modeled on a coding agent's /effort menu — hover to preview a tier, click to commit. Emits nile-change. | | <nile-ai-status> | A compact status pill (pending / active / running / done / error). | | <nile-ai-reasoning> | A collapsible chain-of-thought panel; streaming-aware. Emits nile-toggle. | | <nile-ai-tool-call> | A card for an agent tool / function invocation (name, status, args, collapsible result). Emits nile-toggle. | | <nile-ai-confirmation> | A tool-approval card: shows an approval prompt with Approve / Reject actions while pending, then an accepted or rejected confirmation once resolved (driven by state + approved). Emits nile-respond, nile-approve, nile-reject. | | <nile-ai-steps> | A vertical timeline of agent steps with per-step status markers. When more steps are appended than maxVisible (default 3), older steps slide out the top while new ones slide in, keeping only the trailing window on screen. | | <nile-ai-plan> | A collapsible card showing an AI-generated execution plan — titled/described content sections (headings, prose, bullet lists) with a footer call-to-action; streaming-aware. Emits nile-toggle, nile-action. | | <nile-ai-queue> | A queue of messages / todos in collapsible sections — per-item status indicator, content/description, image & file attachments, and hover-revealed actions. Emits nile-toggle, nile-action, nile-item-click. | | <nile-ai-sources> | A collapsible disclosure listing the grounding sources a model used ("Used N sources") — each a link with a leading icon, title (falling back to the hostname) and optional description, opening in a new tab. Emits nile-toggle, nile-source-click. | | <nile-ai-schema-display> | Visualizes a REST API endpoint — a color-coded HTTP method, the path (with highlighted {path} params), an optional description, and collapsible sections for parameters and request / response body schemas. Types and required render as badges; nested object / array properties expand and collapse in place. Emits nile-toggle. | | <nile-ai-test-results> | A test-suite run report — pass/fail/skip counts with a proportional progress bar, plus collapsible suites whose failed tests reveal an expandable error message and stack trace. Summary counts are computed from the suites when omitted. Emits nile-toggle, nile-error-toggle. |

Installation

npm i @aquera/nile-ai-elements

Usage

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-chat-bubble';
  import '@aquera/nile-ai-elements/nile-ai-token-stream';
  import '@aquera/nile-ai-elements/nile-wibbling-spinner';
</script>
// Chat bubble — configured via a single data object
const bubble = document.createElement('nile-ai-chat-bubble');
bubble.data = {
  role: 'ai',
  agent: 'Synthetica',
  thinking: 'reasoning',
  loading: true,
  message: 'Q3 churn is bleeding from your SMB cohort.',
};

// Token stream — typewriter reveal, also drivable from a backend stream
const stream = document.createElement('nile-ai-token-stream');
stream.text = 'Q3 churn is bleeding from your SMB cohort…';
stream.loop = true;
// stream.streamFrom((await fetch('/api/chat')).body); // live API streaming

// Wibbling spinner — rotating glyph + re-rolling verb + live info
const spinner = document.createElement('nile-wibbling-spinner');
spinner.verbInterval = 1500;

Wiring up a chat

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-chat';
  import '@aquera/nile-ai-elements/nile-ai-prompt-input';
</script>

<nile-ai-chat id="chat" style="height: 480px;">
  <nile-ai-prompt-input slot="footer" placeholder="Ask anything…"></nile-ai-prompt-input>
  <div slot="empty">Start the conversation 👋</div>
</nile-ai-chat>
const chat = document.getElementById('chat');
const composer = chat.querySelector('nile-ai-prompt-input');

composer.addEventListener('nile-submit', e => {
  // append the user's message
  const userBubble = document.createElement('nile-ai-chat-bubble');
  userBubble.data = { role: 'user', message: e.detail.value };
  chat.insertBefore(userBubble, null);
  // …then stream the AI reply into a nile-ai-chat-bubble / nile-ai-token-stream
});

Rich composer (<nile-ai-prompt>)

A fuller composer with a toolbar: an "add context" button, a model dropdown, a mic, and a send button. The mic uses the browser's Web Speech API to dictate straight into the field, showing a live mic waveform while it listens.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-prompt';
</script>

<nile-ai-prompt
  id="composer"
  placeholder="Paste a tweet, get a landing page…"
  default-model="Claude Sonnet 4.6"
></nile-ai-prompt>
const composer = document.getElementById('composer');
composer.models = ['Claude Sonnet 4.6', 'Claude Opus 4.8', 'Claude Haiku 4.5'];

composer.addEventListener('nile-submit', e => {
  console.log('send', e.detail.value, 'with model', e.detail.model);
});
composer.addEventListener('nile-model-change', e => console.log('model →', e.detail.model));

// Attachment menu: set `attach-menu` so the + opens a menu instead of emitting
// `nile-add-context`. Defaults to a single "Add photos or files" option.
composer.attachMenu = true;
// Pass your own items to customize the menu (id is reported as `source`;
// `picksFiles` opens the native file picker):
composer.attachItems = [
  { id: 'files', label: 'Add photos or files', icon: 'ng-image', picksFiles: true },
  { id: 'screenshot', label: 'Take screenshot', icon: 'ng-monitor' },
];
composer.addEventListener('nile-attach', e => {
  if (e.detail.source === 'files') console.log('files:', e.detail.files);
  else console.log('custom action:', e.detail.source);
});

// Speech-to-text: spoken words are appended to the field as you talk.
composer.addEventListener('nile-voice-result', e => console.log(e.detail.transcript, e.detail.isFinal));
composer.addEventListener('nile-voice-end', e => console.log('dictation done:', e.detail.value));

// Optional toolbar extra (e.g. a keyboard hint), rendered before the mic + send:
// <span slot="toolbar-extras">⌘↵ to send</span>

Key options: value / defaultValue, placeholder, rows, models / model / defaultModel, submitOnCmdEnter (default true), speechLang, attach-menu / attachItems / accept, and hide-add-context / hide-model / hide-voice / hide-send. Everything is also settable at once via the data object.

Prompt suggestions (<nile-ai-prompts>)

A predefined list of clickable starter prompts — handy for an empty chat state.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-prompts';
</script>

<nile-ai-prompts id="suggestions" wrap fade-in></nile-ai-prompts>
const suggestions = document.getElementById('suggestions');
suggestions.title = '✨ How can I help you today?';
suggestions.items = [
  { key: 'ignite', icon: 'ng-sparkles', label: 'Ignite an idea', description: 'Brainstorm names and angles' },
  { key: 'write', icon: 'ng-pen-line', label: 'Draft copy', description: 'Turn a tweet into a landing page' },
  // nested children render indented beneath their parent
  { key: 'analytics', icon: 'ng-rocket', label: 'Analytics', children: [
    { key: 'churn', label: 'Summarize Q3 churn by cohort' },
  ] },
];

suggestions.addEventListener('nile-item-click', e => {
  // seed the composer with the chosen prompt
  composer.value = e.detail.data.label;
  composer.focus();
});

icon accepts a nile-glyph name (e.g. ng-sparkles) or any other string (e.g. an emoji). Layout is controlled with vertical and wrap; fade-in / fade-in-left add a staggered entrance.

Suggestion pills (<nile-ai-suggestion>)

A horizontal row of tappable suggestions — the follow-up chips that sit under a chat answer. The row scrolls when it overflows; add wrap to flow onto multiple lines instead.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-suggestion';
</script>

<nile-ai-suggestion id="followups"></nile-ai-suggestion>
const followups = document.getElementById('followups');

// Plain strings — the simplest form.
followups.suggestions = [
  'Summarize Q3 churn by cohort',
  'Which segment is bleeding the most?',
  'Draft a recovery plan',
];

// …or richer items with an icon, a distinct emitted value, or a disabled state.
followups.suggestions = [
  { label: 'Ignite an idea', icon: 'ng-sparkles' },
  { label: 'Explain code', icon: 'ng-code', value: 'explain:code' },
  { label: 'Generate an image', icon: 'ng-image', disabled: true },
];

followups.addEventListener('nile-suggestion-click', e => {
  // e.detail.suggestion is the item's `value` (or its label), e.detail.item the full item
  sendMessage({ text: e.detail.suggestion });
});

Agent transparency

// Tool call — name, status, args + (collapsible) result
const tool = document.createElement('nile-ai-tool-call');
tool.data = { name: 'search_web', status: 'running', args: { query: 'Q3 churn' } };

// Reasoning — collapsible chain-of-thought, streaming-aware
const reasoning = document.createElement('nile-ai-reasoning');
reasoning.data = { loading: true, open: true };

// Steps — a vertical agent timeline
const steps = document.createElement('nile-ai-steps');
steps.data = {
  steps: [{ label: 'Plan' }, { label: 'Search the web' }, { label: 'Synthesize answer' }],
  activeIndex: 1,
  // Only the trailing 3 steps stay mounted; older ones slide out as new
  // ones are appended (set 0 to disable windowing and show every step).
  maxVisible: 3,
};

Queue (<nile-ai-queue>)

A queue of messages / todos grouped into collapsible sections. Each item shows a status indicator, content + optional description, image / file attachments, and action buttons revealed on hover.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-queue';
</script>

<nile-ai-queue id="queue"></nile-ai-queue>
const queue = document.getElementById('queue');
queue.data = {
  sections: [
    {
      id: 'queued',
      label: 'Queued',
      icon: 'ng-list',
      // count defaults to items.length; defaultOpen defaults to true
      items: [
        {
          id: 'q1',
          content: 'Summarize Q3 churn by cohort',
          description: 'Waiting to run',
          attachments: [
            { type: 'image', url: '/cohort.png', filename: 'cohort.png' },
            { filename: 'report.pdf', mediaType: 'application/pdf' },
          ],
          actions: [
            { id: 'run', icon: 'ng-play', label: 'Run now' },
            { id: 'remove', icon: 'ng-x', label: 'Remove' },
          ],
        },
      ],
    },
    {
      id: 'completed',
      label: 'Completed',
      icon: 'ng-circle-check',
      defaultOpen: false,
      items: [{ id: 'c1', content: 'Pull subscription events', completed: true }],
    },
  ],
};

queue.addEventListener('nile-toggle', e => console.log(e.detail.id, e.detail.open));
queue.addEventListener('nile-action', e =>
  console.log('action', e.detail.actionId, 'on', e.detail.itemId)
);
queue.addEventListener('nile-item-click', e => console.log('item', e.detail.itemId));

Sources (<nile-ai-sources>)

A collapsible disclosure listing the grounding sources a model used. The trigger reads "Used N sources"; each source is a link (title falling back to the hostname) that opens in a new tab.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-sources';
</script>

<nile-ai-sources id="sources"></nile-ai-sources>
const sources = document.getElementById('sources');
sources.data = {
  open: false, // collapsed by default; omit `label` for the "Used N sources" default
  sources: [
    {
      href: 'https://en.wikipedia.org/wiki/Revenue_retention',
      title: 'Net revenue retention — Wikipedia',
      description: 'Definition and benchmarks',
    },
    // title falls back to the hostname when omitted
    { href: 'https://stripe.com/docs/billing' },
  ],
};

sources.addEventListener('nile-toggle', e => console.log('open →', e.detail.open));
sources.addEventListener('nile-source-click', e =>
  // e.detail: { index, source, url }
  console.log('opened source', e.detail.index, e.detail.url)
);

Schema display (<nile-ai-schema-display>)

Documents a single REST API endpoint: a color-coded method badge (GET / POST / PUT / PATCH / DELETE), the path with highlighted {path} parameters, an optional description, and collapsible Parameters, Request Body and Response Body sections. Body properties nest recursively — object types expand their properties, array types descend into their items.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-schema-display';
</script>

<nile-ai-schema-display id="schema"></nile-ai-schema-display>
const schema = document.getElementById('schema');
schema.data = {
  method: 'GET',
  path: '/v1/users/{id}/orders',
  description: 'List the orders belonging to a single user.',
  parameters: [
    { name: 'id', type: 'string', in: 'path', required: true },
    { name: 'limit', type: 'integer', in: 'query' },
  ],
  responseBody: [
    {
      name: 'orders',
      type: 'array',
      required: true,
      // arrays descend into `items`; objects expand `properties`
      items: {
        name: 'order',
        type: 'object',
        properties: [
          { name: 'id', type: 'string', required: true },
          { name: 'total', type: 'number', required: true },
        ],
      },
    },
    { name: 'nextCursor', type: 'string' },
  ],
};

schema.addEventListener('nile-toggle', e =>
  // e.detail: { section: 'parameters' | 'request' | 'response', open }
  console.log(e.detail.section, '→', e.detail.open)
);

Test results (<nile-ai-test-results>)

Reports a test-suite run: a header with passed / failed / skipped counts, a total and an optional duration, a proportional progress bar, and collapsible suites. Each test row shows its status icon, name and duration; a failed test with an error reveals an expandable message and stack trace. The summary is computed from the suites when not supplied, and a suite's status is derived from its tests.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-test-results';
</script>

<nile-ai-test-results id="results"></nile-ai-test-results>
const results = document.getElementById('results');
results.data = {
  // summary is optional — omit it and the counts are computed from `suites`
  summary: { passed: 5, failed: 1, skipped: 1, total: 7, duration: 1840 },
  suites: [
    {
      id: 'billing',
      name: 'billing.spec.ts',
      defaultOpen: true,
      tests: [
        { name: 'charges the card on renewal', status: 'passed', duration: 120 },
        {
          name: 'prorates a mid-cycle upgrade',
          status: 'failed',
          duration: 88,
          error: {
            message: 'Expected 41.50 but received 40.00',
            stack: 'AssertionError: ...\n    at proratePlan (billing.ts:212:14)',
          },
        },
      ],
    },
  ],
};

results.addEventListener('nile-toggle', e =>
  // e.detail: { id, open }
  console.log('suite', e.detail.id, '→', e.detail.open)
);
results.addEventListener('nile-error-toggle', e =>
  // e.detail: { suiteId, testIndex, open }
  console.log('error', e.detail.suiteId, '→', e.detail.open)
);

Confirmation (<nile-ai-confirmation>)

Gates a tool / function call behind user approval. While the request is pending (state: 'approval-requested') it shows the prompt with Approve / Reject buttons; once the response resolves (approval-responded, output-denied or output-available) it renders an accepted or rejected confirmation based on approved. Use the title / default / accepted / rejected / actions slots to override any part.

<script type="module">
  import '@aquera/nile-ai-elements/nile-ai-confirmation';
</script>

<nile-ai-confirmation id="confirm"></nile-ai-confirmation>
const confirm = document.getElementById('confirm');
confirm.data = {
  approvalId: 'call_123',
  state: 'approval-requested',
  heading: 'Delete file?',
  request: 'This tool wants to delete /tmp/example.txt. Do you approve?',
  acceptedText: 'You approved this tool execution',
  rejectedText: 'You rejected this tool execution',
};

confirm.addEventListener('nile-respond', e => {
  // e.detail: { id, approved }
  console.log(e.detail.id, '→', e.detail.approved);
  // reflect the decision back into the card
  confirm.data = { ...confirm.data, state: 'output-available', approved: e.detail.approved };
});

The components consume the Nile / NxtGen design tokens (--ng-*). Make sure the NxtGen stylesheet from @aquera/nile is loaded on the page so colors, spacing and typography resolve correctly. <nile-ai-chat-bubble> also depends on @aquera/nile-glyph for its icons.

Linting and formatting

To scan the project for linting and formatting errors, run

npm run lint

To automatically fix linting and formatting errors, run

npm run format

Testing with Web Test Runner

To execute a single test run:

npm run test

To run the tests in watch mode, run

npm run test:watch

Tooling configs

For most of the tools, the configuration is in the package.json to reduce the amount of files in your project.

If you customize the configuration a lot, you can consider moving them to individual files.

Local Demo with web-dev-server

npm start

To run a local development server that serves the basic demo located in demo/index.html.

Release Notes

In this section, you can find the updates for each release of nile-ai-elements. It's a good practice to maintain detailed release notes to help users and developers understand what changes have been made from one version to another and how these changes might affect their projects.

Version 0.0.5 (July 06, 2026)

  • Nile AI Steps: Added a maxVisible property (UIF-1290)

Version 0.0.4 (July 01, 2026)

  • Nile AI Confirmation: Added new component — a tool-approval card that shows an Approve / Reject prompt while pending and an accepted / rejected confirmation once resolved, driven by state + approved. Slots for title / request / accepted / rejected / actions. Emits nile-respond ({ id, approved }), plus nile-approve / nile-reject. (UIF-1284)
  • Nile AI Schema Display: Added new component — visualizes a REST API endpoint with a color-coded method badge, highlighted {path} params, and collapsible Parameters / Request Body / Response Body sections. Types and required render as badges, and nested object / array properties expand and collapse in place. Emits nile-toggle.
  • Nile AI Test Results: Added new component — a test-suite run report with passed / failed / skipped counts, a proportional progress bar, and collapsible suites whose failed tests reveal an expandable message and stack trace. Emits nile-toggle, nile-error-toggle.

Version 0.0.3 (June 30, 2026)

  • Nile AI Queue: Added new component — a queue of messages / todos grouped into collapsible sections (Queued / Completed etc.), each item with a status indicator, content + description, image / file attachments, and hover-revealed action buttons. Data-driven via sections. Emits nile-toggle, nile-action, nile-item-click. (UIF-1282)
  • Nile AI Sources: Added new component — a collapsible "Used N sources" disclosure listing the grounding sources a model used; each is a link with a leading icon, a title (falling back to the hostname) and an optional description, opening in a new tab. Emits nile-toggle, nile-source-click.
  • Nile AI Suggestion: Added new component — a horizontal row of clickable suggestion pills (the follow-up chips under an answer); scrolls on overflow or wraps with wrap; accepts plain strings or { label, value, icon, disabled } items. Emits nile-suggestion-click with { suggestion, item }.
  • Nile AI Prompt: The + button can now open a customizable attachment menu instead of emitting nile-add-context. Set attach-menu for the default "Add photos or files" option, or pass attachItems ({ id, label, icon?, picksFiles? }) to define your own; accept filters the file picker. Emits nile-attach with { source, files? }.

Version 0.0.2 (June 19, 2026)

  • Nile AI Chat: Added new component — scrollable conversation thread with autoscroll, "scroll to latest", and header / footer / empty slots; optional data.messages rendering. Emits nile-scroll-state. (UIF-1279)
  • Nile AI Prompt Input: Added new composer component — auto-growing textarea, send / stop button, Enter-to-send (Shift+Enter newline), prefix / suffix / footer slots. Emits nile-submit, nile-input, nile-stop.
  • Nile AI Prompt: Added new rich composer — auto-growing textarea with a toolbar (add-context, model dropdown, mic, send), data-object config, controlled/uncontrolled value & model, and a toolbar-extras slot. Speech-to-text dictation via the Web Speech API with a live mic waveform; submit on Cmd/Ctrl+Enter. Emits nile-submit, nile-change, nile-model-change, nile-add-context, nile-voice / nile-voice-start / nile-voice-result / nile-voice-end / nile-voice-error, and nile-stop.
  • Nile AI Prompts: Added new component — a predefined set of clickable prompt suggestions (icon / label / description) with nested children, a title, vertical / wrap layouts and fade-in / fade-in-left entrances. Modeled on Ant Design X's Prompts. Emits nile-item-click.
  • Nile AI Message Actions: Added new component — per-message toolbar (copy / regenerate / like / dislike) with clipboard copy. Emits nile-action.
  • Nile AI Status: Added new component — compact status pill (pending / active / running / done / error).
  • Nile AI Reasoning: Added new component — collapsible, streaming-aware chain-of-thought panel. Emits nile-toggle.
  • Nile AI Tool Call: Added new component — agent tool / function invocation card (name, status, args, collapsible result). Emits nile-toggle.
  • Nile AI Steps: Added new component — vertical agent timeline with per-step status markers.

Version 0.0.1 (June 17, 2026)

  • Nile AI Chat Bubble: Added new component — user/ai roles, agent header, reasoning pill with loader, and a single data-object API. (UIF-1269)
  • Nile AI Token Stream: Added new component — token-by-token text reveal with jitter, looping, blinking caret, and live API streaming (append, finish, streamFrom).(UIF-1269)
  • Nile Wibbling Spinner: Added new component — rotating glyph, re-rolling verb pool, and stateful parenthetical info.(UIF-1269)
  • Initial release of the @aquera/nile-ai-elements package (build tooling, dev server, and tests mirroring @aquera/nile-elements).(UIF-1269)