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

@servicetitan/carto-react-kit

v0.4.0

Published

Carto React component kit

Readme

@servicetitan/carto-react-kit

Carto React component kit. Ships as ESM with type declarations.

Install

pnpm add @servicetitan/carto-react-kit

Peer requirements: react@>=18 <20, react-dom@>=18 <20.

Usage

import { Button, CartoTheme } from "@servicetitan/carto-react-kit";
import { IconPencil } from "@servicetitan/carto-react-kit/icons";
import "@servicetitan/carto-react-kit/styles.css";

<CartoTheme>
  <Button label="Save" onPress={handleSave} />
  <Button label="Edit" icon={<IconPencil />} onPress={handleEdit} />
</CartoTheme>

Always import the CSS bundle once at your app's entry point so vanilla-extract styles are loaded.

Icons ship as individual components under the ./icons subpath — IconPencil, IconChevronDown, etc. Each accepts the same locked prop surface (size, color, label, className, style, ref). The allowlist (Lucide-backed and custom Carto SVGs alike) is owned by VizD and curated inside the kit; consumers can't extend it from outside, and direct lucide-react imports outside this module are intentionally out of bounds.

Fonts

Carto components render in Inter (Google Fonts) and Satoshi (Fontshare). For the fastest first paint, add the following <link> tags to your app shell <head> so the fetches start during HTML parse, before any Carto JS runs:

<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://api.fontshare.com" crossorigin />
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css?family=Inter:400,400i,500,500i,700,700i&display=optional"
/>
<link
  rel="stylesheet"
  href="https://api.fontshare.com/v2/css?f[]=satoshi@900,700,500,400&display=optional"
/>

The kit also injects these links at module load as a runtime safety net, so components don't render in fallback indefinitely if you skip the shell setup — but the shell pattern is strictly preferable: fonts arrive before paint instead of after. See .storybook/preview-head.html for the canonical reference.

Source layout

Component code lives in src/components/<Component>/. Each component is a sibling group: <Component>.tsx (render only), <Component>.css.ts (vanilla-extract recipe), types.ts (props + variant unions), <Component>.test.tsx, and stories/<Component>.stories.tsx. Icons follow a slightly different shape — they ship from src/icons/ via factory functions; see src/icons/custom/README.md for the custom-icon workflow.

Common tasks (build, test, typecheck, typedoc, storybook) run from the repo root via pnpm build:carto-react-kit, pnpm test:carto-react-kit, etc. See the root package.json for the full list.

Local testing

Vitest is split into two projects (see vitest.config.ts):

  • unit — jsdom, runs every *.test.tsx. This is what pnpm test and CI's Test job run.
  • storybook — real Chromium via @vitest/browser-playwright, runs every *.stories.tsx through @storybook/addon-vitest. This is what the Run tests button in the Storybook UI and pnpm test-storybook use locally. CI does not run this project — Chromatic catches play-function regressions in the cloud.

The storybook project needs Playwright's Chromium binary installed locally — it lives outside node_modules at ~/Library/Caches/ms-playwright/ (macOS) or ~/.cache/ms-playwright/ (Linux), ~150 MB. Run once per machine:

pnpm --filter @servicetitan/carto-react-kit exec playwright install chromium

You only need this if you (a) click Run tests in the Storybook UI or (b) run pnpm test-storybook locally. Browsing stories with pnpm storybook and running unit tests with pnpm test do not need it.

Storybook

pnpm storybook:carto-react-kit

Stories render in light DOM by default. The Storybook toolbar has a Shadow toggle that wraps the story in an open shadow root (data-mfe-name="test-mfe"), mirroring how Carto components run inside MFE shadow roots in the host monolith. Switch to Shadow mode when you specifically want to validate CSS isolation against monolith styles — a red dotted outline flags the special mode.

Shadow mode clones document.head styles into the shadow root, surfacing collisions where monolith global selectors match Carto markup. It is not a fidelity environment for hover/focus testing — non-bubbling DOM events (pointerenter, mouseenter) can't cross shadow boundaries and React 18's polyfill can't bridge them across the outer-Storybook / inner-portal split. See src/internal/components/Shadow/Shadow.tsx for details; develop hover-driven components in Fragment mode.

Monolith CSS snapshot

preview-head.html loads real monolith stylesheets so the Storybook page environment matches what an MFE inherits from the host. A snapshot lives at public/monolith-css/. To refresh it:

pnpm refresh-monolith-css:carto-react-kit

The script sources the bundles two different ways:

  • app-css, sui, kendo-css, main — pulled from the public ServiceTitan CDN (https://go.servicetitan.com/scripts/build/). Hashes are resolved on the fly via the desktop and desktop-legacy webpack manifests, so refreshes pick up the current monolith build automatically.
  • anvil2, design-system — built locally from the @servicetitan/anvil2 and @servicetitan/design-system npm devDeps. anvil2 is concatenated from dist/*.css (excluding bundles the package vendors from old monolith builds); design-system uses dist/system.css directly. The refresh-monolith-css script always runs pnpm update @servicetitan/anvil2 first so anvil2 is on the latest published version before the snapshot is rebuilt. design-system is frozen so it stays where it's pinned.

No monolith checkout is required.