@usecontextlayer/sdk 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @usecontextlayer/sdk
2
2
 
3
- Tools for ContextLayer React Router apps. In local development, calls execute through the ContextLayer platform using your assigned Composio Platform connections.
3
+ ContextLayer integration for React Router apps: the shared document Layout and Tools/Viewer capabilities. In local development, tool calls execute through the ContextLayer platform using your assigned Composio Platform connections.
4
4
 
5
5
  Create an app with `npx @usecontextlayer/cli init my-app`. The CLI installs this package and configures a development-only Cloudflare Worker and native service binding. Use the generated app's normal `pnpm dev` command. First-party `@usecontextlayer/*` packages are exempt from pnpm's release-age policy in generated projects.
6
6
 
@@ -8,7 +8,19 @@ Create an app with `npx @usecontextlayer/cli init my-app`. The CLI installs this
8
8
 
9
9
  Run `ctx login` to save your ContextLayer login. Declare `work-email` as an individual Gmail requirement in `public/slate.json`, then use `ctx connections list` to find your connection and `ctx connection local assign work-email <connection_id>` to assign it. Run local commands from the app root.
10
10
 
11
- When `pnpm dev` starts, `contextlayer(env)` from `@usecontextlayer/sdk/vite` configures the Cloudflare Vite plugin and calls the CLI-owned `getLocalToolsBindings` helper. This Node helper reads the AppID from Git origin and obtains a current access token using the same saved login as the CLI. Only the AppID, platform URL, and access token enter the local Tools Worker. The refresh token stays in `~/.contextlayer/auth.json`; the Composio project key stays on the platform. Restart `pnpm dev` when the access token expires.
11
+ When `pnpm dev` starts, `contextlayer(env)` from `@usecontextlayer/sdk/vite` configures the Cloudflare Vite plugin and calls the CLI-owned `getLocalToolsBindings` helper. This Node helper reads the AppID from Git origin and obtains a current access token using the same saved login as the CLI. The AppID, platform URL, auth issuer, and access token enter the existing local auxiliary Worker, which exports Tools and Viewer entrypoints. The refresh token stays in `~/.contextlayer/auth.json`; the Composio project key stays on the platform. Restart `pnpm dev` when the access token expires.
12
+
13
+ ## App Layout
14
+
15
+ The generated `app/root.tsx` re-exports the SDK's document Layout and root loader:
16
+
17
+ ```tsx
18
+ export { Layout, loader } from "@usecontextlayer/sdk/react"
19
+ ```
20
+
21
+ The Layout owns the HTML document, React Router's metadata, links, scripts, scroll restoration, and the shared ContextLayer header. The app owns its routes, root component, error boundary, stylesheet, and font links. The thin, full-width header expands an inline settings panel, moving the app content down. Connection controls are not implemented yet.
22
+
23
+ The header and settings panel render into a native ShadowRoot through a React portal after hydration. Vite processes `@usecontextlayer/sdk/styles.css?inline` into a stylesheet string, which is inserted only into that ShadowRoot; apps must not import the SDK stylesheet globally. The shadcn Base UI Collapsible owns the single header trigger, open state, accessibility, and panel lifecycle; its content remains in normal document flow. The lowercase wordmark uses the existing Fugaz One font through the browser's Font Loading API. The app's Tailwind and shadcn base-nova configuration are independent of these chrome styles. Chrome rendering lives in the SDK rather than being copied into each app or injected into HTML by the dispatcher.
12
24
 
13
25
  ## A loader that reads Gmail
14
26
 
