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

@xenition/ui

v0.1.3

Published

Official UI kit for Xenition-generated apps — seed-token theme compiler with WCAG auto-contrast, Tailwind preset, themed React primitives (web), and React Native theme tokens.

Readme

@xenition/ui

Official UI kit for apps generated by the Xenition no-code builder. One npm package, subpath exports per concern: a seed-token theme compiler with WCAG-AA auto-contrast, a Tailwind preset bound to CSS variables, themed React primitives (web), a dependency-free motion layer, composed marketing sections, and a resolved token layer for React Native.

The reliability argument that moved backend logic into @xenition/sdk moves interface into this kit: the builder LLM wires tested components and writes a ~5-value theme seed — it does not hallucinate JSX or hand-pick colors.

Install

# Development builds
npm install "github:xenition/ui-kit#develop"

# Production builds
npm install "github:xenition/ui-kit"

npm publishing will follow in 1.0.0, alongside @xenition/sdk. react (>= 18) is a peer dependency.

Seed-token theming

An app's entire look is authored as a tiny theme.seed.json — the only theme input the LLM (or a settings form) ever writes:

{
  "primary": "#7C3AED",           // brand color
  "accent": "#F59E0B",            // optional; defaults to primary hue +40°
  "neutral": "warm",              // warm | cool | pure — gray ramp temperature
  "font": { "heading": "Inter", "body": "Inter" },
  "shape": "rounded",             // sharp | rounded | pill → radius scale
  "mode": "both"                  // light | dark | both
}

compileTheme(seed) is a pure, deterministic, unit-tested function that derives everything else:

  • 11-step color ramps (50–950) for primary, accent, and neutral.
  • Semantic slots per mode: surface, on-surface, primary, on-primary, accent, on-accent, muted, border, and fixed-hue success / warn / danger.
  • Auto-contrast: every on-X/X pair is adjusted in lightness until it passes WCAG 2.1 AA (≥ 4.5:1). The adjustment is guaranteed to terminate — a compiled theme can never ship an unreadable button.
  • Dark mode derived by ramp inversion (50 ↔ 950).
  • Radius scale from shape, plus spacing and typography scales.

Three outputs from one compiled theme:

| Output | Function | Consumer | | --- | --- | --- | | CSS custom properties (--xen-*) | toCssVars(theme) | web runtime (injected by the provider) | | Tailwind preset (var-bound) | toTailwindPreset(theme) | generated web app's Tailwind build | | Resolved token object | toNativeTokens(theme) | React Native StyleSheet |

Invalid seeds throw descriptive errors — a bad theme is rejected at compile time, never "best-effort applied".

Usage (web)

import { XenitionUIProvider, Button, Card, Input, Stack } from '@xenition/ui';
import seed from './theme.seed.json';

export function App() {
  return (
    <XenitionUIProvider theme={seed}>
      <Card>
        <Stack gap="md">
          <Input placeholder="Email" />
          <Button variant="primary" size="lg">Sign up</Button>
        </Stack>
      </Card>
    </XenitionUIProvider>
  );
}
// tailwind.config.js
const { compileTheme } = require('@xenition/ui/theme');
const { toTailwindPreset } = require('@xenition/ui/tailwind-preset');
const seed = require('./theme.seed.json');

module.exports = {
  presets: [toTailwindPreset(compileTheme(seed))],
  content: [
    './src/**/*.{ts,tsx}',
    './node_modules/@xenition/ui/dist/**/*.js', // kit classes must be purge-visible
  ],
};

Because the preset maps bg-primary, text-on-surface, radii, and spacing to var(--xen-*) references, swapping the injected variables restyles a built app live — "restyle by prompt" is a data change, not a rebuild.

Motion (@xenition/ui/motion)

Dependency-free scroll and pointer motion — CSS transitions + IntersectionObserver, no framer-motion. Every component is SSR-safe (window/observer access is guarded) and honors prefers-reduced-motion: reduced-motion users get the final state instantly, with no animation.

