@timbal-ai/timbal-react 0.6.0 → 0.7.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +24 -5
  3. package/dist/app.cjs +2282 -738
  4. package/dist/app.d.cts +4 -1
  5. package/dist/app.d.ts +4 -1
  6. package/dist/app.esm.js +58 -5
  7. package/dist/button-CIKzUrJI.d.cts +18 -0
  8. package/dist/button-CIKzUrJI.d.ts +18 -0
  9. package/dist/chart-artifact-BFDz8Tf9.d.ts +756 -0
  10. package/dist/chart-artifact-bWUa-iSG.d.cts +756 -0
  11. package/dist/chat.cjs +872 -562
  12. package/dist/chat.d.cts +2 -2
  13. package/dist/chat.d.ts +2 -2
  14. package/dist/chat.esm.js +3 -3
  15. package/dist/{chunk-4TCJQSIX.esm.js → chunk-2XZ3S4OP.esm.js} +14 -3
  16. package/dist/chunk-533MK5EA.esm.js +2294 -0
  17. package/dist/{chunk-OVHR7J3J.esm.js → chunk-7O5VY3TP.esm.js} +38 -11
  18. package/dist/{chunk-WLTW56MC.esm.js → chunk-N3PYVTY5.esm.js} +2 -2
  19. package/dist/{chunk-IYENDIRY.esm.js → chunk-TDIJHV4I.esm.js} +1 -1
  20. package/dist/{chunk-YJQLLFKP.esm.js → chunk-TLUF2RUL.esm.js} +813 -507
  21. package/dist/{chunk-OFHLFNJH.esm.js → chunk-Z27GBSOT.esm.js} +3 -1
  22. package/dist/index.cjs +2587 -1016
  23. package/dist/index.d.cts +6 -5
  24. package/dist/index.d.ts +6 -5
  25. package/dist/index.esm.js +57 -7
  26. package/dist/{layout-CQWngNQ7.d.ts → layout-BTJyU8wd.d.ts} +1 -1
  27. package/dist/{layout-B9VayJhZ.d.cts → layout-C2G-FcER.d.cts} +1 -1
  28. package/dist/studio.cjs +1127 -788
  29. package/dist/studio.d.cts +1 -1
  30. package/dist/studio.d.ts +1 -1
  31. package/dist/studio.esm.js +6 -6
  32. package/dist/{timbal-v2-button-F4-z7m33.d.ts → timbal-v2-button-CNfdwGq4.d.cts} +1 -1
  33. package/dist/{timbal-v2-button-F4-z7m33.d.cts → timbal-v2-button-CNfdwGq4.d.ts} +1 -1
  34. package/dist/ui.cjs +12 -3
  35. package/dist/ui.d.cts +5 -16
  36. package/dist/ui.d.ts +5 -16
  37. package/dist/ui.esm.js +2 -2
  38. package/dist/{welcome-BOizSp5h.d.ts → welcome-BBmB3tl7.d.ts} +4 -3
  39. package/dist/{welcome--80i_O0p.d.cts → welcome-C89Mgdaw.d.cts} +4 -3
  40. package/package.json +2 -1
  41. package/vite/local-dev.mjs +91 -5
  42. package/dist/chart-artifact-C71dk4xI.d.ts +0 -329
  43. package/dist/chart-artifact-CPEpOmtV.d.cts +0 -329
  44. package/dist/chunk-M4V6Q6XO.esm.js +0 -1082
package/dist/studio.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { M as ModeToggle, a as ModeToggleProps, b as ModeToggleTheme, S as STUDIO_NAV_MODE, c as StudioModeSwitch, d as StudioModeSwitchProps, e as StudioNavMode, f as StudioSidebar, g as StudioSidebarProps, h as StudioWelcome, i as StudioWelcomeProps, T as TimbalChatShell, j as TimbalChatShellProps, k as TimbalMark, l as TimbalMarkProps, m as TimbalStudioShell, n as TimbalStudioShellProps } from './welcome--80i_O0p.cjs';
1
+ export { M as ModeToggle, a as ModeToggleProps, b as ModeToggleTheme, S as STUDIO_NAV_MODE, c as StudioModeSwitch, d as StudioModeSwitchProps, e as StudioNavMode, f as StudioSidebar, g as StudioSidebarProps, h as StudioWelcome, i as StudioWelcomeProps, T as TimbalChatShell, j as TimbalChatShellProps, k as TimbalMark, l as TimbalMarkProps, m as TimbalStudioShell, n as TimbalStudioShellProps } from './welcome-C89Mgdaw.cjs';
2
2
  import { FC } from 'react';