@@ -30,11 +42,26 @@ export async function loader({ context }: LoaderFunctionArgs) {
30
42
 
31
43
  Calls return `{ data, logId }`. Validate the tool-specific `data` in your loader. The complete [Gmail example](examples/gmail.tsx) validates the response with Zod and renders a message list. Copy it to `app/routes/home.tsx` in a generated app and assign your Gmail connection to `work-email`.
32
44
 
45
+ ## Current viewer
46
+
47
+ Read the safe profile in a loader through the request-scoped Viewer capability:
48
+
49
+ ```ts
50
+ import { viewerContext } from "@usecontextlayer/sdk"
51
+ import type { LoaderFunctionArgs } from "react-router"
52
+
53
+ export async function loader({ context }: LoaderFunctionArgs) {
54
+ return context.get(viewerContext).getCurrentUser()
55
+ }
56
+ ```
57
+
58
+ The result is `{ id, name, image }` with nullable image, or `null` for an anonymous viewer. Local Viewer sends the saved CLI access token directly to web's `/api/me`; hosted Viewer sends the existing viewer cookie to that same endpoint. `CTX_AUTH_ISSUER` determines web's origin. Web verifies identity; the capability validates its response with Zod. The app receives only profile data through RPC. No access token, session cookie, refresh token, or platform profile proxy is exposed. The SDK root loader reads this profile once and Layout consumes the root route data to show the avatar and name in the always-visible header. Anonymous viewers see “Not signed in”. The installed local loader has been verified through the native development Worker. Hosted WfP verification remains pending.
59
+
33
60
  ## Runtime ownership
34
61
 
35
- The package root exports the `Tools` interface and `toolsContext`. `@usecontextlayer/sdk/local` exports the local `Tools` Worker entrypoint. `@usecontextlayer/sdk/worker` exports `createApp`, which creates the React Router request handler and supplies `toolsContext` from the local binding or production request props. `@usecontextlayer/sdk/vite` owns the `contextlayer` integration. The CLI package owns the Node startup helper and saved-login handling. The generated application supplies its virtual server-build import, mode, and development flag through thin Worker wiring, and composes Vite plugins. The Cloudflare Vite plugin runs the auxiliary Worker only in development; production bundles exclude it and its service binding.
62
+ The package root exports the `Tools` and `Viewer` interfaces, `User` profile type, and `toolsContext`/`viewerContext`. `@usecontextlayer/sdk/react` exports the shared React Router document `Layout` and profile `loader`; `@usecontextlayer/sdk/styles.css` exports the chrome stylesheet for Vite to process and render inside the ShadowRoot. `@usecontextlayer/sdk/local` exports the local `Tools` and `Viewer` Worker entrypoints. `@usecontextlayer/sdk/worker` exports `createApp`, which creates the React Router request handler and supplies `toolsContext` and `viewerContext` from local bindings or production request props. The native default `viewerContext` returns null for anonymous viewers. `@usecontextlayer/sdk/vite` owns the `contextlayer` integration. The CLI package owns the Node startup helper and saved-login handling. The generated application supplies its virtual server-build import, mode, and development flag through thin Worker wiring, and composes Vite plugins. The Cloudflare Vite plugin runs the auxiliary Worker only in development; production bundles exclude it and its service binding.
36
63
 
37
- The platform execution API is implemented; deployed viewer integration is not yet implemented. The packaged request handler reserves `ctx.props.tools` for that later path. Local access-token bindings are not included in production builds.
64
+ In hosted apps, the dispatcher supplies `ctx.props.tools` as a request-scoped RPC handle. Its methods call the same platform execution API using the viewer session; the app cannot read the underlying viewer credential. The platform resolves the signed-in viewer’s assignment for the app and slug, so a viewer using the same account as the CLI uses the same saved assignment. Local access-token bindings are not included in production builds.
38
65
 
39
66
  ## Vite configuration
40
67
 
@@ -52,6 +79,6 @@ export default defineConfig((env) => ({
52
79
  }))
53
80
  ```
54
81
 
55
- This integration supplies the Cloudflare plugin; do not add a second instance. It uses the generated `workers/local-tools/wrangler.jsonc` to start the local Tools Worker and provides its development-only service binding. At development startup, the CLI reads the app's Git origin and saved ContextLayer login. Production builds exclude local credentials and the auxiliary Worker.
82
+ This integration supplies the Cloudflare plugin; do not add a second instance. It uses the generated `workers/local-tools/wrangler.jsonc` to start the local Tools Worker and provides its development-only Tools and Viewer service bindings. At development startup, the CLI reads the app's Git origin and saved ContextLayer login. Production builds exclude local credentials and the auxiliary Worker.
56
83
 
57
- The app retains its routes, `public/slate.json`, and thin Worker/configuration files. `@usecontextlayer/sdk/worker` owns the React Router request handler and Tools context setup.
84
+ The app retains its routes, `public/slate.json`, and thin Worker/configuration files. `@usecontextlayer/sdk/worker` owns the React Router request handler and Tools/Viewer context setup.
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ //#region viewer.d.ts
3
+ declare const userSchema: z.ZodObject<{
4
+ id: z.ZodString;
5
+ image: z.ZodNullable<z.ZodString>;
6
+ name: z.ZodString;
7
+ }, z.core.$strip>;
8
+ type User = z.infer<typeof userSchema>;
9
+ interface Viewer {
10
+ getCurrentUser(): Promise<User | null>;
11
+ }
12
+ //#endregion
13
+ //#region index.d.ts
14
+ interface Tools {
15
+ call(slug: string, toolSlug: string, args: Record<string, unknown>): Promise<{
16
+ data: unknown;
17
+ logId: string;
18
+ }>;
19
+ }
20
+ declare const toolsContext: import("react-router").RouterContext<Tools>;
21
+ declare const viewerContext: import("react-router").RouterContext<Viewer>;
22
+ //#endregion
23
+ export { Viewer as a, User as i, toolsContext as n, viewerContext as r, Tools as t };
24
+ //# sourceMappingURL=index-DbuYj6qS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-DbuYj6qS.d.ts","names":[],"sources":["../viewer.ts","../index.ts"],"mappings":";;cAEa,YAAU,EAAA;;;;GAIrB,EAAA,KAAA;KAEU,OAAO,EAAE,aAAa;UAEjB;EAChB,kBAAkB,QAAQ;;;;UCNV;EAChB,KACC,cACA,kBACA,MAAM,0BACJ;IAAU;IAAe;;;cAGhB,qCAAY,cAAA;cACZ,sCAAa,cAAA"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,2 @@
1
- //#region index.d.ts
2
- export interface Tools {
3
- call(slug: string, toolSlug: string, args: Record<string, unknown>): Promise<{
4
- data: unknown;
5
- logId: string;
6
- }>;
7
- }
8
- export declare const toolsContext: import("react-router").RouterContext<Tools>;
9
- //#endregion
10
- //# sourceMappingURL=index.d.ts.map
1
+ import { a as Viewer, i as User, n as toolsContext, r as viewerContext, t as Tools } from "./index-DbuYj6qS.js";
2
+ export { Tools, type User, type Viewer, toolsContext, viewerContext };
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import { createContext } from "react-router";
2
2
  //#region index.ts
3
3
  const toolsContext = createContext();
4
+ const viewerContext = createContext({ getCurrentUser: async () => null });
4
5
  //#endregion
5
- export { toolsContext };
6
+ export { toolsContext, viewerContext };
6
7
 
7
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../index.ts"],"sourcesContent":["import { createContext } from \"react-router\"\n\nexport interface Tools {\n\tcall(\n\t\tslug: string,\n\t\ttoolSlug: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<{ data: unknown; logId: string }>\n}\n\nexport const toolsContext = createContext<Tools>()\n"],"mappings":";;AAUA,MAAa,eAAe,cAAqB"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../index.ts"],"sourcesContent":["import { createContext } from \"react-router\"\nimport type { Viewer } from \"@/viewer\"\n\nexport type { User, Viewer } from \"@/viewer\"\n\nexport interface Tools {\n\tcall(\n\t\tslug: string,\n\t\ttoolSlug: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<{ data: unknown; logId: string }>\n}\n\nexport const toolsContext = createContext<Tools>()\nexport const viewerContext = createContext<Viewer>({ getCurrentUser: async () => null })\n"],"mappings":";;AAaA,MAAa,eAAe,cAAqB;AACjD,MAAa,gBAAgB,cAAsB,EAAE,gBAAgB,YAAY,KAAK,CAAC"}
package/dist/local.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { Tools as Tools$1 } from "./index.js";
1
+ import { a as Viewer$1, t as Tools$1 } from "./index-DbuYj6qS.js";
2
2
  import { WorkerEntrypoint } from "cloudflare:workers";
3
3
  import { z } from "zod";
4
4
  //#region env.d.ts
5
5
  declare const schema: z.ZodObject<{
6
6
  CTX_ACCESS_TOKEN: z.ZodString;
7
7
  CTX_APP_ID: z.ZodUUID;
8
+ CTX_AUTH_ISSUER: z.ZodURL;
8
9
  CTX_PLATFORM_URL: z.ZodURL;
9
10
  }, z.core.$strip>;
10
11
  type Bindings = z.input<typeof schema>;
@@ -16,5 +17,12 @@ export declare class Tools extends WorkerEntrypoint<Bindings> implements Tools$1
16
17
  logId: string;
17
18
  }>;
18
19
  }
20
+ export declare class Viewer extends WorkerEntrypoint<Bindings> implements Viewer$1 {
21
+ getCurrentUser(): Promise<{
22
+ id: string;
23
+ image: string | null;
24
+ name: string;
25
+ } | null>;
26
+ }
19
27
  //#endregion
20
28
  //# sourceMappingURL=local.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","names":[],"sources":["../env.ts","../local.ts"],"mappings":";;;;cAEM,QAAM,EAAA;;;;GAIV,EAAA,KAAA;KACU,WAAW,EAAE,aAAa;;;qBCIzB,cAAc,iBAAiB,qBAAqB;EAC1D,KAAK,cAAc,kBAAkB,MAAM,0BAAuB"}
1
+ {"version":3,"file":"local.d.ts","names":[],"sources":["../env.ts","../local.ts"],"mappings":";;;;cAEM,QAAM,EAAA;;;;;GAKV,EAAA,KAAA;KACU,WAAW,EAAE,aAAa;;;qBCIzB,cAAc,iBAAiB,qBAAqB;EAC1D,KAAK,cAAc,kBAAkB,MAAM,0BAAuB;;;;;qBAoB5D,eAAe,iBAAiB,qBAAqB;EAC3D,kBAAc"}
package/dist/local.js CHANGED
@@ -4,10 +4,18 @@ import { z } from "zod";
4
4
  const schema = z.object({
5
5
  CTX_ACCESS_TOKEN: z.string().min(1),
6
6
  CTX_APP_ID: z.uuid(),
7
+ CTX_AUTH_ISSUER: z.url(),
7
8
  CTX_PLATFORM_URL: z.url()
8
9
  });
9
10
  const parseEnv = (bindings) => schema.parse(bindings);
10
11
  //#endregion
12
+ //#region viewer.ts
13
+ const userSchema = z.object({
14
+ id: z.string().min(1),
15
+ image: z.string().nullable(),
16
+ name: z.string()
17
+ });
18
+ //#endregion
11
19
  //#region local.ts
12
20
  const execution = z.object({
13
21
  data: z.record(z.string(), z.unknown()),
@@ -38,7 +46,16 @@ var Tools = class extends WorkerEntrypoint {
38
46
  };
39
47
  }
40
48
  };
49
+ var Viewer = class extends WorkerEntrypoint {
50
+ async getCurrentUser() {
51
+ const env = parseEnv(this.env);
52
+ const response = await fetch(new URL("/api/me", env.CTX_AUTH_ISSUER), { headers: { authorization: `Bearer ${env.CTX_ACCESS_TOKEN}` } });
53
+ if (response.status === 401) return null;
54
+ if (!response.ok) throw new Error(`Identity request failed: HTTP ${response.status}`);
55
+ return userSchema.parse(await response.json());
56
+ }
57
+ };
41
58
  //#endregion
42
- export { Tools };
59
+ export { Tools, Viewer };
43
60
 
44
61
  //# sourceMappingURL=local.js.map
package/dist/local.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","names":[],"sources":["../env.ts","../local.ts"],"sourcesContent":["import { z } from \"zod\"\n\nconst schema = z.object({\n\tCTX_ACCESS_TOKEN: z.string().min(1),\n\tCTX_APP_ID: z.uuid(),\n\tCTX_PLATFORM_URL: z.url(),\n})\nexport type Bindings = z.input<typeof schema>\nexport const parseEnv = (bindings: Bindings) => schema.parse(bindings)\n","import { WorkerEntrypoint } from \"cloudflare:workers\"\nimport { z } from \"zod\"\nimport { type Bindings, parseEnv } from \"@/env\"\nimport type { Tools as ToolsContract } from \"@/index\"\n\nconst execution = z.object({\n\tdata: z.record(z.string(), z.unknown()),\n\terror: z.string().nullable(),\n\tlogId: z.string(),\n})\n\nexport class Tools extends WorkerEntrypoint<Bindings> implements ToolsContract {\n\tasync call(slug: string, toolSlug: string, args: Record<string, unknown>) {\n\t\tconst env = parseEnv(this.env)\n\t\tconst response = await fetch(\n\t\t\tnew URL(`/api/apps/${env.CTX_APP_ID}/tools/call`, env.CTX_PLATFORM_URL),\n\t\t\t{\n\t\t\t\tbody: JSON.stringify({ arguments: args, slug, tool: toolSlug }),\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${env.CTX_ACCESS_TOKEN}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tmethod: \"POST\",\n\t\t\t},\n\t\t)\n\t\tif (!response.ok) throw new Error(`Tool call failed: HTTP ${response.status}`)\n\t\tconst result = execution.parse(await response.json())\n\t\tif (result.error !== null) throw new Error(`${result.error} (log: ${result.logId})`)\n\t\treturn { data: result.data, logId: result.logId }\n\t}\n}\n"],"mappings":";;;AAEA,MAAM,SAAS,EAAE,OAAO;CACvB,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CAClC,YAAY,EAAE,KAAK;CACnB,kBAAkB,EAAE,IAAI;AACzB,CAAC;AAED,MAAa,YAAY,aAAuB,OAAO,MAAM,QAAQ;;;ACHrE,MAAM,YAAY,EAAE,OAAO;CAC1B,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC;CACtC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,OAAO,EAAE,OAAO;AACjB,CAAC;AAED,IAAa,QAAb,cAA2B,iBAAoD;CAC9E,MAAM,KAAK,MAAc,UAAkB,MAA+B;EACzE,MAAM,MAAM,SAAS,KAAK,GAAG;EAC7B,MAAM,WAAW,MAAM,MACtB,IAAI,IAAI,aAAa,IAAI,WAAW,cAAc,IAAI,gBAAgB,GACtE;GACC,MAAM,KAAK,UAAU;IAAE,WAAW;IAAM;IAAM,MAAM;GAAS,CAAC;GAC9D,SAAS;IACR,eAAe,UAAU,IAAI;IAC7B,gBAAgB;GACjB;GACA,QAAQ;EACT,CACD;EACA,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,0BAA0B,SAAS,QAAQ;EAC7E,MAAM,SAAS,UAAU,MAAM,MAAM,SAAS,KAAK,CAAC;EACpD,IAAI,OAAO,UAAU,MAAM,MAAM,IAAI,MAAM,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM,EAAE;EACnF,OAAO;GAAE,MAAM,OAAO;GAAM,OAAO,OAAO;EAAM;CACjD;AACD"}
1
+ {"version":3,"file":"local.js","names":[],"sources":["../env.ts","../viewer.ts","../local.ts"],"sourcesContent":["import { z } from \"zod\"\n\nconst schema = z.object({\n\tCTX_ACCESS_TOKEN: z.string().min(1),\n\tCTX_APP_ID: z.uuid(),\n\tCTX_AUTH_ISSUER: z.url(),\n\tCTX_PLATFORM_URL: z.url(),\n})\nexport type Bindings = z.input<typeof schema>\nexport const parseEnv = (bindings: Bindings) => schema.parse(bindings)\n","import { z } from \"zod\"\n\nexport const userSchema = z.object({\n\tid: z.string().min(1),\n\timage: z.string().nullable(),\n\tname: z.string(),\n})\n\nexport type User = z.infer<typeof userSchema>\n\nexport interface Viewer {\n\tgetCurrentUser(): Promise<User | null>\n}\n","import { WorkerEntrypoint } from \"cloudflare:workers\"\nimport { z } from \"zod\"\nimport { type Bindings, parseEnv } from \"@/env\"\nimport type { Tools as ToolsContract } from \"@/index\"\nimport { userSchema, type Viewer as ViewerContract } from \"@/viewer\"\n\nconst execution = z.object({\n\tdata: z.record(z.string(), z.unknown()),\n\terror: z.string().nullable(),\n\tlogId: z.string(),\n})\n\nexport class Tools extends WorkerEntrypoint<Bindings> implements ToolsContract {\n\tasync call(slug: string, toolSlug: string, args: Record<string, unknown>) {\n\t\tconst env = parseEnv(this.env)\n\t\tconst response = await fetch(\n\t\t\tnew URL(`/api/apps/${env.CTX_APP_ID}/tools/call`, env.CTX_PLATFORM_URL),\n\t\t\t{\n\t\t\t\tbody: JSON.stringify({ arguments: args, slug, tool: toolSlug }),\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${env.CTX_ACCESS_TOKEN}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tmethod: \"POST\",\n\t\t\t},\n\t\t)\n\t\tif (!response.ok) throw new Error(`Tool call failed: HTTP ${response.status}`)\n\t\tconst result = execution.parse(await response.json())\n\t\tif (result.error !== null) throw new Error(`${result.error} (log: ${result.logId})`)\n\t\treturn { data: result.data, logId: result.logId }\n\t}\n}\n\nexport class Viewer extends WorkerEntrypoint<Bindings> implements ViewerContract {\n\tasync getCurrentUser() {\n\t\tconst env = parseEnv(this.env)\n\t\tconst response = await fetch(new URL(\"/api/me\", env.CTX_AUTH_ISSUER), {\n\t\t\theaders: { authorization: `Bearer ${env.CTX_ACCESS_TOKEN}` },\n\t\t})\n\t\tif (response.status === 401) return null\n\t\tif (!response.ok) throw new Error(`Identity request failed: HTTP ${response.status}`)\n\t\treturn userSchema.parse(await response.json())\n\t}\n}\n"],"mappings":";;;AAEA,MAAM,SAAS,EAAE,OAAO;CACvB,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CAClC,YAAY,EAAE,KAAK;CACnB,iBAAiB,EAAE,IAAI;CACvB,kBAAkB,EAAE,IAAI;AACzB,CAAC;AAED,MAAa,YAAY,aAAuB,OAAO,MAAM,QAAQ;;;ACPrE,MAAa,aAAa,EAAE,OAAO;CAClC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACpB,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,MAAM,EAAE,OAAO;AAChB,CAAC;;;ACAD,MAAM,YAAY,EAAE,OAAO;CAC1B,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC;CACtC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,OAAO,EAAE,OAAO;AACjB,CAAC;AAED,IAAa,QAAb,cAA2B,iBAAoD;CAC9E,MAAM,KAAK,MAAc,UAAkB,MAA+B;EACzE,MAAM,MAAM,SAAS,KAAK,GAAG;EAC7B,MAAM,WAAW,MAAM,MACtB,IAAI,IAAI,aAAa,IAAI,WAAW,cAAc,IAAI,gBAAgB,GACtE;GACC,MAAM,KAAK,UAAU;IAAE,WAAW;IAAM;IAAM,MAAM;GAAS,CAAC;GAC9D,SAAS;IACR,eAAe,UAAU,IAAI;IAC7B,gBAAgB;GACjB;GACA,QAAQ;EACT,CACD;EACA,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,0BAA0B,SAAS,QAAQ;EAC7E,MAAM,SAAS,UAAU,MAAM,MAAM,SAAS,KAAK,CAAC;EACpD,IAAI,OAAO,UAAU,MAAM,MAAM,IAAI,MAAM,GAAG,OAAO,MAAM,SAAS,OAAO,MAAM,EAAE;EACnF,OAAO;GAAE,MAAM,OAAO;GAAM,OAAO,OAAO;EAAM;CACjD;AACD;AAEA,IAAa,SAAb,cAA4B,iBAAqD;CAChF,MAAM,iBAAiB;EACtB,MAAM,MAAM,SAAS,KAAK,GAAG;EAC7B,MAAM,WAAW,MAAM,MAAM,IAAI,IAAI,WAAW,IAAI,eAAe,GAAG,EACrE,SAAS,EAAE,eAAe,UAAU,IAAI,mBAAmB,EAC5D,CAAC;EACD,IAAI,SAAS,WAAW,KAAK,OAAO;EACpC,IAAI,CAAC,SAAS,IAAI,MAAM,IAAI,MAAM,iCAAiC,SAAS,QAAQ;EACpF,OAAO,WAAW,MAAM,MAAM,SAAS,KAAK,CAAC;CAC9C;AACD"}
@@ -0,0 +1,15 @@
1
+ import { LoaderFunctionArgs } from "react-router";
2
+ import { ReactNode } from "react";
3
+ //#region react.d.ts
4
+ export declare function loader({ context }: LoaderFunctionArgs): Promise<{
5
+ user: {
6
+ id: string;
7
+ image: string | null;
8
+ name: string;
9
+ } | null;
10
+ }>;
11
+ export declare function Layout({ children }: {
12
+ children: ReactNode;
13
+ }): import("react").JSX.Element;
14
+ //#endregion
15
+ //# sourceMappingURL=react.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.d.ts","names":[],"sources":["../react.tsx"],"mappings":";;;wBAsBsB,SAAS,WAAW,qBAAkB;;;;;;;wBAyF5C,SAAS;EAAc,UAAU;oBAAW,IAAA"}
package/dist/react.js ADDED
@@ -0,0 +1,192 @@
1
+ import { viewerContext } from "./index.js";
2
+ import { Links, Meta, Scripts, ScrollRestoration, useRouteLoaderData } from "react-router";
3
+ import logoFont from "@fontsource/fugaz-one/files/fugaz-one-latin-400-normal.woff2?url";
4
+ import chromeStyles from "@usecontextlayer/sdk/styles.css?inline";
5
+ import { useCallback, useEffect, useState } from "react";
6
+ import { createPortal } from "react-dom";
7
+ import { Avatar } from "@base-ui/react/avatar";
8
+ import { cn } from "cn";
9
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
+ import { Button } from "@base-ui/react/button";
11
+ import { cva } from "class-variance-authority";
12
+ import { Collapsible } from "@base-ui/react/collapsible";
13
+ //#region components/ui/avatar.tsx
14
+ function Avatar$1({ className, size = "default", ...props }) {
15
+ return /* @__PURE__ */ jsx(Avatar.Root, {
16
+ "data-slot": "avatar",
17
+ "data-size": size,
18
+ className: cn("group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten", className),
19
+ ...props
20
+ });
21
+ }
22
+ function AvatarImage({ className, ...props }) {
23
+ return /* @__PURE__ */ jsx(Avatar.Image, {
24
+ "data-slot": "avatar-image",
25
+ className: cn("aspect-square size-full rounded-full object-cover", className),
26
+ ...props
27
+ });
28
+ }
29
+ function AvatarFallback({ className, ...props }) {
30
+ return /* @__PURE__ */ jsx(Avatar.Fallback, {
31
+ "data-slot": "avatar-fallback",
32
+ className: cn("flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs", className),
33
+ ...props
34
+ });
35
+ }
36
+ //#endregion
37
+ //#region components/ui/button.tsx
38
+ const buttonVariants = cva("group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
39
+ defaultVariants: {
40
+ size: "default",
41
+ variant: "default"
42
+ },
43
+ variants: {
44
+ size: {
45
+ default: "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
46
+ icon: "size-8",
47
+ "icon-lg": "size-9",
48
+ "icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
49
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
50
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
51
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
52
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3"
53
+ },
54
+ variant: {
55
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
56
+ destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
57
+ ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
58
+ link: "text-primary underline-offset-4 hover:underline",
59
+ outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
60
+ secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground"
61
+ }
62
+ }
63
+ });
64
+ function Button$1({ className, variant = "default", size = "default", ...props }) {
65
+ return /* @__PURE__ */ jsx(Button, {
66
+ "data-slot": "button",
67
+ className: cn(buttonVariants({
68
+ className,
69
+ size,
70
+ variant
71
+ })),
72
+ ...props
73
+ });
74
+ }
75
+ //#endregion
76
+ //#region components/ui/collapsible.tsx
77
+ function Collapsible$1({ ...props }) {
78
+ return /* @__PURE__ */ jsx(Collapsible.Root, {
79
+ "data-slot": "collapsible",
80
+ ...props
81
+ });
82
+ }
83
+ function CollapsibleTrigger({ ...props }) {
84
+ return /* @__PURE__ */ jsx(Collapsible.Trigger, {
85
+ "data-slot": "collapsible-trigger",
86
+ ...props
87
+ });
88
+ }
89
+ function CollapsibleContent({ ...props }) {
90
+ return /* @__PURE__ */ jsx(Collapsible.Panel, {
91
+ "data-slot": "collapsible-content",
92
+ ...props
93
+ });
94
+ }
95
+ //#endregion
96
+ //#region react.tsx
97
+ async function loader({ context }) {
98
+ return { user: await context.get(viewerContext).getCurrentUser() };
99
+ }
100
+ function Chrome({ user }) {
101
+ const [shadowRoot, setShadowRoot] = useState(null);
102
+ const attach = useCallback((host) => {
103
+ if (host) setShadowRoot(host.shadowRoot ?? host.attachShadow({ mode: "open" }));
104
+ }, []);
105
+ useEffect(() => {
106
+ const font = new FontFace("ContextLayer Logo", `url("${logoFont}")`, {
107
+ display: "swap",
108
+ weight: "400"
109
+ });
110
+ document.fonts.add(font);
111
+ font.load();
112
+ return () => {
113
+ document.fonts.delete(font);
114
+ };
115
+ }, []);
116
+ return /* @__PURE__ */ jsx("header", {
117
+ ref: attach,
118
+ children: shadowRoot && createPortal(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("style", { children: chromeStyles }), /* @__PURE__ */ jsxs(Collapsible$1, {
119
+ className: "group/chrome",
120
+ children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
121
+ "aria-label": user ? `Toggle ContextLayer settings for ${user.name}` : "Toggle ContextLayer settings",
122
+ render: /* @__PURE__ */ jsx(Button$1, {
123
+ variant: "ghost",
124
+ className: "h-auto w-full justify-between gap-0 rounded-none border-x-0 border-t-0 border-b-slate-200 bg-slate-100 p-0 text-slate-600 hover:bg-slate-200 hover:text-slate-600 aria-expanded:bg-slate-100 aria-expanded:hover:bg-slate-200"
125
+ }),
126
+ children: [/* @__PURE__ */ jsx("span", {
127
+ className: "shrink-0 px-4 py-[6.5px] font-logo text-[13px]/4 font-normal text-slate-500",
128
+ children: "contextlayer"
129
+ }), /* @__PURE__ */ jsxs("span", {
130
+ className: "flex min-w-0 self-stretch",
131
+ children: [/* @__PURE__ */ jsxs("span", {
132
+ className: "flex shrink-0 items-center px-3 text-[13px]/4 font-normal text-slate-400",
133
+ children: [/* @__PURE__ */ jsx("span", {
134
+ className: "group-data-open/chrome:hidden",
135
+ children: "click to open"
136
+ }), /* @__PURE__ */ jsx("span", {
137
+ className: "hidden group-data-open/chrome:inline",
138
+ children: "click to close"
139
+ })]
140
+ }), /* @__PURE__ */ jsx("span", {
141
+ className: "flex min-w-0 items-center gap-2 border-l border-slate-200 py-[3px] pr-3 pl-[3px] text-[13px]/4 font-normal",
142
+ children: user ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Avatar$1, {
143
+ className: "size-[23px] rounded-[3px] after:rounded-[3px]",
144
+ children: [/* @__PURE__ */ jsx(AvatarImage, {
145
+ className: "rounded-[3px]",
146
+ src: user.image ?? void 0,
147
+ alt: ""
148
+ }), /* @__PURE__ */ jsx(AvatarFallback, {
149
+ className: "rounded-[3px] text-[13px]",
150
+ children: user.name.slice(0, 1)
151
+ })]
152
+ }), /* @__PURE__ */ jsx("span", {
153
+ className: "max-w-40 truncate",
154
+ title: user.name,
155
+ children: user.name
156
+ })] }) : /* @__PURE__ */ jsx("span", {
157
+ className: "truncate pl-[9px]",
158
+ children: "Not signed in"
159
+ })
160
+ })]
161
+ })]
162
+ }), /* @__PURE__ */ jsx(CollapsibleContent, {
163
+ className: "h-(--collapsible-panel-height) overflow-hidden bg-slate-100 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none",
164
+ children: /* @__PURE__ */ jsx("div", { className: "min-h-40 border-b border-slate-200" })
165
+ })]
166
+ })] }), shadowRoot)
167
+ });
168
+ }
169
+ function Layout({ children }) {
170
+ const data = useRouteLoaderData("root");
171
+ return /* @__PURE__ */ jsxs("html", {
172
+ lang: "en",
173
+ children: [/* @__PURE__ */ jsxs("head", { children: [
174
+ /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
175
+ /* @__PURE__ */ jsx("meta", {
176
+ name: "viewport",
177
+ content: "width=device-width, initial-scale=1"
178
+ }),
179
+ /* @__PURE__ */ jsx(Meta, {}),
180
+ /* @__PURE__ */ jsx(Links, {})
181
+ ] }), /* @__PURE__ */ jsxs("body", { children: [
182
+ /* @__PURE__ */ jsx(Chrome, { user: data?.user ?? null }),
183
+ children,
184
+ /* @__PURE__ */ jsx(ScrollRestoration, {}),
185
+ /* @__PURE__ */ jsx(Scripts, {})
186
+ ] })]
187
+ });
188
+ }
189
+ //#endregion
190
+ export { Layout, loader };
191
+
192
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","names":["Avatar","AvatarPrimitive","Button","ButtonPrimitive","Collapsible","CollapsiblePrimitive","Collapsible","Button","Avatar"],"sources":["../components/ui/avatar.tsx","../components/ui/button.tsx","../components/ui/collapsible.tsx","../react.tsx"],"sourcesContent":["import { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\"\nimport { cn } from \"cn\"\nimport type * as React from \"react\"\n\nfunction Avatar({\n\tclassName,\n\tsize = \"default\",\n\t...props\n}: AvatarPrimitive.Root.Props & {\n\tsize?: \"default\" | \"sm\" | \"lg\"\n}) {\n\treturn (\n\t\t<AvatarPrimitive.Root\n\t\t\tdata-slot=\"avatar\"\n\t\t\tdata-size={size}\n\t\t\tclassName={cn(\n\t\t\t\t\"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {\n\treturn (\n\t\t<AvatarPrimitive.Image\n\t\t\tdata-slot=\"avatar-image\"\n\t\t\tclassName={cn(\"aspect-square size-full rounded-full object-cover\", className)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction AvatarFallback({ className, ...props }: AvatarPrimitive.Fallback.Props) {\n\treturn (\n\t\t<AvatarPrimitive.Fallback\n\t\t\tdata-slot=\"avatar-fallback\"\n\t\t\tclassName={cn(\n\t\t\t\t\"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\n\treturn (\n\t\t<span\n\t\t\tdata-slot=\"avatar-badge\"\n\t\t\tclassName={cn(\n\t\t\t\t\"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none\",\n\t\t\t\t\"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n\t\t\t\t\"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n\t\t\t\t\"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"avatar-group\"\n\t\t\tclassName={cn(\n\t\t\t\t\"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction AvatarGroupCount({ className, ...props }: React.ComponentProps<\"div\">) {\n\treturn (\n\t\t<div\n\t\t\tdata-slot=\"avatar-group-count\"\n\t\t\tclassName={cn(\n\t\t\t\t\"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage }\n","import { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\n\nconst buttonVariants = cva(\n\t\"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n\t{\n\t\tdefaultVariants: {\n\t\t\tsize: \"default\",\n\t\t\tvariant: \"default\",\n\t\t},\n\t\tvariants: {\n\t\t\tsize: {\n\t\t\t\tdefault:\n\t\t\t\t\t\"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n\t\t\t\ticon: \"size-8\",\n\t\t\t\t\"icon-lg\": \"size-9\",\n\t\t\t\t\"icon-sm\":\n\t\t\t\t\t\"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg\",\n\t\t\t\t\"icon-xs\":\n\t\t\t\t\t\"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3\",\n\t\t\t\tlg: \"h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n\t\t\t\tsm: \"h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5\",\n\t\t\t\txs: \"h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n\t\t\t},\n\t\t\tvariant: {\n\t\t\t\tdefault: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n\t\t\t\tdestructive:\n\t\t\t\t\t\"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n\t\t\t\tghost:\n\t\t\t\t\t\"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n\t\t\t\tlink: \"text-primary underline-offset-4 hover:underline\",\n\t\t\t\toutline:\n\t\t\t\t\t\"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n\t\t\t\tsecondary:\n\t\t\t\t\t\"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n\t\t\t},\n\t\t},\n\t},\n)\n\nfunction Button({\n\tclassName,\n\tvariant = \"default\",\n\tsize = \"default\",\n\t...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n\treturn (\n\t\t<ButtonPrimitive\n\t\t\tdata-slot=\"button\"\n\t\t\tclassName={cn(buttonVariants({ className, size, variant }))}\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Button, buttonVariants }\n","import { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\"\n\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\n\treturn (\n\t\t<CollapsiblePrimitive.Root\n\t\t\tdata-slot=\"collapsible\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\n\treturn (\n\t\t<CollapsiblePrimitive.Trigger\n\t\t\tdata-slot=\"collapsible-trigger\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\n\treturn (\n\t\t<CollapsiblePrimitive.Panel\n\t\t\tdata-slot=\"collapsible-content\"\n\t\t\t{...props}\n\t\t/>\n\t)\n}\n\nexport { Collapsible, CollapsibleContent, CollapsibleTrigger }\n","import logoFont from \"@fontsource/fugaz-one/files/fugaz-one-latin-400-normal.woff2?url\"\nimport chromeStyles from \"@usecontextlayer/sdk/styles.css?inline\"\nimport { type ReactNode, useCallback, useEffect, useState } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport {\n\tLinks,\n\ttype LoaderFunctionArgs,\n\tMeta,\n\tScripts,\n\tScrollRestoration,\n\tuseRouteLoaderData,\n} from \"react-router\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport { Button } from \"@/components/ui/button\"\nimport {\n\tCollapsible,\n\tCollapsibleContent,\n\tCollapsibleTrigger,\n} from \"@/components/ui/collapsible\"\nimport { viewerContext } from \"@/index\"\nimport type { User } from \"@/viewer\"\n\nexport async function loader({ context }: LoaderFunctionArgs) {\n\treturn { user: await context.get(viewerContext).getCurrentUser() }\n}\n\nfunction Chrome({ user }: { user: User | null }) {\n\tconst [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n\tconst attach = useCallback((host: HTMLElement | null) => {\n\t\tif (host) setShadowRoot(host.shadowRoot ?? host.attachShadow({ mode: \"open\" }))\n\t}, [])\n\n\tuseEffect(() => {\n\t\tconst font = new FontFace(\"ContextLayer Logo\", `url(\"${logoFont}\")`, {\n\t\t\tdisplay: \"swap\",\n\t\t\tweight: \"400\",\n\t\t})\n\t\tdocument.fonts.add(font)\n\t\tvoid font.load()\n\t\treturn () => {\n\t\t\tdocument.fonts.delete(font)\n\t\t}\n\t}, [])\n\n\treturn (\n\t\t<header ref={attach}>\n\t\t\t{shadowRoot &&\n\t\t\t\tcreatePortal(\n\t\t\t\t\t<>\n\t\t\t\t\t\t<style>{chromeStyles}</style>\n\t\t\t\t\t\t<Collapsible className=\"group/chrome\">\n\t\t\t\t\t\t\t<CollapsibleTrigger\n\t\t\t\t\t\t\t\taria-label={\n\t\t\t\t\t\t\t\t\tuser\n\t\t\t\t\t\t\t\t\t\t? `Toggle ContextLayer settings for ${user.name}`\n\t\t\t\t\t\t\t\t\t\t: \"Toggle ContextLayer settings\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\trender={\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"h-auto w-full justify-between gap-0 rounded-none border-x-0 border-t-0 border-b-slate-200 bg-slate-100 p-0 text-slate-600 hover:bg-slate-200 hover:text-slate-600 aria-expanded:bg-slate-100 aria-expanded:hover:bg-slate-200\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<span className=\"shrink-0 px-4 py-[6.5px] font-logo text-[13px]/4 font-normal text-slate-500\">\n\t\t\t\t\t\t\t\t\tcontextlayer\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span className=\"flex min-w-0 self-stretch\">\n\t\t\t\t\t\t\t\t\t<span className=\"flex shrink-0 items-center px-3 text-[13px]/4 font-normal text-slate-400\">\n\t\t\t\t\t\t\t\t\t\t<span className=\"group-data-open/chrome:hidden\">click to open</span>\n\t\t\t\t\t\t\t\t\t\t<span className=\"hidden group-data-open/chrome:inline\">\n\t\t\t\t\t\t\t\t\t\t\tclick to close\n\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t<span className=\"flex min-w-0 items-center gap-2 border-l border-slate-200 py-[3px] pr-3 pl-[3px] text-[13px]/4 font-normal\">\n\t\t\t\t\t\t\t\t\t\t{user ? (\n\t\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t\t<Avatar className=\"size-[23px] rounded-[3px] after:rounded-[3px]\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t<AvatarImage\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"rounded-[3px]\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsrc={user.image ?? undefined}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<AvatarFallback className=\"rounded-[3px] text-[13px]\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{user.name.slice(0, 1)}\n\t\t\t\t\t\t\t\t\t\t\t\t\t</AvatarFallback>\n\t\t\t\t\t\t\t\t\t\t\t\t</Avatar>\n\t\t\t\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\t\t\t\tclassName=\"max-w-40 truncate\"\n\t\t\t\t\t\t\t\t\t\t\t\t\ttitle={user.name}\n\t\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t{user.name}\n\t\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"truncate pl-[9px]\">Not signed in</span>\n\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</CollapsibleTrigger>\n\t\t\t\t\t\t\t<CollapsibleContent className=\"h-(--collapsible-panel-height) overflow-hidden bg-slate-100 transition-[height] duration-200 ease-out data-ending-style:h-0 data-starting-style:h-0 motion-reduce:transition-none\">\n\t\t\t\t\t\t\t\t<div className=\"min-h-40 border-b border-slate-200\" />\n\t\t\t\t\t\t\t</CollapsibleContent>\n\t\t\t\t\t\t</Collapsible>\n\t\t\t\t\t</>,\n\t\t\t\t\tshadowRoot,\n\t\t\t\t)}\n\t\t</header>\n\t)\n}\n\nexport function Layout({ children }: { children: ReactNode }) {\n\tconst data = useRouteLoaderData<typeof loader>(\"root\")\n\treturn (\n\t\t<html lang=\"en\">\n\t\t\t<head>\n\t\t\t\t<meta charSet=\"utf-8\" />\n\t\t\t\t<meta\n\t\t\t\t\tname=\"viewport\"\n\t\t\t\t\tcontent=\"width=device-width, initial-scale=1\"\n\t\t\t\t/>\n\t\t\t\t<Meta />\n\t\t\t\t<Links />\n\t\t\t</head>\n\t\t\t<body>\n\t\t\t\t<Chrome user={data?.user ?? null} />\n\t\t\t\t{children}\n\t\t\t\t<ScrollRestoration />\n\t\t\t\t<Scripts />\n\t\t\t</body>\n\t\t</html>\n\t)\n}\n"],"mappings":";;;;;;;;;;;;;AAIA,SAASA,SAAO,EACf,WACA,OAAO,WACP,GAAG,SAGD;CACF,OACC,oBAACC,OAAgB,MAAjB;EACC,aAAU;EACV,aAAW;EACX,WAAW,GACV,yPACA,SACD;EACA,GAAI;CACJ,CAAA;AAEH;AAEA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAsC;CAC1E,OACC,oBAACA,OAAgB,OAAjB;EACC,aAAU;EACV,WAAW,GAAG,qDAAqD,SAAS;EAC5E,GAAI;CACJ,CAAA;AAEH;AAEA,SAAS,eAAe,EAAE,WAAW,GAAG,SAAyC;CAChF,OACC,oBAACA,OAAgB,UAAjB;EACC,aAAU;EACV,WAAW,GACV,sIACA,SACD;EACA,GAAI;CACJ,CAAA;AAEH;;;ACzCA,MAAM,iBAAiB,IACtB,8lBACA;CACC,iBAAiB;EAChB,MAAM;EACN,SAAS;CACV;CACA,UAAU;EACT,MAAM;GACL,SACC;GACD,MAAM;GACN,WAAW;GACX,WACC;GACD,WACC;GACD,IAAI;GACJ,IAAI;GACJ,IAAI;EACL;EACA,SAAS;GACR,SAAS;GACT,aACC;GACD,OACC;GACD,MAAM;GACN,SACC;GACD,WACC;EACF;CACD;AACD,CACD;AAEA,SAASC,SAAO,EACf,WACA,UAAU,WACV,OAAO,WACP,GAAG,SAC4D;CAC/D,OACC,oBAACC,QAAD;EACC,aAAU;EACV,WAAW,GAAG,eAAe;GAAE;GAAW;GAAM;EAAQ,CAAC,CAAC;EAC1D,GAAI;CACJ,CAAA;AAEH;;;ACpDA,SAASC,cAAY,EAAE,GAAG,SAA0C;CACnE,OACC,oBAACC,YAAqB,MAAtB;EACC,aAAU;EACV,GAAI;CACJ,CAAA;AAEH;AAEA,SAAS,mBAAmB,EAAE,GAAG,SAA6C;CAC7E,OACC,oBAACA,YAAqB,SAAtB;EACC,aAAU;EACV,GAAI;CACJ,CAAA;AAEH;AAEA,SAAS,mBAAmB,EAAE,GAAG,SAA2C;CAC3E,OACC,oBAACA,YAAqB,OAAtB;EACC,aAAU;EACV,GAAI;CACJ,CAAA;AAEH;;;ACLA,eAAsB,OAAO,EAAE,WAA+B;CAC7D,OAAO,EAAE,MAAM,MAAM,QAAQ,IAAI,aAAa,CAAC,CAAC,eAAe,EAAE;AAClE;AAEA,SAAS,OAAO,EAAE,QAA+B;CAChD,MAAM,CAAC,YAAY,iBAAiB,SAA4B,IAAI;CACpE,MAAM,SAAS,aAAa,SAA6B;EACxD,IAAI,MAAM,cAAc,KAAK,cAAc,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC,CAAC;CAC/E,GAAG,CAAC,CAAC;CAEL,gBAAgB;EACf,MAAM,OAAO,IAAI,SAAS,qBAAqB,QAAQ,SAAS,KAAK;GACpE,SAAS;GACT,QAAQ;EACT,CAAC;EACD,SAAS,MAAM,IAAI,IAAI;EACvB,KAAU,KAAK;EACf,aAAa;GACZ,SAAS,MAAM,OAAO,IAAI;EAC3B;CACD,GAAG,CAAC,CAAC;CAEL,OACC,oBAAC,UAAD;EAAQ,KAAK;EACX,UAAA,cACA,aACC,qBAAA,UAAA,EAAA,UAAA,CACC,oBAAC,SAAD,EAAA,UAAQ,aAAoB,CAAA,GAC5B,qBAACC,eAAD;GAAa,WAAU;GAAvB,UAAA,CACC,qBAAC,oBAAD;IACC,cACC,OACG,oCAAoC,KAAK,SACzC;IAEJ,QACC,oBAACC,UAAD;KACC,SAAQ;KACR,WAAU;IACV,CAAA;IAVH,UAAA,CAaC,oBAAC,QAAD;KAAM,WAAU;KAA8E,UAAA;IAExF,CAAA,GACN,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACC,qBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACC,oBAAC,QAAD;OAAM,WAAU;OAAgC,UAAA;MAAmB,CAAA,GACnE,oBAAC,QAAD;OAAM,WAAU;OAAuC,UAAA;MAEjD,CAAA,CACD;KACN,CAAA,GAAA,oBAAC,QAAD;MAAM,WAAU;MACd,UAAA,OACA,qBAAA,UAAA,EAAA,UAAA,CACC,qBAACC,UAAD;OAAQ,WAAU;OAAlB,UAAA,CACC,oBAAC,aAAD;QACC,WAAU;QACV,KAAK,KAAK,SAAS,KAAA;QACnB,KAAI;OACJ,CAAA,GACD,oBAAC,gBAAD;QAAgB,WAAU;QACxB,UAAA,KAAK,KAAK,MAAM,GAAG,CAAC;OACN,CAAA,CACT;MACR,CAAA,GAAA,oBAAC,QAAD;OACC,WAAU;OACV,OAAO,KAAK;OAEX,UAAA,KAAK;MACD,CAAA,CACL,EAAA,CAAA,IAEF,oBAAC,QAAD;OAAM,WAAU;OAAoB,UAAA;MAAmB,CAAA;KAEnD,CAAA,CACD;IACa,CAAA,CAAA;GACpB,CAAA,GAAA,oBAAC,oBAAD;IAAoB,WAAU;IAC7B,UAAA,oBAAC,OAAD,EAAK,WAAU,qCAAsC,CAAA;GAClC,CAAA,CACR;EACZ,CAAA,CAAA,EAAA,CAAA,GACF,UACD;CACM,CAAA;AAEV;AAEA,SAAgB,OAAO,EAAE,YAAqC;CAC7D,MAAM,OAAO,mBAAkC,MAAM;CACrD,OACC,qBAAC,QAAD;EAAM,MAAK;EAAX,UAAA,CACC,qBAAC,QAAD,EAAA,UAAA;GACC,oBAAC,QAAD,EAAM,SAAQ,QAAS,CAAA;GACvB,oBAAC,QAAD;IACC,MAAK;IACL,SAAQ;GACR,CAAA;GACD,oBAAC,MAAD,CAAO,CAAA;GACP,oBAAC,OAAD,CAAQ,CAAA;EACH,EAAA,CAAA,GACN,qBAAC,QAAD,EAAA,UAAA;GACC,oBAAC,QAAD,EAAQ,MAAM,MAAM,QAAQ,KAAO,CAAA;GAClC;GACD,oBAAC,mBAAD,CAAoB,CAAA;GACpB,oBAAC,SAAD,CAAU,CAAA;EACL,EAAA,CAAA,CACD;;AAER"}
package/dist/vite.js CHANGED
@@ -12,6 +12,10 @@ async function contextlayer({ command }) {
12
12
  binding: "TOOLS",
13
13
  entrypoint: "Tools",
14
14
  service: "ctx-local-tools"
15
+ }, {
16
+ binding: "VIEWER",
17
+ entrypoint: "Viewer",
18
+ service: "ctx-local-tools"
15
19
  }] } : {},