| Component | What it does | | --- | --- | | Reveal | scroll-triggered entrance (effect: fade-up | fade | slide-left | slide-right | zoom | blur-in; delay, duration, once, threshold) | | Stagger | cascades child Reveals with incremental delays (interval, delay) | | Parallax | subtle translateY on scroll (rAF + passive listener; speed clamped ±0.5) | | AnimatedCounter | counts up when scrolled into view (to, from, duration, format) | | Marquee | infinite horizontal loop (speed px/s, pauseOnHover; duplicate copy is aria-hidden) | | TiltCard | pointer-tracked 3D tilt (maxTilt, default 8°; off for touch + reduced motion) |

The usePrefersReducedMotion() and useInView() hooks are exported for custom motion built on the same rules.

Marketing sections (@xenition/ui/marketing)

Composed, slot-based sections for marketing-grade template sites. Styled only via --xen-* tokens and the var-bound Tailwind preset — no literal colors anywhere (unit-enforced) — so an entire template restyles from the theme seed alone, dark mode included.

| Component | What it does | | --- | --- | | AuroraBackground | animated layered gradient: blurred ramp-colored blobs (primary/accent 400–700) drifting on slow keyframes; variant: aurora | mesh | radial; optional grain (inline feTurbulence) and pattern: dots | grid | | GradientHero | full-bleed hero over the aurora; slots: eyebrow, title, subtitle, actions, media | | Navbar | sticky, backdrop-blur once scrolled, mobile disclosure menu; slots: logo, links (children), actions | | SectionHeading | eyebrow + title + lede, align left/center | | FeatureGrid / FeatureCard | responsive feature cards (icon slot, title, body, hover-lift) | | StatBar / Stat | row of AnimatedCounter stats with prefix/suffix + label | | Testimonials / Testimonial | quote cards, avatar-initials fallback, mode: grid | marquee | | PricingTable / PricingTier | tier cards, featured emphasis (token ring/scale + badge), checklists, action slot | | FAQ / FAQItem | accessible accordion (aria-expanded + labelled region, animated height) | | CTABanner | compact gradient band reusing the aurora machinery | | Footer / FooterColumn | multi-column link groups + bottom bar | | LogoCloud | dimmed logo slots that restore on hover | | ProductMock | configurable fake-product hero panel (variant: analytics | chat | commerce | calendar; KPI tiles, chart: bars | sparkline | rings | scene, live event feed, pulsing badge, 3D entrance tilt); CSS-only animation, deterministic, aria-hidden | | BentoGrid / BentoCard | asymmetric span-config feature grid (per-card span/rowSpan, icon tile, metric chip, micro-visual slot, token hover energy wash) | | ParticleField | ambient particles (mood: ember | snow | fireflies | sparks; density, seed); deterministic golden-ratio layout, static scatter under reduced motion; computeParticles() exported | | OrnamentRule | editorial divider — fading gradient rule with diamond | dot | line ornament, tone: accent | primary | border | | PriceList / PriceRow | dotted-leader price rows with ornamented group headings (menus, service lists, rate cards) | | GenerativeCover | deterministic SVG cover art from { seed, form: arc \| bands \| orbit \| grid \| wave \| stack, ink, paper } — two token color roles, seeded PRNG geometry, no stock imagery | | PointerHalo | optional custom-cursor affordance — accent halo trailing the pointer, tightens over links, swells with a label over [data-halo="grow"]; fine-pointer only, reduced-motion/touch → renders nothing | | EditorialGrid / EditorialItem | 12-column asymmetric overlap layout (span/start/offset per item, surface-backed caption slot, automatic z-order so overlaps slide under captions) | | SectionDivider | section separator (hairline | ornament | fade), optionally parallax-capable via parallax speed | | EntityCard | generic content/entity card that collapses the templates' bespoke PostCard / ServiceCard / SpeakerCard / ListingCard / ProgramCard — slots { title, eyebrow?, description?, meta?, media?: { imageUrl?, seed?, aspect? }, badge?, footer?, href? }; composes Card + media (<img> or a seeded GenerativeCover) + Eyebrow; one card expresses a blog post, a service, a speaker, a listing, or a program by props alone |

The display primitives that keep recurring across templates live in @xenition/ui/primitives (also re-exported from the root):