3
3
  import './chat-CWtQWDtJ.cjs';
4
4
  import 'react/jsx-runtime';
package/dist/studio.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { M as ModeToggle, a as ModeToggleProps, b as ModeToggleTheme, S as STUDIO_NAV_MODE, c as StudioModeSwitch, d as StudioModeSwitchProps, e as StudioNavMode, f as StudioSidebar, g as StudioSidebarProps, h as StudioWelcome, i as StudioWelcomeProps, T as TimbalChatShell, j as TimbalChatShellProps, k as TimbalMark, l as TimbalMarkProps, m as TimbalStudioShell, n as TimbalStudioShellProps } from './welcome-BOizSp5h.js';
1
+ export { M as ModeToggle, a as ModeToggleProps, b as ModeToggleTheme, S as STUDIO_NAV_MODE, c as StudioModeSwitch, d as StudioModeSwitchProps, e as StudioNavMode, f as StudioSidebar, g as StudioSidebarProps, h as StudioWelcome, i as StudioWelcomeProps, T as TimbalChatShell, j as TimbalChatShellProps, k as TimbalMark, l as TimbalMarkProps, m as TimbalStudioShell, n as TimbalStudioShellProps } from './welcome-BBmB3tl7.js';
2
2
  import { FC } from 'react';
3
3
  import './chat-CWtQWDtJ.js';
4
4
  import 'react/jsx-runtime';
