{"_id":"@apex-inc/react","_rev":"6-a75686e0e72f1bfd1487f7f1c855caf1","name":"@apex-inc/react","dist-tags":{"latest":"0.4.4"},"versions":{"0.3.0":{"name":"@apex-inc/react","version":"0.3.0","keywords":["apex","react","preferences","notifications","preference-center"],"license":"MIT","_id":"@apex-inc/react@0.3.0","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"dist":{"shasum":"a45229d4b54cab40bac4efd05168292dade53e14","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.3.0.tgz","fileCount":27,"integrity":"sha512-6cIIHyRd4SYIiSl00zCozywI+Rr1j9KwckMfmLH43V/0y+vI37gQoM5a2V1waOwcrBJsxzWhB9+ux2kUJwQCgA==","signatures":[{"sig":"MEUCIGBhsmnRawS5OCyoedj8PUdCaMjK3vEyPbx6YoRIlnPYAiEA/Qnp45HT1oGYzP1ngAdukqu8ZFBf9241319W7Y3ihdY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":85675},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"77fc660e442d3c49d7b3f7aa22c5d7d4dea4f580","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"_npmVersion":"10.9.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"sideEffects":false,"_nodeVersion":"23.11.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react_0.3.0_1781487189335_0.09012319447583117","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@apex-inc/react","version":"0.4.0","keywords":["apex","react","preferences","notifications","preference-center"],"license":"MIT","_id":"@apex-inc/react@0.4.0","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"dist":{"shasum":"c990cf2066059cfa083a14d1ddad823f37275509","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.4.0.tgz","fileCount":27,"integrity":"sha512-duzcoJtWxxHRAzReT8Otx6nJP4ezWNIXGVM3QmRA64XLNvdwtx8mI4PW8LJH5ULty74bXe0nw+sApGjzgDDtOQ==","signatures":[{"sig":"MEQCIB6gPrBgIsdE2atRkchcylbLJ5ehlafxX7z+76dRJO1gAiBAJR4rUW17OQnul3MAtlPLfTIWJ4P00dyniBbfWNcSXQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":94444},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"6d603ebd61cbeae766908f839253180be1536246","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"_npmVersion":"10.8.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react_0.4.0_1784144549441_0.7906404404712359","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@apex-inc/react","version":"0.4.1","keywords":["apex","react","preferences","notifications","preference-center"],"license":"MIT","_id":"@apex-inc/react@0.4.1","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"dist":{"shasum":"50826a6f273d2510572c52273a60ff0dce335a53","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.4.1.tgz","fileCount":27,"integrity":"sha512-SaULERfW3tAayZ71r0WNZW6b6iXKt7JAE9nL4TWY8REVZXkpeXDmCCqncAtd/xo/cKbv/yuJZPRWMhgp79PQFQ==","signatures":[{"sig":"MEUCIGV07EJOut9RHg7+OTxZUJCxB5a984kLS7ikAcmsNVFUAiEAwprLI0SqDEdvawnpXFeViELAsZeU1fHn54foerMEne0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97443},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"ae6ab75089a192045b4af5af6d2606094017c37e","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"_npmVersion":"10.8.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react_0.4.1_1786739078830_0.6625079433089902","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@apex-inc/react","version":"0.4.2","keywords":["apex","react","preferences","notifications","preference-center"],"license":"MIT","_id":"@apex-inc/react@0.4.2","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"dist":{"shasum":"c209212db904cd22026b7f8ad347b38bae1bc760","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.4.2.tgz","fileCount":32,"integrity":"sha512-u3gCs7LilnJRMx6HzT5QkIUbouQsWwyg3A7Qb1aVj9Hp0/Ab/CiYSatDdJAityPlpiotic26VSBvwAo5pn54zg==","signatures":[{"sig":"MEUCIGrwfzHE7lTbHAcYwCoOUKoh9CRwDKaY8Y55X0cv2BHOAiEAuuIy1mKg+XujShTzm26fAmuNaohuVD6jNReLw/9bEy0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHF/sVQgos/P+Ul8oiqc//J7LtU2qR0ob4tX57sG2PuzAiEA3IA0Wi4pY/MDME4hUnpGyG7nTgtQtcPs6IE6t3S4YSc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109910},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"ed7864be12b4dfa54aab90bc743ad2df5c412107","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"_npmVersion":"10.8.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react_0.4.2_1787864812477_0.27998052868399226","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@apex-inc/react","version":"0.4.3","keywords":["apex","react","preferences","notifications","preference-center"],"license":"MIT","_id":"@apex-inc/react@0.4.3","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"dist":{"shasum":"66b0d36f73aa495b8229841604885c6a859a30c2","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.4.3.tgz","fileCount":32,"integrity":"sha512-I1pux0jLU078B6RGyFjF2HX1Mv8H1Jtznm/ayt5XJd8xKVphTdNGi8C2aYmxSiwKeXHmZGP/bdZkiQX+CP+TJg==","signatures":[{"sig":"MEUCIQDrfpmw2kxuaLRb0Aktwxmz/ND52fCpw9ZMLimjCqYFygIgANStY0OlUYgy8YsHVc1T4kNBdvvXsVqAn6+Y/cekb0M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDNpXerbncwYu+vfzJp5ZhfDFd5umHT5uyYurxa34RHUAIgf6tkVMxnklU45usvDPUBNYcWBZRwhMIAjluksfaiYaI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117562},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"7e9812b1523fb3640a27e283893f111ebf2d4250","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"_npmVersion":"10.8.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"tmp":"tmp/react_0.4.3_1788025622655_0.41690010000359234","host":"s3://npm-registry-packages-npm-production"}},"0.4.4":{"_id":"@apex-inc/react@0.4.4","dist":{"shasum":"51202d7f379948ea2fc3127250b23f08f2dff98d","tarball":"https://registry.npmjs.org/@apex-inc/react/-/react-0.4.4.tgz","fileCount":32,"integrity":"sha512-vprD1pBB+QhnDhd158ZAMwZZkSTLqiMya0KbUde/LwUUWig4ORxfqjg5X0dpNZ49g6UDvwmvKfbtc36VxOozFA==","signatures":[{"sig":"MEUCIQCJKKvssZ93MKX+SAWVdTnVvi2Ugv1Y+jj3LDseJBdeqgIgOjeEjYCPOR8p5pv0lIqqYA2DLPkKWTKuvnbYRwCQy7U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCy5HpavDxcaB4tp7VWDmFbGanqULoLeRDORC7cyB2f5QIgWucEU581ZucROhsOtDpEkF3xwafZZKXFG7CI8Key7FA="}],"unpackedSize":117562},"main":"dist/index.js","name":"@apex-inc/react","types":"dist/index.d.ts","module":"dist/esm/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/esm/index.js","require":"./dist/index.js"}},"gitHead":"306530a3737ba47aa286f1f853f6847b7e2b3b5b","license":"MIT","scripts":{"dev":"tsc --watch","build":"tsc && tsc -p tsconfig.esm.json"},"version":"0.4.4","_npmUser":{"name":"apex.inc","email":"chris@apex.inc"},"keywords":["apex","react","preferences","notifications","preference-center"],"_npmVersion":"10.8.2","description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","directories":{},"maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.0.0","react-dom":"^18.0.0","typescript":"^5.7.0","@types/react":"^18.0.0","@types/react-dom":"^18.0.0"},"peerDependencies":{"react":">=17.0.0","react-dom":">=17.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react_0.4.4_1788030387503_0.2162693168343226"}}},"time":{"created":"2026-06-15T01:33:09.191Z","modified":"2026-08-29T19:06:27.750Z","0.3.0":"2026-06-15T01:33:09.583Z","0.4.0":"2026-07-15T19:42:29.657Z","0.4.1":"2026-08-14T20:24:38.969Z","0.4.2":"2026-08-27T21:06:52.568Z","0.4.3":"2026-08-29T17:47:02.737Z","0.4.4":"2026-08-29T19:06:27.590Z"},"license":"MIT","keywords":["apex","react","preferences","notifications","preference-center"],"description":"React components and hooks for Apex — ApexPreferenceCenter for communication preferences plus useApexVariant for code-level A/B experiments.","maintainers":[{"name":"apex.inc","email":"chris@apex.inc"}],"readme":"# @apex-inc/react\n\nEmbeddable React components for [Apex](https://apex.inc) communication surfaces.\n\n**v0.1 — MVP.** Ships `<ApexPreferenceCenter>` only. Embeddable inbox and web-push subscription components arrive in v0.2 once a design partner validates demand.\n\n## Experiments — `useApexVariant`\n\n```tsx\nimport { useApexVariant } from \"@apex-inc/react\";\n\nconst variant = useApexVariant(\"exp_123\");\n```\n\nMerchants still write that line and branch in React. First HTML is\nflicker-free only when the server already assigned the visitor and\npassed that arm in.\n\nOn Next.js / Remix: mint or read the `apex_vid` cookie on the document\nrequest, assign with the same rules as `GET /api/experiments/{id}/assign`,\nand pass that arm. `{ search }` makes `?_apex_preview=` match on first\nHTML.\n\nIf you use Next.js, install `@apex-inc/next` (visitor middleware +\n`assignExperiments`). Pass the result to `<ApexProvider assignments>`.\n\n```tsx\nconst variant = useApexVariant(\"exp_123\", { initialVariant, search });\n// or:\n// <ApexProvider assignments={{ exp_123: variant }} search={search}>\n```\n\nA client-only SPA cannot know the arm before first HTML. Do not promise\nno flicker there. Do not hide the page until `/assign` returns.\n\nSnippet mode (Apex mutates the DOM) is a different path. Do not conflate.\n\n## Install\n\n```bash\nnpm install @apex-inc/react @apex-inc/sdk\n```\n\n## Quick start (styled default)\n\n```tsx\nimport { ApexPreferenceCenter } from \"@apex-inc/react\";\n\nexport default function PreferencesPage({ token }: { token: string }) {\n  return <ApexPreferenceCenter endUserAuth={{ token }} />;\n}\n```\n\nServer-side, mint the token with the Apex SDK:\n\n```ts\n// app/api/apex-token/route.ts (Next.js example)\nimport { signEndUserToken } from \"@apex-inc/sdk/tokens\";\n\nexport async function GET(request: Request) {\n  const user = await getCurrentUser(request);\n  const token = signEndUserToken({\n    workspaceKey: process.env.APEX_PROJECT_KEY!,\n    endUserId: user.id,\n    expiresIn: 3600,\n  });\n  return Response.json({ token });\n}\n```\n\nThe token is short-lived by design — refresh from your server when it expires.\n\n## Customizing the look\n\n```tsx\n<ApexPreferenceCenter\n  endUserAuth={{ token }}\n  theme={{\n    accentColor: \"#0066FF\",\n    fontFamily: '\"Inter\", system-ui, sans-serif',\n    borderRadius: 12,\n  }}\n/>\n```\n\n## Headless — bring your own UI\n\nWhen the styled default doesn't match your design system, render the component with your own JSX:\n\n```tsx\nimport { ApexPreferenceCenter, type ApexChannel } from \"@apex-inc/react\";\n\nconst CHANNELS: ApexChannel[] = [\"email\", \"inbox\", \"web_push\", \"mobile_push\"];\n\nexport default function PreferencesPage({ token }: { token: string }) {\n  return (\n    <ApexPreferenceCenter\n      endUserAuth={{ token }}\n      render={(state) => {\n        if (state.loading) return <Spinner />;\n        if (!state.prefs) return <ErrorState />;\n        return (\n          <YourCard>\n            {CHANNELS.map((ch) => (\n              <YourSwitch\n                key={ch}\n                label={ch}\n                checked={state.prefs!.channelPreferences[ch] ?? true}\n                onChange={(v) => state.setChannel(ch, v)}\n              />\n            ))}\n            <YourDangerSwitch\n              label=\"Unsubscribe from everything\"\n              checked={state.prefs.globalOptOut}\n              onChange={state.setGlobalOptOut}\n            />\n          </YourCard>\n        );\n      }}\n    />\n  );\n}\n```\n\nOr use the `useApexPreferences` hook directly if you'd rather not nest your UI under a render prop.\n\n## API\n\n### `<ApexPreferenceCenter>` props\n\n| Prop | Type | Required | Description |\n|---|---|---|---|\n| `endUserAuth` | `{ token: string }` or `{ sessionCookie: true }` | yes | Auth credentials. Use `{ token }` for any external host. |\n| `apiBaseUrl` | `string` | no | Defaults to `https://app.apex.inc`. Override for self-hosted Apex. |\n| `workspaceKey` | `string` | no | Workspace ID. Read from token claims when using `{ token }` auth. |\n| `endUserId` | `string` | no | End-user ID. Read from token claims when using `{ token }` auth. |\n| `theme` | `ApexThemeTokens` | no | Colour and font overrides for the styled default. |\n| `render` | `(state) => JSX` | no | Headless override. When provided, the styled default is skipped. |\n\n### `useApexPreferences(options)`\n\nReturns `{ prefs, loading, saving, saved, error, refresh, setGlobalOptOut, setChannel, setCommunicationOverride }`. Same options as the component minus `theme` and `render`.\n\n## What ships next\n\nThe roadmap for v0.2 is gated on at least one production design partner asking for it. The most likely additions are:\n\n- `<ApexInbox>` — drop-in bell + dropdown that mirrors the dashboard's `NotificationBell`.\n- `useApexWebPushSubscription` — headless hook around `navigator.serviceWorker.register('/apex-push-sw.js')` + the subscribe endpoint.\n- An Apex-provided service-worker template you can copy into your `public/` folder.\n\nUntil then, keep using Apex's hosted preferences page at `https://app.apex.inc/preferences/<token>` for the customer-facing inbox + web push surfaces.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}