| Component | What it does | | --- | --- | | GradientText | ramp-driven clipped gradient text (ramp: primary | accent | primary-accent | accent-primary, angle) | | Eyebrow | tracked small-caps kicker label (tone, optional flanking rules, align) | | GlassPanel | color-mix translucent blurred surface over the surface/border tokens (intensity: soft | regular | strong) | | StatusDot | pulsing semantic status dot (tone: success | warn | danger | primary | accent; echo disabled under reduced motion; optional accessible label) | | Rating | ★ rating row (value, max=5, size, showValue, label) — filled accent glyphs up to the rounded value, muted after; announced as one role="img" | | StatusMessage | loading / empty / error feedback (state, optional message) — loading = a reduced-motion-safe CSS spinner + role="status", empty = a muted message, error = a danger-token message + role="alert"; pairs with @xenition/ui/data's useResource |

AuroraBackground is exported directly so templates can build custom striking sections from the same machinery.

Domain blocks — booking / media / commerce

Presentational components for the module-backed template families. Like the marketing sections they are token-only (no literal colors — unit-enforced, both modes verified) and motion/reduced-motion safe, but they carry no data layer: every component takes its data as props (the shapes below mirror the SDK module DTOs) and never fetches or imports an SDK. A template wires them to @xenition/ui/data + @xenition/sdk; the kit just renders.

Booking (@xenition/ui/booking)

Prop shapes mirror the booking module — a resource is { name, timezone, slotMinutes } and a slot is { startsAt, endsAt, spotsLeft } (instants are ISO-8601 strings).

| Component | What it does | | --- | --- | | BookingCalendar | month or week view highlighting days with availability (derived from slots, or a per-day availability summary, bucketed in timezone); ARIA grid with roving-tabindex cells and full keyboard nav (arrows/Home/End/PageUp-Down/Enter), availability shown as a dot and in the aria-label; selectedDate, onSelectDate | | SlotPicker | grid of bookable times for a day; slots, onPick(slot), selected, a formatTime override (default timezone-aware), remaining-spots hint, and disabled/Full when spotsLeft === 0 | | BookingSummary | read-only recap of the chosen resource + slot (date, time range, duration, timezone), optional action slot |

Media (@xenition/ui/media)

Prop shapes mirror the media module — an album { title } and items { url, kind, caption, alt, width, height }.

| Component | What it does | | --- | --- | | Gallery | responsive grid (+ masonry variant) of media items; columns, onOpen(index), loading="lazy" images, aspect-ratio boxes reserved from width/height | | Lightbox | fullscreen overlay viewer; items, index (null = closed), onClose/onPrev/onNext, loop; role="dialog" aria-modal, focus trap (enter on open, cycle on Tab, restore on close), keyboard (Esc/←/→), token-styled backdrop, opacity-only fade dropped under reduced motion | | MediaFigure | a single item with its <figcaption>, in a reserved aspect-ratio box |

Commerce (@xenition/ui/commerce)

Prop shapes mirror the catalog/cart/order module — Product { slug, title, imageUrl }, Variant { title, priceCents, currency, compareAtCents }, CartItem { title, variantTitle, quantity, unitPriceCents, imageUrl }. Money is always integer cents, formatted through the single exported formatMoney(cents, currency) home (overridable per component via a formatMoney prop).

| Component | What it does | | --- | --- | | formatMoney | the one cents → localized currency string util (1200"$12.00") | | PriceTag | formatted price with an optional struck-through compareAt | | ProductCard | media (image, or a seeded GenerativeCover fallback when no imageUrl), title, PriceTag, optional onAdd/href | | ProductGrid | responsive grid of ProductCards (columns) | | QuantityStepper | −/n/+ control with min/max clamping (boundary button self-disables), onChange | | CartLineItem | thumbnail, title + variant, QuantityStepper, line total (unit × qty), remove | | CartSummary | subtotal / shipping (Free at 0) / tax / discount / total rows (all cents), onCheckout | | OrderSummary / CheckoutSummary | read-only order recap — line items + totals + StatusBadge | | StatusBadge | order-status pill using contrast-checked X/on-X semantic pairs | | EmptyState | generic empty / no-results (empty cart, no matches) — icon slot, title, description, action |