16
20
  viteEnvironment: { name: "ssr" }
17
21
  });
package/dist/vite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","names":[],"sources":["../vite.ts"],"sourcesContent":["import { cloudflare } from \"@cloudflare/vite-plugin\"\nimport { getLocalToolsBindings } from \"@usecontextlayer/cli/vite\"\nimport type { ConfigEnv } from \"vite\"\n\nexport async function contextlayer({ command }: ConfigEnv) {\n\treturn cloudflare({\n\t\tauxiliaryWorkers: [\n\t\t\t{\n\t\t\t\tconfig: command === \"serve\" ? { vars: await getLocalToolsBindings() } : {},\n\t\t\t\tconfigPath: \"workers/local-tools/wrangler.jsonc\",\n\t\t\t\tdevOnly: true,\n\t\t\t},\n\t\t],\n\t\tconfig:\n\t\t\tcommand === \"serve\"\n\t\t\t\t? {\n\t\t\t\t\t\tservices: [\n\t\t\t\t\t\t\t{ binding: \"TOOLS\", entrypoint: \"Tools\", service: \"ctx-local-tools\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: {},\n\t\tviteEnvironment: { name: \"ssr\" },\n\t})\n}\n"],"mappings":";;;AAIA,eAAsB,aAAa,EAAE,WAAsB;CAC1D,OAAO,WAAW;EACjB,kBAAkB,CACjB;GACC,QAAQ,YAAY,UAAU,EAAE,MAAM,MAAM,sBAAsB,EAAE,IAAI,CAAC;GACzE,YAAY;GACZ,SAAS;EACV,CACD;EACA,QACC,YAAY,UACT,EACA,UAAU,CACT;GAAE,SAAS;GAAS,YAAY;GAAS,SAAS;EAAkB,CACrE,EACD,IACC,CAAC;EACL,iBAAiB,EAAE,MAAM,MAAM;CAChC,CAAC;AACF"}
1
+ {"version":3,"file":"vite.js","names":[],"sources":["../vite.ts"],"sourcesContent":["import { cloudflare } from \"@cloudflare/vite-plugin\"\nimport { getLocalToolsBindings } from \"@usecontextlayer/cli/vite\"\nimport type { ConfigEnv } from \"vite\"\n\nexport async function contextlayer({ command }: ConfigEnv) {\n\treturn cloudflare({\n\t\tauxiliaryWorkers: [\n\t\t\t{\n\t\t\t\tconfig: command === \"serve\" ? { vars: await getLocalToolsBindings() } : {},\n\t\t\t\tconfigPath: \"workers/local-tools/wrangler.jsonc\",\n\t\t\t\tdevOnly: true,\n\t\t\t},\n\t\t],\n\t\tconfig:\n\t\t\tcommand === \"serve\"\n\t\t\t\t? {\n\t\t\t\t\t\tservices: [\n\t\t\t\t\t\t\t{ binding: \"TOOLS\", entrypoint: \"Tools\", service: \"ctx-local-tools\" },\n\t\t\t\t\t\t\t{ binding: \"VIEWER\", entrypoint: \"Viewer\", service: \"ctx-local-tools\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: {},\n\t\tviteEnvironment: { name: \"ssr\" },\n\t})\n}\n"],"mappings":";;;AAIA,eAAsB,aAAa,EAAE,WAAsB;CAC1D,OAAO,WAAW;EACjB,kBAAkB,CACjB;GACC,QAAQ,YAAY,UAAU,EAAE,MAAM,MAAM,sBAAsB,EAAE,IAAI,CAAC;GACzE,YAAY;GACZ,SAAS;EACV,CACD;EACA,QACC,YAAY,UACT,EACA,UAAU,CACT;GAAE,SAAS;GAAS,YAAY;GAAS,SAAS;EAAkB,GACpE;GAAE,SAAS;GAAU,YAAY;GAAU,SAAS;EAAkB,CACvE,EACD,IACC,CAAC;EACL,iBAAiB,EAAE,MAAM,MAAM;CAChC,CAAC;AACF"}
package/dist/worker.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Tools } from "./index.js";
1
+ import { a as Viewer, t as Tools } from "./index-DbuYj6qS.js";
2
2
  import { createRequestHandler } from "react-router";