@@ -8,12 +8,12 @@ import {
8
8
  TimbalChatShell,
9
9
  TimbalMark,
10
10
  TimbalStudioShell
11
- } from "./chunk-OVHR7J3J.esm.js";
12
- import "./chunk-OFHLFNJH.esm.js";
13
- import "./chunk-WLTW56MC.esm.js";
14
- import "./chunk-YJQLLFKP.esm.js";
15
- import "./chunk-IYENDIRY.esm.js";
16
- import "./chunk-4TCJQSIX.esm.js";
11
+ } from "./chunk-7O5VY3TP.esm.js";
12
+ import "./chunk-Z27GBSOT.esm.js";
13
+ import "./chunk-N3PYVTY5.esm.js";
14
+ import "./chunk-TLUF2RUL.esm.js";
15
+ import "./chunk-TDIJHV4I.esm.js";
16
+ import "./chunk-2XZ3S4OP.esm.js";
17
17
  export {
18
18
  ModeToggle,
19
19
  STUDIO_NAV_MODE,
@@ -22,7 +22,7 @@ interface TimbalV2ButtonProps extends React.ComponentProps<"button"> {
22
22
  isIconOnly?: boolean;
23
23
  isLoading?: boolean;
24
24
  fullWidth?: boolean;
25
- /** `pill` (default)full rounding; `rect` `rounded-md` for shadcn-style buttons. */
25
+ /** Kept for API compatibility all shapes render fully rounded (`rounded-full`). */
26
26
  shape?: "pill" | "rect";
27
27
  /**
28
28
  * When true, merges props onto the single child element (Radix Slot).
@@ -22,7 +22,7 @@ interface TimbalV2ButtonProps extends React.ComponentProps<"button"> {
22
22
  isIconOnly?: boolean;
23
23
  isLoading?: boolean;
24
24
  fullWidth?: boolean;
25
- /** `pill` (default)full rounding; `rect` `rounded-md` for shadcn-style buttons. */
25
+ /** Kept for API compatibility all shapes render fully rounded (`rounded-full`). */
26
26
  shape?: "pill" | "rect";
27
27
  /**
28
28
  * When true, merges props onto the single child element (Radix Slot).
package/dist/ui.cjs CHANGED
@@ -156,6 +156,10 @@ var TIMBAL_V2_SWITCH_THUMB = cn(
156
156
  TIMBAL_V2_ELEVATED_GRADIENT,
157
157
  "border border-border/80 shadow-sm"
158
158
  );
159
+ var TIMBAL_V2_ELEVATED_SURFACE = cn(
160
+ TIMBAL_V2_ELEVATED_GRADIENT,
161
+ "border border-border shadow-card"
162
+ );
159
163
  var TIMBAL_V2_SECONDARY_CHROME = [
160
164
  TIMBAL_V2_ELEVATED_GRADIENT,
161
165
  "border border-border shadow-card",
@@ -163,6 +167,11 @@ var TIMBAL_V2_SECONDARY_CHROME = [
163
167
  "hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to",
164
168
  "active:from-secondary-fill-active-from active:to-secondary-fill-active-to"
165
169
  ].join(" ");
170
+ var TIMBAL_V2_LOGO_TILE = cn(
171
+ "bg-gradient-to-b from-white to-neutral-100",
172
+ "border border-neutral-200",
173
+ "shadow-[0_1px_2px_-0.5px_rgba(0,0,0,0.08)]"
174
+ );
166
175
 
167
176
  // src/ui/timbal-v2-button.tsx
168
177
  var React = __toESM(require("react"), 1);
@@ -207,7 +216,7 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
207
216
  isIconOnly = false,
208
217
  isLoading = false,
209
218
  fullWidth = false,
210
- shape = "pill",
219
+ shape: _shape = "pill",
211
220
  asChild = false,
212
221
  className,
213
222
  disabled,
@@ -217,7 +226,7 @@ var TimbalV2Button = React.forwardRef(function TimbalV2Button2({
217
226
  }, ref) {
218
227
  const isDisabled = disabled || isLoading;
219
228
  const sizeClass = isIconOnly ? TIMBAL_V2_SIZE_ICON[size] : TIMBAL_V2_SIZE_HEIGHT[size];
220
- const radiusClass = variant === "link" || variant === "ghost" ? "rounded-md" : shape === "rect" ? "rounded-md" : "rounded-full";
229
+ const radiusClass = "rounded-full";
221
230
  const sharedRootClass = cn(
222
231
  "relative box-border inline-flex items-center justify-center gap-2 whitespace-nowrap border-0 text-sm font-normal shadow-none transition duration-200 ease-in-out",
223
232
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-1 focus-visible:ring-offset-background",
@@ -347,7 +356,7 @@ function Button({
347
356
  "data-size": size,
348
357
  variant: v2Variant,
349
358
  size: v2Size,
350
- shape: "rect",
359
+ shape: "pill",
351
360
  isIconOnly,
352
361
  asChild,
353
362
  className: cn(buttonVariants({ variant, size, className })),
package/dist/ui.d.cts CHANGED
@@ -1,22 +1,11 @@
1
+ export { B as Button } from './button-CIKzUrJI.cjs';
1
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as class_variance_authority_types from 'class-variance-authority/types';
3
3
  import * as React from 'react';
4
4
  import { ElementType, ReactNode, FC } from 'react';
5
- import { VariantProps } from 'class-variance-authority';
6
5
  import { Tooltip as Tooltip$1, Avatar as Avatar$1, Dialog as Dialog$1 } from 'radix-ui';
7
- export { a as TimbalV2Button } from './timbal-v2-button-F4-z7m33.cjs';
8
-
9
- /**
10
- * Layout-only variants for consumers that compose `buttonVariants` directly.
11
- * Fill / border / shadow come from `button-tokens` via `TimbalV2Button`.
12
- */
13
- declare const buttonVariants: (props?: ({
14
- variant?: "secondary" | "ghost" | "destructive" | "link" | "default" | "outline" | null | undefined;
15
- size?: "xs" | "sm" | "lg" | "default" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
16
- } & class_variance_authority_types.ClassProp) | undefined) => string;
17
- declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
18
- asChild?: boolean;
19
- }): react_jsx_runtime.JSX.Element;
6
+ export { a as TimbalV2Button } from './timbal-v2-button-CNfdwGq4.cjs';
7
+ import 'class-variance-authority/types';
8
+ import 'class-variance-authority';
20
9
 
21
10
  declare function TooltipProvider({ delayDuration, ...props }: React.ComponentProps<typeof Tooltip$1.Provider>): react_jsx_runtime.JSX.Element;