Composition, not creation

The kit owns the design; apps only compose. Every "bespoke" visual trick the flagship templates shipped — the fake dashboard product shot, the bento grid's hover wash, the ember sky, brass rules and dotted price leaders, the generative cover plates, the studio cursor, the overlapping editorial grid — now lives here as a configurable, token-pure, reduced-motion-safe component. The same rule extends to the domain blocks: a booking flow, a photo gallery + lightbox, a storefront grid, a cart drawer, or an order recap is composed from @xenition/ui/booking · /media · /commerce, never hand-written per template. It also extends to the per-template card zoo: the bespoke PostCard / ServiceCard / SpeakerCard / ListingCard / ProgramCard each template used to hand-build now collapse into a single token-only EntityCard (marketing, web + native), the Stars widget into Rating, and hand-rolled loading/empty/error blocks into StatusMessage — one contract, restyled by seed, contrast-checked, reduced-motion-safe. Those components take data as props (no fetching, no SDK import) and are styled by tokens alone, so the same booking calendar or product grid restyles — light and dark — from the theme seed. Templates and the no-code builder must compose these components (and the /motion layer) rather than writing their own motion or color CSS. Bespoke visual code in a generated app is an anti-pattern: it can't be restyled by seed, isn't contrast-checked, and won't respect reduced motion. If a design needs something the kit can't express, the fix is a new prop or component in the kit — never a one-off in the app.

Building a beautiful template

The showpiece pattern — an aurora hero, staggered reveals, and a counting stat bar — is pure composition; not a single color is written:

import { XenitionUIProvider, Button } from '@xenition/ui';
import { Reveal, Stagger } from '@xenition/ui/motion';
import {
  GradientHero,
  SectionHeading,
  FeatureGrid,
  FeatureCard,
  StatBar,
  Stat,
  CTABanner,
} from '@xenition/ui/marketing';
import seed from './theme.seed.json';

export function LandingPage() {
  return (
    <XenitionUIProvider theme={seed}>
      <GradientHero
        variant="aurora"
        grain
        pattern="dots"
        eyebrow="Now in beta"
        title="Launch a themed site in minutes"
        subtitle="Every color on this page comes from a 5-value theme seed."
        actions={
          <>
            <Button size="lg">Get started</Button>
            <Button size="lg" variant="secondary">Live demo</Button>
          </>
        }
      />

      <SectionHeading align="center" eyebrow="Features" title="Why it works" />
      <Stagger interval={120}>
        <Reveal effect="fade-up"><FeatureCard title="Token-driven">Restyle by seed.</FeatureCard></Reveal>
        <Reveal effect="fade-up"><FeatureCard title="Accessible">WCAG-AA by construction.</FeatureCard></Reveal>
        <Reveal effect="fade-up"><FeatureCard title="Fast">No animation library.</FeatureCard></Reveal>
      </Stagger>

      <Reveal effect="zoom">
        <StatBar>
          <Stat to={12000} suffix="+" label="Sites generated" />
          <Stat to={99} suffix="%" label="Lighthouse a11y" />
        </StatBar>
      </Reveal>

      <CTABanner title="Ready?" action={<Button size="lg">Start free</Button>} />
    </XenitionUIProvider>
  );
}

Swap the seed, and the aurora, buttons, rings, and patterns all follow — "restyle by prompt" now covers the marketing site, not just the app shell.

Usage (React Native)

The token layer alone is still available for bespoke styling — useXenitionTheme() returns resolved hex/px values (RN cannot read CSS variables):

import {
  XenitionNativeThemeProvider,
  useXenitionTheme,
} from '@xenition/ui/native/theme';

function BuyButton() {
  const { colors, tokens } = useXenitionTheme();
  return (
    <Pressable
      style={{
        backgroundColor: colors.primary,
        borderRadius: tokens.radius.md,
        padding: tokens.spacing.md,
      }}
    >
      <Text style={{ color: colors.onPrimary }}>Buy</Text>
    </Pressable>
  );
}