3
3
  //#region worker.d.ts
4
4
  export declare function createApp({ build, mode, development }: {
@@ -8,8 +8,10 @@ export declare function createApp({ build, mode, development }: {
8
8
  }): {
9
9
  fetch(request: Request, env: {
10
10
  TOOLS: Tools;
11
+ VIEWER: Viewer;
11
12
  }, ctx: ExecutionContext<{
12
13
  tools: Tools;
14
+ viewer?: Viewer;
13
15
  }>): Promise<Response>;
14
16
  };
15
17
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","names":[],"sources":["../worker.ts"],"mappings":";;;wBAGgB,YACf,OACA,MACA;EAEA,OAAO,kBAAkB;EACzB;EACA;;EAIO,MAAK,SACD,SAAO;IACT,OAAO;KAAO,KAChB;IAAmB,OAAO;OAAQ,QAAA"}
1
+ {"version":3,"file":"worker.d.ts","names":[],"sources":["../worker.ts"],"mappings":";;;wBAGgB,YACf,OACA,MACA;EAEA,OAAO,kBAAkB;EACzB;EACA;;EAIO,MAAK,SACD,SAAO;IACT,OAAO;IAAO,QAAQ;KAAQ,KAChC;IAAmB,OAAO;IAAO,SAAS;OAAS,QAAA"}
package/dist/worker.js CHANGED
@@ -1,4 +1,4 @@
1
- import { toolsContext } from "./index.js";
1
+ import { toolsContext, viewerContext } from "./index.js";
2
2
  import { RouterContextProvider, createRequestHandler } from "react-router";
3
3
  //#region worker.ts
4
4
  function createApp({ build, mode, development }) {
@@ -6,6 +6,8 @@ function createApp({ build, mode, development }) {
6
6
  return { async fetch(request, env, ctx) {
7
7
  const context = new RouterContextProvider();
8
8
  context.set(toolsContext, development ? env.TOOLS : ctx.props.tools);
9
+ const viewer = development ? env.VIEWER : ctx.props.viewer;
10
+ if (viewer) context.set(viewerContext, viewer);
9
11
  return requestHandler(request, context);
10
12
  } };
11
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","names":[],"sources":["../worker.ts"],"sourcesContent":["import { createRequestHandler, RouterContextProvider } from \"react-router\"\nimport { type Tools, toolsContext } from \"@/index\"\n\nexport function createApp({\n\tbuild,\n\tmode,\n\tdevelopment,\n}: {\n\tbuild: Parameters<typeof createRequestHandler>[0]\n\tmode: string\n\tdevelopment: boolean\n}) {\n\tconst requestHandler = createRequestHandler(build, mode)\n\treturn {\n\t\tasync fetch(\n\t\t\trequest: Request,\n\t\t\tenv: { TOOLS: Tools },\n\t\t\tctx: ExecutionContext<{ tools: Tools }>,\n\t\t) {\n\t\t\tconst context = new RouterContextProvider()\n\t\t\tcontext.set(toolsContext, development ? env.TOOLS : ctx.props.tools)\n\t\t\treturn requestHandler(request, context)\n\t\t},\n\t}\n}\n"],"mappings":";;;AAGA,SAAgB,UAAU,EACzB,OACA,MACA,eAKE;CACF,MAAM,iBAAiB,qBAAqB,OAAO,IAAI;CACvD,OAAO,EACN,MAAM,MACL,SACA,KACA,KACC;EACD,MAAM,UAAU,IAAI,sBAAsB;EAC1C,QAAQ,IAAI,cAAc,cAAc,IAAI,QAAQ,IAAI,MAAM,KAAK;EACnE,OAAO,eAAe,SAAS,OAAO;CACvC,EACD;AACD"}
1
+ {"version":3,"file":"worker.js","names":[],"sources":["../worker.ts"],"sourcesContent":["import { createRequestHandler, RouterContextProvider } from \"react-router\"\nimport { type Tools, toolsContext, type Viewer, viewerContext } from \"@/index\"\n\nexport function createApp({\n\tbuild,\n\tmode,\n\tdevelopment,\n}: {\n\tbuild: Parameters<typeof createRequestHandler>[0]\n\tmode: string\n\tdevelopment: boolean\n}) {\n\tconst requestHandler = createRequestHandler(build, mode)\n\treturn {\n\t\tasync fetch(\n\t\t\trequest: Request,\n\t\t\tenv: { TOOLS: Tools; VIEWER: Viewer },\n\t\t\tctx: ExecutionContext<{ tools: Tools; viewer?: Viewer }>,\n\t\t) {\n\t\t\tconst context = new RouterContextProvider()\n\t\t\tcontext.set(toolsContext, development ? env.TOOLS : ctx.props.tools)\n\t\t\tconst viewer = development ? env.VIEWER : ctx.props.viewer\n\t\t\tif (viewer) context.set(viewerContext, viewer)\n\t\t\treturn requestHandler(request, context)\n\t\t},\n\t}\n}\n"],"mappings":";;;AAGA,SAAgB,UAAU,EACzB,OACA,MACA,eAKE;CACF,MAAM,iBAAiB,qBAAqB,OAAO,IAAI;CACvD,OAAO,EACN,MAAM,MACL,SACA,KACA,KACC;EACD,MAAM,UAAU,IAAI,sBAAsB;EAC1C,QAAQ,IAAI,cAAc,cAAc,IAAI,QAAQ,IAAI,MAAM,KAAK;EACnE,MAAM,SAAS,cAAc,IAAI,SAAS,IAAI,MAAM;EACpD,IAAI,QAAQ,QAAQ,IAAI,eAAe,MAAM;EAC7C,OAAO,eAAe,SAAS,OAAO;CACvC,EACD;AACD"}
package/package.json CHANGED
@@ -1,13 +1,23 @@
1
1
  {
2
2
  "dependencies": {
3
+ "@base-ui/react": "^1.8.0",
4
+ "@fontsource/fugaz-one": "^5.3.0",
5
+ "class-variance-authority": "^0.7.1",
6
+ "cn": "^0.4.0",
7
+ "shadcn": "^4.21.1",
8
+ "tailwindcss": "^4.3.3",
9
+ "tw-animate-css": "^1.4.0",
3
10
  "zod": "^4.4.3",
4
- "@usecontextlayer/cli": "0.12.1"
11
+ "@usecontextlayer/cli": "0.13.0"
5
12
  },
6
13
  "devDependencies": {
7
14
  "@cloudflare/vite-plugin": "^1.62.4",
8
15
  "@cloudflare/workers-types": "^5.20261001.1",
9
16
  "@types/node": "^24.13.3",
10
17
  "@types/react": "^19.0.0",
18
+ "@types/react-dom": "^19.0.0",
19
+ "react": "^19.3.0",
20
+ "react-dom": "^19.3.0",
11
21
  "react-router": "^8.4.0",
12
22
  "tsdown": "latest",
13
23
  "typescript": "latest",
@@ -22,6 +32,11 @@
22
32
  "import": "./dist/local.js",
23
33
  "types": "./dist/local.d.ts"
24
34
  },
35
+ "./react": {
36
+ "import": "./dist/react.js",
37
+ "types": "./dist/react.d.ts"
38
+ },
39
+ "./styles.css": "./styles.css",
25
40
  "./vite": {
26
41
  "import": "./dist/vite.js",
27
42
  "types": "./dist/vite.d.ts"
@@ -33,16 +48,19 @@
33
48
  },
34
49
  "files": [
35
50
  "dist",
36
- "examples"
51
+ "examples",
52
+ "styles.css"
37
53
  ],
38
54
  "name": "@usecontextlayer/sdk",
39
55
  "peerDependencies": {
40
56
  "@cloudflare/vite-plugin": "^1.62.4",
57
+ "react": "^19.0.0",
58
+ "react-dom": "^19.0.0",
41
59
  "react-router": "^8.4.0",
42
60
  "vite": "^8.3.2"
43
61
  },
44
62
  "type": "module",
45
- "version": "0.12.1",
63
+ "version": "0.13.0",
46
64
  "scripts": {
47
65
  "build": "tsdown",
48
66
  "dev:watch": "tsdown --watch",
package/styles.css ADDED
@@ -0,0 +1,136 @@
1
+ @import "tailwindcss" source(none);
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+ @source "./dist";
5
+
6
+ @custom-variant dark (&:is(.dark *));
7
+
8
+ @theme inline {
9
+ --font-heading: var(--font-sans);
10
+ --font-sans: ui-sans-serif, system-ui, sans-serif;
11
+ --font-logo: "ContextLayer Logo", sans-serif;
12
+ --color-sidebar-ring: var(--sidebar-ring);
13
+ --color-sidebar-border: var(--sidebar-border);
14
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
15
+ --color-sidebar-accent: var(--sidebar-accent);
16
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
17
+ --color-sidebar-primary: var(--sidebar-primary);
18
+ --color-sidebar-foreground: var(--sidebar-foreground);
19
+ --color-sidebar: var(--sidebar);
20
+ --color-chart-5: var(--chart-5);
21
+ --color-chart-4: var(--chart-4);
22
+ --color-chart-3: var(--chart-3);
23
+ --color-chart-2: var(--chart-2);
24
+ --color-chart-1: var(--chart-1);
25
+ --color-ring: var(--ring);
26
+ --color-input: var(--input);
27
+ --color-border: var(--border);
28
+ --color-destructive: var(--destructive);
29
+ --color-accent-foreground: var(--accent-foreground);
30
+ --color-accent: var(--accent);
31
+ --color-muted-foreground: var(--muted-foreground);
32
+ --color-muted: var(--muted);
33
+ --color-secondary-foreground: var(--secondary-foreground);
34
+ --color-secondary: var(--secondary);
35
+ --color-primary-foreground: var(--primary-foreground);
36
+ --color-primary: var(--primary);
37
+ --color-popover-foreground: var(--popover-foreground);
38
+ --color-popover: var(--popover);
39
+ --color-card-foreground: var(--card-foreground);
40
+ --color-card: var(--card);
41
+ --color-foreground: var(--foreground);
42
+ --color-background: var(--background);
43
+ --radius-sm: calc(var(--radius) * 0.6);
44
+ --radius-md: calc(var(--radius) * 0.8);
45
+ --radius-lg: var(--radius);
46
+ --radius-xl: calc(var(--radius) * 1.4);
47
+ --radius-2xl: calc(var(--radius) * 1.8);
48
+ --radius-3xl: calc(var(--radius) * 2.2);
49
+ --radius-4xl: calc(var(--radius) * 2.6);
50
+ }
51
+
52
+ :host {
53
+ --background: oklch(1 0 0);
54
+ --foreground: oklch(0.145 0 0);
55
+ --card: oklch(1 0 0);
56
+ --card-foreground: oklch(0.145 0 0);
57
+ --popover: oklch(1 0 0);
58
+ --popover-foreground: oklch(0.145 0 0);
59
+ --primary: oklch(0.205 0 0);
60
+ --primary-foreground: oklch(0.985 0 0);
61
+ --secondary: oklch(0.97 0 0);
62
+ --secondary-foreground: oklch(0.205 0 0);
63
+ --muted: oklch(0.97 0 0);
64
+ --muted-foreground: oklch(0.556 0 0);
65
+ --accent: oklch(0.97 0 0);
66
+ --accent-foreground: oklch(0.205 0 0);
67
+ --destructive: oklch(0.577 0.245 27.325);
68
+ --border: oklch(0.922 0 0);
69
+ --input: oklch(0.922 0 0);
70
+ --ring: oklch(0.708 0 0);
71
+ --chart-1: oklch(0.87 0 0);
72
+ --chart-2: oklch(0.556 0 0);
73
+ --chart-3: oklch(0.439 0 0);
74
+ --chart-4: oklch(0.371 0 0);
75
+ --chart-5: oklch(0.269 0 0);
76
+ --radius: 0.625rem;
77
+ --sidebar: oklch(0.985 0 0);
78
+ --sidebar-foreground: oklch(0.145 0 0);
79
+ --sidebar-primary: oklch(0.205 0 0);
80
+ --sidebar-primary-foreground: oklch(0.985 0 0);
81
+ --sidebar-accent: oklch(0.97 0 0);
82
+ --sidebar-accent-foreground: oklch(0.205 0 0);
83
+ --sidebar-border: oklch(0.922 0 0);
84
+ --sidebar-ring: oklch(0.708 0 0);
85
+ }
86
+
87
+ :host(.dark) {
88
+ --background: oklch(0.145 0 0);
89
+ --foreground: oklch(0.985 0 0);
90
+ --card: oklch(0.205 0 0);
91
+ --card-foreground: oklch(0.985 0 0);
92
+ --popover: oklch(0.205 0 0);
93
+ --popover-foreground: oklch(0.985 0 0);
94
+ --primary: oklch(0.922 0 0);
95
+ --primary-foreground: oklch(0.205 0 0);
96
+ --secondary: oklch(0.269 0 0);
97
+ --secondary-foreground: oklch(0.985 0 0);
98
+ --muted: oklch(0.269 0 0);
99
+ --muted-foreground: oklch(0.708 0 0);
100
+ --accent: oklch(0.269 0 0);
101
+ --accent-foreground: oklch(0.985 0 0);
102
+ --destructive: oklch(0.704 0.191 22.216);
103
+ --border: oklch(1 0 0 / 10%);
104
+ --input: oklch(1 0 0 / 15%);
105
+ --ring: oklch(0.556 0 0);
106
+ --chart-1: oklch(0.87 0 0);
107
+ --chart-2: oklch(0.556 0 0);
108
+ --chart-3: oklch(0.439 0 0);
109
+ --chart-4: oklch(0.371 0 0);
110
+ --chart-5: oklch(0.269 0 0);
111
+ --sidebar: oklch(0.205 0 0);
112
+ --sidebar-foreground: oklch(0.985 0 0);
113
+ --sidebar-primary: oklch(0.488 0.243 264.376);
114
+ --sidebar-primary-foreground: oklch(0.985 0 0);
115
+ --sidebar-accent: oklch(0.269 0 0);
116
+ --sidebar-accent-foreground: oklch(0.985 0 0);
117
+ --sidebar-border: oklch(1 0 0 / 10%);
118
+ --sidebar-ring: oklch(0.556 0 0);
119
+ }
120
+
121
+ @layer base {
122
+ :host {
123
+ all: initial;
124
+ display: block;
125
+ background: var(--background);
126
+ color: var(--foreground);
127
+ font:
128
+ 14px / 1.5 ui-sans-serif,
129
+ system-ui,
130
+ sans-serif;
131
+ color-scheme: light;
132
+ }
133
+ * {
134
+ @apply border-border outline-ring/50;
135
+ }
136
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../index.ts"],"mappings":";iBAEiB;EAChB,KACC,cACA,kBACA,MAAM,0BACJ;IAAU;IAAe;;;qBAGhB,qCAAY,cAAA"}