22
11
  declare function Tooltip({ ...props }: React.ComponentProps<typeof Tooltip$1.Root>): react_jsx_runtime.JSX.Element;
@@ -71,4 +60,4 @@ interface PillSegmentedTabsProps {
71
60
  declare const PillSegmentedTabs: FC<PillSegmentedTabsProps>;
72
61
  declare const MemoPillSegmentedTabs: React.NamedExoticComponent<PillSegmentedTabsProps>;
73
62
 
74
- export { Avatar, AvatarFallback, AvatarImage, Button, Dialog, DialogClose, DialogContent, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, MemoPillSegmentedTabs, type PillSegmentedTab, PillSegmentedTabs, type PillSegmentedTabsProps, Shimmer, type TextShimmerProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
63
+ export { Avatar, AvatarFallback, AvatarImage, Dialog, DialogClose, DialogContent, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, MemoPillSegmentedTabs, type PillSegmentedTab, PillSegmentedTabs, type PillSegmentedTabsProps, Shimmer, type TextShimmerProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
package/dist/ui.d.ts CHANGED
@@ -1,22 +1,11 @@
1
+ export { B as Button } from './button-CIKzUrJI.js';
1
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as class_variance_authority_types from 'class-variance-authority/types';
3
3
  import * as React from 'react';
4
4
  import { ElementType, ReactNode, FC } from 'react';
5
- import { VariantProps } from 'class-variance-authority';
6
5
  import { Tooltip as Tooltip$1, Avatar as Avatar$1, Dialog as Dialog$1 } from 'radix-ui';
7
- export { a as TimbalV2Button } from './timbal-v2-button-F4-z7m33.js';
8
-
9
- /**
10
- * Layout-only variants for consumers that compose `buttonVariants` directly.
11
- * Fill / border / shadow come from `button-tokens` via `TimbalV2Button`.
12
- */
13
- declare const buttonVariants: (props?: ({
14
- variant?: "secondary" | "ghost" | "destructive" | "link" | "default" | "outline" | null | undefined;
15
- size?: "xs" | "sm" | "lg" | "default" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
16
- } & class_variance_authority_types.ClassProp) | undefined) => string;
17
- declare function Button({ className, variant, size, asChild, ...props }: React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
18
- asChild?: boolean;
19
- }): react_jsx_runtime.JSX.Element;
6
+ export { a as TimbalV2Button } from './timbal-v2-button-CNfdwGq4.js';
7
+ import 'class-variance-authority/types';
8
+ import 'class-variance-authority';
20
9
 
21
10
  declare function TooltipProvider({ delayDuration, ...props }: React.ComponentProps<typeof Tooltip$1.Provider>): react_jsx_runtime.JSX.Element;
22
11
  declare function Tooltip({ ...props }: React.ComponentProps<typeof Tooltip$1.Root>): react_jsx_runtime.JSX.Element;
@@ -71,4 +60,4 @@ interface PillSegmentedTabsProps {
71
60
  declare const PillSegmentedTabs: FC<PillSegmentedTabsProps>;
72
61
  declare const MemoPillSegmentedTabs: React.NamedExoticComponent<PillSegmentedTabsProps>;
73
62
 
74
- export { Avatar, AvatarFallback, AvatarImage, Button, Dialog, DialogClose, DialogContent, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, MemoPillSegmentedTabs, type PillSegmentedTab, PillSegmentedTabs, type PillSegmentedTabsProps, Shimmer, type TextShimmerProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
63
+ export { Avatar, AvatarFallback, AvatarImage, Dialog, DialogClose, DialogContent, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, MemoPillSegmentedTabs, type PillSegmentedTab, PillSegmentedTabs, type PillSegmentedTabsProps, Shimmer, type TextShimmerProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
package/dist/ui.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MemoPillSegmentedTabs,
3
3
  PillSegmentedTabs
4
- } from "./chunk-IYENDIRY.esm.js";
4
+ } from "./chunk-TDIJHV4I.esm.js";
5
5
  import {
6
6
  Avatar,
7
7
  AvatarFallback,
@@ -20,7 +20,7 @@ import {
20
20
  TooltipContent,
21
21
  TooltipProvider,
22
22
  TooltipTrigger
23
- } from "./chunk-4TCJQSIX.esm.js";
23
+ } from "./chunk-2XZ3S4OP.esm.js";
24
24
  export {
25
25
  Avatar,
26
26
  AvatarFallback,
@@ -151,9 +151,10 @@ interface ModeToggleProps {
151
151
  *
152
152
  * 1. Pass `theme` + `setTheme` (e.g. from `next-themes`'s `useTheme`).
153
153
  * The component is then fully controlled.
154
- * 2. Omit both. The toggle reads the current state from `.dark` on
155
- * `<html>` and flips it on click. Good enough for prototypes and
156
- * cases where there is no theme manager.
154
+ * 2. Omit both. The toggle reads/writes `.dark` on `<html>` and persists
155
+ * the choice to `localStorage` under `STORAGE_KEYS.theme`. For SSR or
156
+ * zero flash on first paint, mirror that key in a blocking `<script>` in
157
+ * `index.html` before your bundle loads.
157
158
  */
158
159
  declare const ModeToggle: FC<ModeToggleProps>;
159
160
 
@@ -151,9 +151,10 @@ interface ModeToggleProps {
151
151
  *
152
152
  * 1. Pass `theme` + `setTheme` (e.g. from `next-themes`'s `useTheme`).
153
153
  * The component is then fully controlled.
154
- * 2. Omit both. The toggle reads the current state from `.dark` on
155
- * `<html>` and flips it on click. Good enough for prototypes and
156
- * cases where there is no theme manager.
154
+ * 2. Omit both. The toggle reads/writes `.dark` on `<html>` and persists
155
+ * the choice to `localStorage` under `STORAGE_KEYS.theme`. For SSR or
156
+ * zero flash on first paint, mirror that key in a blocking `<script>` in
157
+ * `index.html` before your bundle loads.
157
158
  */
158
159
  declare const ModeToggle: FC<ModeToggleProps>;
159
160
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timbal-ai/timbal-react",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "React components and runtime for building Timbal chat and studio apps",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -43,6 +43,7 @@
43
43
  "vite",
44
44
  "scripts/dev-linked.mjs",
45
45
  "README.md",
46
+ "CHANGELOG.md",
46
47
  "LICENSE"
47
48
  ],
48
49
  "scripts": {
@@ -3,10 +3,17 @@
3
3
  *
4
4
  * - Skips pre-bundling so `dist/` updates are not stuck in `node_modules/.vite/deps`
5
5
  * - Watches the linked package `dist/` and triggers a full reload when it changes
6
+ *
7
+ * IMPORTANT: this is a no-op for normal npm installs. Excluding the package from
8
+ * `optimizeDeps` only makes sense when it is `file:`-linked (a symlink in
9
+ * `node_modules`). For published installs Vite must pre-bundle the package so its
10
+ * CJS-only transitive deps (e.g. `use-sync-external-store/shim` reached via
11
+ * `radix-ui` -> `@radix-ui/react-use-is-hydrated`) are converted to ESM instead of
12
+ * leaking to the browser.
6
13
  */
7
14
  import { createRequire } from "node:module";
15
+ import fs from "node:fs";
8
16
  import path from "node:path";
9
- import { fileURLToPath } from "node:url";
10
17
 
11
18
  const TIMBAL_REACT_EXPORTS = [
12
19
  "@timbal-ai/timbal-react",
@@ -16,6 +23,36 @@ const TIMBAL_REACT_EXPORTS = [
16
23
  "@timbal-ai/timbal-react/app",
17
24
  ];
18
25
 
26
+ /** Subpath → source entry (used when `dist/*.esm.js` is missing). */
27
+ const SOURCE_ENTRIES = {
28
+ "@timbal-ai/timbal-react": "src/index.ts",
29
+ "@timbal-ai/timbal-react/chat": "src/chat.ts",
30
+ "@timbal-ai/timbal-react/studio": "src/studio.ts",
31
+ "@timbal-ai/timbal-react/ui": "src/ui.ts",
32
+ "@timbal-ai/timbal-react/app": "src/app.ts",
33
+ "@timbal-ai/timbal-react/styles.css": "src/styles.css",
34
+ };
35
+
36
+ function distIsBuilt(distDir) {
37
+ try {
38
+ return fs.statSync(path.join(distDir, "index.esm.js")).isFile();
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * CJS-only transitive deps that must be pre-bundled even when the package itself
46
+ * is excluded, so their `useSyncExternalStore` named imports resolve as ESM.
47
+ */
48
+ const CJS_INTEROP_DEPS = [
49
+ "radix-ui",
50
+ "@radix-ui/react-use-is-hydrated",
51
+ "use-sync-external-store/shim",
52
+ "use-sync-external-store/shim/with-selector",
53
+ "zustand",
54
+ ];
55
+
19
56
  function resolveLinkedPackageRoot() {
20
57
  try {
21
58
  const require = createRequire(import.meta.url);
@@ -26,6 +63,28 @@ function resolveLinkedPackageRoot() {
26
63
  }
27
64
  }
28
65
 
66
+ /**
67
+ * Only treat the install as "linked" when the `node_modules` entry is a symlink,
68
+ * i.e. installed via `file:../timbal-react` (or a workspace link). Normal npm
69
+ * installs are real directories and must be left to Vite's pre-bundler.
70
+ *
71
+ * @param {string} [root] consuming project root
72
+ */
73
+ function isLinkedInstall(root) {
74
+ const base = root || process.cwd();
75
+ const entry = path.join(
76
+ base,
77
+ "node_modules",
78
+ "@timbal-ai",
79
+ "timbal-react",
80
+ );
81
+ try {
82
+ return fs.lstatSync(entry).isSymbolicLink();
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+
29
88
  /** @returns {import('vite').Plugin} */
30
89
  export function timbalReactLocalDev() {
31
90
  /** @type {string | null} */
@@ -34,26 +93,53 @@ export function timbalReactLocalDev() {
34
93
  return {
35
94
  name: "timbal-react-local-dev",
36
95
  enforce: "pre",
37
- config() {
96
+ config(config) {
97
+ if (!isLinkedInstall(config.root)) return {};
98
+
38
99
  const pkgRoot = resolveLinkedPackageRoot();
39
100
  if (!pkgRoot) return {};
40
101
 
41
102
  distDir = path.join(pkgRoot, "dist");
42
- const distGlob = `${distDir.replace(/\\/g, "/")}/**`;
103
+ const built = distIsBuilt(distDir);
104
+ const srcDir = path.join(pkgRoot, "src");
105
+ const watchGlob = built
106
+ ? `${distDir.replace(/\\/g, "/")}/**`
107
+ : `${srcDir.replace(/\\/g, "/")}/**`;
108
+
109
+ if (!built) {
110
+ console.warn(
111
+ "[timbal-react] dist/ is missing (404 on *.esm.js) — aliasing to src/. " +
112
+ "Run `bun run build` in timbal-react for production-like dev, or `bun run example:app` from the repo root.",
113
+ );
114
+ }
115
+
116
+ /** @type {Record<string, string>} */
117
+ const alias = {};
118
+ if (!built) {
119
+ for (const [pkg, rel] of Object.entries(SOURCE_ENTRIES)) {
120
+ alias[pkg] = path.join(pkgRoot, rel);
121
+ }
122
+ }
43
123
 
44
124
  return {
125
+ resolve: Object.keys(alias).length ? { alias } : undefined,
45
126
  optimizeDeps: {
46
127
  exclude: TIMBAL_REACT_EXPORTS,
128
+ include: CJS_INTEROP_DEPS,
47
129
  },
48
130
  server: {
49
131
  watch: {
50
- ignored: ["**/.git/**", "**/node_modules/**", `!${distGlob}`],
132
+ ignored: ["**/.git/**", "**/node_modules/**", `!${watchGlob}`],
51
133
  },
52
134
  },
53
135
  };
54
136
  },
55
137
  handleHotUpdate({ file, server }) {
56
- if (!distDir || !file.startsWith(distDir)) return;
138
+ if (!distDir) return;
139
+ const srcDir = path.join(path.dirname(distDir), "src");
140
+ const isDist = file.startsWith(distDir);
141
+ const isSrc = file.startsWith(srcDir);
142
+ if (!isDist && !isSrc) return;
57
143
 
58
144
  for (const mod of server.moduleGraph.idToModuleMap.values()) {
59
145
  if (