But the kit now ships genuine React Native components under @xenition/ui/native/* that mirror the web prop contracts exactly — a template's mobile screen composes them 1:1 like the web page, swapping web→native by import path only (onClickonPress is the one idiomatic change). They are real RN components (View / Text / Pressable / TextInput / Image / FlatList / Animated — no DOM), styled only from the compiled theme tokens (light + dark, restyle-by-seed), and reduced-motion-safe via AccessibilityInfo.

import { XenitionUIProvider, Button, Card, Stack } from '@xenition/ui/native/primitives';
import { ProductGrid, ProductCard, CartSummary } from '@xenition/ui/native/commerce';
import seed from './theme.seed.json';

export function Storefront() {
  return (
    <XenitionUIProvider theme={seed}>
      <ProductGrid columns={2}>
        <ProductCard title="Ceramic Mug" priceCents={2400} compareAtCents={3200} onAdd={add} />
        <ProductCard title="Linen Napkin" priceCents={1800} imageUrl={url} />
      </ProductGrid>
      <CartSummary subtotalCents={4200} shippingCents={0} taxCents={336} totalCents={4536} onCheckout={checkout} />
    </XenitionUIProvider>
  );
}

@xenition/ui/native/primitives

XenitionUIProvider (native root), Button (variant primary/secondary/ghost, size sm/md/lg, onPress, disabled, loading), Card, Stack (direction/gap/align, plus an additive justify), Input (invalid + optional label), Eyebrow, StatusDot (Animated pulse, reduced-motion-safe), Rating (★ row — same value/max/size/showValue/ label contract as web), StatusMessage (loading ActivityIndicator / empty muted / error danger feedback — same state/message contract as web), GlassPanel (translucent rgba derived from the surface token), GradientText, EmptyState, PriceTag, and formatMoney (re-exported from the single commerce home).

Gradients on native. RN has no background-clip: text, so GradientText uses a tasteful solid-token fallback (the ramp's mid step) rather than pulling in a masked-view dependency; the angle prop is accepted for parity but inert. Real gradient surfaces (the commerce cover placeholder) use expo-linear-gradient — an optional peer that every Expo consumer already has; absent it, those surfaces degrade to a solid token fill.

@xenition/ui/native/commerce

formatMoney, PriceTag, ProductCard, ProductGrid (FlatList-backed), QuantityStepper, CartLineItem, CartSummary, OrderSummary / CheckoutSummary, StatusBadge, EmptyState, and a native GenerativeCover image placeholder — all matching the web @xenition/ui/commerce prop APIs. Money is integer cents throughout.

react-native is a peer dependency; expo-linear-gradient is an optional peer (used for gradient cover placeholders).

@xenition/ui/native/marketing

EntityCard — the native mirror of the web marketing EntityCard, with the same slot contract (hrefonPress is the idiomatic swap). Composes the native Card + media (Image, or a seeded GenerativeCover) + Eyebrow, so one card expresses a blog post, a service, a speaker, a listing, or a program by props alone — mobile screens compose it 1:1 with the web page.

@xenition/ui/native/booking

BookingCalendar (View/Pressable month/week grid — availability dots, selected/disabled cells, accessibilityState; header chevrons change month), SlotPicker (FlatList of time chips — full slots disabled with a Full label, low-stock "{n} left" hint, onPick), and BookingSummary (resource + slot recap card) — all matching the web @xenition/ui/booking prop APIs (onSelectDate/onPick are the native event idioms). The pure date helpers (toDayKey/dayKeyInTz/monthMatrix/weekRow/…) are re-exported from the single web home, never duplicated.

@xenition/ui/native/media

Gallery (FlatList grid — numColumns, grid/masonry from width/height via the RN aspectRatio style, windowing gives the web's lazy loading; onOpen(index)), Lightbox (a reduced-motion-safe transparent RN Modal — token-styled backdrop, prev/next Pressable controls, and horizontal swipe via PanResponder from RN core with no extra gesture dependency; the Android back button routes through onRequestCloseonClose; renders nothing for a null/out-of-range index), and MediaFigure (single image + caption) — all matching the web @xenition/ui/media prop APIs (onOpen/onActivate/ onClose/onPrev/onNext are the native event idioms).

@xenition/ui/native/motion

Reveal ({children, effect: 'fade' | 'fade-up' | 'zoom', delay?, duration?}) and Stagger (sequences child Reveal delays), built on the RN Animated API only (no animation library). On mobile the norm is a mount entrance, so Reveal animates in on mount rather than on scroll; under the OS "Reduce Motion" setting content renders immediately with animations off. The scroll/pointer-driven web pieces — Parallax, Marquee, TiltCard, AnimatedCounter — are web-only (they depend on scroll position / pointer events / IntersectionObserver with no React Native analogue); use them from @xenition/ui/motion in web templates.

Subpath layout

| Subpath | Contents | | --- | --- | | @xenition/ui | everything web: theme + primitives + XenitionUIProvider | | @xenition/ui/theme | compileTheme, color/WCAG utilities, output functions | | @xenition/ui/tailwind-preset | toTailwindPreset (also the default export) | | @xenition/ui/primitives | Button, Card, Input, Stack, GradientText, Eyebrow, GlassPanel, StatusDot, Rating, StatusMessage | | @xenition/ui/motion | Reveal, Stagger, Parallax, AnimatedCounter, Marquee, TiltCard | | @xenition/ui/data | useResource hook + headless Resource (loading/error/empty branching) — pairs with @xenition/sdk/client | | @xenition/ui/marketing | GradientHero, AuroraBackground, Navbar, FeatureGrid, PricingTable, FAQ, ProductMock, BentoGrid, ParticleField, GenerativeCover, EditorialGrid, PointerHalo, EntityCard, … | | @xenition/ui/booking | BookingCalendar, SlotPicker, BookingSummary (+ toDayKey / dayKeyInTz / formatTimeInTz date helpers) | | @xenition/ui/media | Gallery, Lightbox, MediaFigure | | @xenition/ui/commerce | formatMoney, PriceTag, ProductCard, ProductGrid, QuantityStepper, CartLineItem, CartSummary, OrderSummary / CheckoutSummary, StatusBadge, EmptyState | | @xenition/ui/native/theme | XenitionNativeThemeProvider, useXenitionTheme | | @xenition/ui/native/primitives | XenitionUIProvider, Button, Card, Stack, Input, Eyebrow, StatusDot, Rating, StatusMessage, GlassPanel, GradientText, EmptyState, PriceTag, formatMoney (React Native) | | @xenition/ui/native/commerce | formatMoney, PriceTag, ProductCard, ProductGrid, QuantityStepper, CartLineItem, CartSummary, OrderSummary / CheckoutSummary, StatusBadge, EmptyState, GenerativeCover (React Native) | | @xenition/ui/native/marketing | EntityCard (React Native; mirrors the web marketing EntityCard, hrefonPress) | | @xenition/ui/native/booking | BookingCalendar, SlotPicker, BookingSummary (React Native; shares the web date helpers) | | @xenition/ui/native/media | Gallery (FlatList), Lightbox (RN Modal + PanResponder swipe), MediaFigure (React Native) | | @xenition/ui/native/motion | Reveal (mount entrance via Animated, reduced-motion-safe), Stagger (React Native) |

The booking / media / commerce families ship these as presentational components (data-as-props, no fetching); the SDK-backed headless hooks that feed them — wired through one root provider, à la @xenition/ui/data — land alongside their SDK modules. Further families (@xenition/ui/catalog, …) follow the same pattern as their modules land.

Relation to @xenition/sdk

@xenition/ui is the interface half of the same moat: components are SDK-backed and will accept the app's XenitionClient through the root provider, so LLM wiring stays "provider once + drop components". The two packages version together and are injected into generated apps the same way.

Repository convention (private → public mirror)

This repo (xenition/ui-kit-private) is the source of truth where all work happens; CI mirrors it to the public xenition/ui-kit on push — the same convention as node-sdk-privatenode-sdk. Unlike the SDK there is no URL patching in the mirror step: the kit embeds no backend URLs (it receives the client), so the split is purely source-visibility policy.

Development

npm install     # also builds (prepare)
npm test        # jest (ts-jest)
npm run build   # tsc → dist/

Hard rule (enforced by lint in CI): kit components consume tokens only — no literal colors.

License

MIT