@tambo-ai/react 0.75.0 → 1.0.0-rc.4
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/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +13 -13
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.test.js +3 -3
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -1
- package/dist/index.d.ts +7 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -59
- package/dist/index.js.map +1 -1
- package/dist/mcp/mcp-hooks.js +5 -5
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/model/component-metadata.d.ts +4 -4
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/providers/tambo-client-provider.d.ts +6 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +4 -2
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts +1 -1
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js +2 -10
- package/dist/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/dist/providers/tambo-interactables-additional-context.test.js +3 -19
- package/dist/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.d.ts +8 -17
- package/dist/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/dist/providers/tambo-mcp-token-provider.js +20 -97
- package/dist/providers/tambo-mcp-token-provider.js.map +1 -1
- package/dist/testing/tools.d.ts +3 -3
- package/dist/testing/tools.d.ts.map +1 -1
- package/dist/testing/tools.js.map +1 -1
- package/dist/util/registry-validators.js +1 -1
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/v1/__tests__/v1-interactables.test.js +1 -1
- package/dist/v1/__tests__/v1-interactables.test.js.map +1 -1
- package/dist/v1/components/v1-component-renderer.d.ts +9 -9
- package/dist/v1/components/v1-component-renderer.d.ts.map +1 -1
- package/dist/v1/components/v1-component-renderer.js +13 -13
- package/dist/v1/components/v1-component-renderer.js.map +1 -1
- package/dist/v1/components/v1-component-renderer.test.js +15 -15
- package/dist/v1/components/v1-component-renderer.test.js.map +1 -1
- package/{esm/hooks/use-current-message.d.ts → dist/v1/hooks/use-tambo-current-message.d.ts} +30 -9
- package/dist/v1/hooks/use-tambo-current-message.d.ts.map +1 -0
- package/dist/{hooks/use-current-message.js → v1/hooks/use-tambo-current-message.js} +13 -8
- package/dist/v1/hooks/use-tambo-current-message.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts +5 -5
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.js +8 -8
- package/dist/v1/hooks/use-tambo-v1-auth-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js +12 -12
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts +7 -6
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.js +50 -24
- package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js +60 -35
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts +9 -9
- package/dist/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-messages.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +7 -7
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +20 -22
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +51 -51
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +5 -5
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.js +12 -14
- package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +19 -19
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts +7 -7
- package/dist/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.js +9 -9
- package/dist/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js +44 -44
- package/dist/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +29 -29
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +5 -5
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +13 -17
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts +3 -3
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.js +4 -4
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +5 -5
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.d.ts +16 -7
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.js +41 -10
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +176 -48
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +31 -27
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +45 -35
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +20 -20
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +32 -32
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +22 -22
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +15 -15
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +17 -17
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +9 -9
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts +9 -9
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.js +7 -7
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.test.js +25 -25
- package/dist/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +9 -9
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +16 -16
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/dist/v1/types/auth.d.ts +2 -2
- package/dist/v1/types/auth.d.ts.map +1 -1
- package/dist/v1/types/auth.js.map +1 -1
- package/dist/v1/types/component.d.ts +3 -3
- package/dist/v1/types/component.d.ts.map +1 -1
- package/dist/v1/types/component.js +2 -2
- package/dist/v1/types/component.js.map +1 -1
- package/dist/v1/types/event.d.ts +1 -1
- package/dist/v1/types/event.js +1 -1
- package/dist/v1/types/event.js.map +1 -1
- package/dist/v1/types/message.d.ts +17 -24
- package/dist/v1/types/message.d.ts.map +1 -1
- package/dist/v1/types/message.js +1 -1
- package/dist/v1/types/message.js.map +1 -1
- package/dist/v1/types/thread.d.ts +10 -8
- package/dist/v1/types/thread.d.ts.map +1 -1
- package/dist/v1/types/thread.js +1 -1
- package/dist/v1/types/thread.js.map +1 -1
- package/dist/v1/types/tool-choice.d.ts +1 -1
- package/dist/v1/types/tool-choice.js.map +1 -1
- package/dist/v1/utils/component-renderer.d.ts +11 -5
- package/dist/v1/utils/component-renderer.d.ts.map +1 -1
- package/dist/v1/utils/component-renderer.js +16 -7
- package/dist/v1/utils/component-renderer.js.map +1 -1
- package/dist/v1/utils/component-renderer.test.js +7 -7
- package/dist/v1/utils/component-renderer.test.js.map +1 -1
- package/dist/v1/utils/event-accumulator.d.ts +13 -13
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
- package/dist/v1/utils/event-accumulator.js +26 -15
- package/dist/v1/utils/event-accumulator.js.map +1 -1
- package/dist/v1/utils/event-accumulator.test.js +54 -19
- package/dist/v1/utils/event-accumulator.test.js.map +1 -1
- package/dist/v1/utils/registry-conversion.d.ts +18 -18
- package/dist/v1/utils/registry-conversion.js +23 -23
- package/dist/v1/utils/registry-conversion.js.map +1 -1
- package/dist/v1/utils/stream-handler.d.ts +1 -1
- package/dist/v1/utils/stream-handler.js +1 -1
- package/dist/v1/utils/stream-handler.js.map +1 -1
- package/dist/v1/utils/thread-utils.d.ts +2 -2
- package/dist/v1/utils/thread-utils.d.ts.map +1 -1
- package/dist/v1/utils/thread-utils.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.d.ts +1 -1
- package/dist/v1/utils/tool-call-tracker.js +1 -1
- package/dist/v1/utils/tool-call-tracker.js.map +1 -1
- package/dist/v1/utils/tool-executor.d.ts +1 -1
- package/dist/v1/utils/tool-executor.js +2 -2
- package/dist/v1/utils/tool-executor.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +13 -13
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.test.js +1 -1
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -1
- package/esm/index.d.ts +7 -25
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +7 -21
- package/esm/index.js.map +1 -1
- package/esm/mcp/mcp-hooks.js +1 -1
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/model/component-metadata.d.ts +4 -4
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/providers/tambo-client-provider.d.ts +6 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +4 -2
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts +1 -1
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js +2 -10
- package/esm/providers/tambo-interactables-additional-context-edge-cases.test.js.map +1 -1
- package/esm/providers/tambo-interactables-additional-context.test.js +3 -19
- package/esm/providers/tambo-interactables-additional-context.test.js.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.d.ts +8 -17
- package/esm/providers/tambo-mcp-token-provider.d.ts.map +1 -1
- package/esm/providers/tambo-mcp-token-provider.js +20 -97
- package/esm/providers/tambo-mcp-token-provider.js.map +1 -1
- package/esm/testing/tools.d.ts +3 -3
- package/esm/testing/tools.d.ts.map +1 -1
- package/esm/testing/tools.js.map +1 -1
- package/esm/util/registry-validators.js +1 -1
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/v1/__tests__/v1-interactables.test.js +1 -1
- package/esm/v1/__tests__/v1-interactables.test.js.map +1 -1
- package/esm/v1/components/v1-component-renderer.d.ts +9 -9
- package/esm/v1/components/v1-component-renderer.d.ts.map +1 -1
- package/esm/v1/components/v1-component-renderer.js +12 -12
- package/esm/v1/components/v1-component-renderer.js.map +1 -1
- package/esm/v1/components/v1-component-renderer.test.js +16 -16
- package/esm/v1/components/v1-component-renderer.test.js.map +1 -1
- package/{dist/hooks/use-current-message.d.ts → esm/v1/hooks/use-tambo-current-message.d.ts} +30 -9
- package/esm/v1/hooks/use-tambo-current-message.d.ts.map +1 -0
- package/esm/{hooks/use-current-message.js → v1/hooks/use-tambo-current-message.js} +13 -8
- package/esm/v1/hooks/use-tambo-current-message.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts +5 -5
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.js +8 -8
- package/esm/v1/hooks/use-tambo-v1-auth-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js +14 -14
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts +7 -6
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.js +50 -24
- package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js +62 -37
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts +9 -9
- package/esm/v1/hooks/use-tambo-v1-messages.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.js +3 -3
- package/esm/v1/hooks/use-tambo-v1-messages.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +9 -9
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +21 -23
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +54 -54
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +5 -5
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.js +12 -14
- package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +21 -21
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts +7 -7
- package/esm/v1/hooks/use-tambo-v1-suggestions.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.js +11 -11
- package/esm/v1/hooks/use-tambo-v1-suggestions.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js +48 -48
- package/esm/v1/hooks/use-tambo-v1-suggestions.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread-input.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.js +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread-input.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +32 -32
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts +4 -4
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +6 -6
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +15 -19
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts +3 -3
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.js +4 -4
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +6 -6
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.d.ts +16 -7
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.js +43 -12
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +178 -50
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +31 -27
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +38 -33
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +20 -20
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +32 -32
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +23 -23
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +15 -15
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +17 -17
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +10 -10
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts +9 -9
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.js +9 -9
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.test.js +28 -28
- package/esm/v1/providers/tambo-v1-stub-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +9 -9
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +15 -15
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/esm/v1/types/auth.d.ts +2 -2
- package/esm/v1/types/auth.d.ts.map +1 -1
- package/esm/v1/types/auth.js.map +1 -1
- package/esm/v1/types/component.d.ts +3 -3
- package/esm/v1/types/component.d.ts.map +1 -1
- package/esm/v1/types/component.js +2 -2
- package/esm/v1/types/component.js.map +1 -1
- package/esm/v1/types/event.d.ts +1 -1
- package/esm/v1/types/event.js +1 -1
- package/esm/v1/types/event.js.map +1 -1
- package/esm/v1/types/message.d.ts +17 -24
- package/esm/v1/types/message.d.ts.map +1 -1
- package/esm/v1/types/message.js +1 -1
- package/esm/v1/types/message.js.map +1 -1
- package/esm/v1/types/thread.d.ts +10 -8
- package/esm/v1/types/thread.d.ts.map +1 -1
- package/esm/v1/types/thread.js +1 -1
- package/esm/v1/types/thread.js.map +1 -1
- package/esm/v1/types/tool-choice.d.ts +1 -1
- package/esm/v1/types/tool-choice.js.map +1 -1
- package/esm/v1/utils/component-renderer.d.ts +11 -5
- package/esm/v1/utils/component-renderer.d.ts.map +1 -1
- package/esm/v1/utils/component-renderer.js +13 -5
- package/esm/v1/utils/component-renderer.js.map +1 -1
- package/esm/v1/utils/component-renderer.test.js +8 -8
- package/esm/v1/utils/component-renderer.test.js.map +1 -1
- package/esm/v1/utils/event-accumulator.d.ts +13 -13
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
- package/esm/v1/utils/event-accumulator.js +26 -15
- package/esm/v1/utils/event-accumulator.js.map +1 -1
- package/esm/v1/utils/event-accumulator.test.js +54 -19
- package/esm/v1/utils/event-accumulator.test.js.map +1 -1
- package/esm/v1/utils/registry-conversion.d.ts +18 -18
- package/esm/v1/utils/registry-conversion.js +23 -23
- package/esm/v1/utils/registry-conversion.js.map +1 -1
- package/esm/v1/utils/stream-handler.d.ts +1 -1
- package/esm/v1/utils/stream-handler.js +1 -1
- package/esm/v1/utils/stream-handler.js.map +1 -1
- package/esm/v1/utils/thread-utils.d.ts +2 -2
- package/esm/v1/utils/thread-utils.d.ts.map +1 -1
- package/esm/v1/utils/thread-utils.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.d.ts +1 -1
- package/esm/v1/utils/tool-call-tracker.js +1 -1
- package/esm/v1/utils/tool-call-tracker.js.map +1 -1
- package/esm/v1/utils/tool-executor.d.ts +1 -1
- package/esm/v1/utils/tool-executor.js +2 -2
- package/esm/v1/utils/tool-executor.js.map +1 -1
- package/package.json +4 -9
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -34
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/use-component-state.d.ts +0 -30
- package/dist/hooks/use-component-state.d.ts.map +0 -1
- package/dist/hooks/use-component-state.js +0 -139
- package/dist/hooks/use-component-state.js.map +0 -1
- package/dist/hooks/use-component-state.test.d.ts +0 -2
- package/dist/hooks/use-component-state.test.d.ts.map +0 -1
- package/dist/hooks/use-component-state.test.js +0 -406
- package/dist/hooks/use-component-state.test.js.map +0 -1
- package/dist/hooks/use-current-message.d.ts.map +0 -1
- package/dist/hooks/use-current-message.js.map +0 -1
- package/dist/hooks/use-current-message.test.d.ts +0 -2
- package/dist/hooks/use-current-message.test.d.ts.map +0 -1
- package/dist/hooks/use-current-message.test.js +0 -269
- package/dist/hooks/use-current-message.test.js.map +0 -1
- package/dist/hooks/use-streaming-props.d.ts +0 -11
- package/dist/hooks/use-streaming-props.d.ts.map +0 -1
- package/dist/hooks/use-streaming-props.js +0 -37
- package/dist/hooks/use-streaming-props.js.map +0 -1
- package/dist/hooks/use-suggestions.d.ts +0 -46
- package/dist/hooks/use-suggestions.d.ts.map +0 -1
- package/dist/hooks/use-suggestions.js +0 -118
- package/dist/hooks/use-suggestions.js.map +0 -1
- package/dist/hooks/use-suggestions.test.d.ts +0 -2
- package/dist/hooks/use-suggestions.test.d.ts.map +0 -1
- package/dist/hooks/use-suggestions.test.js +0 -247
- package/dist/hooks/use-suggestions.test.js.map +0 -1
- package/dist/hooks/use-tambo-stream-status.d.ts +0 -90
- package/dist/hooks/use-tambo-stream-status.d.ts.map +0 -1
- package/dist/hooks/use-tambo-stream-status.js +0 -213
- package/dist/hooks/use-tambo-stream-status.js.map +0 -1
- package/dist/hooks/use-tambo-stream-status.test.d.ts +0 -2
- package/dist/hooks/use-tambo-stream-status.test.d.ts.map +0 -1
- package/dist/hooks/use-tambo-stream-status.test.js +0 -378
- package/dist/hooks/use-tambo-stream-status.test.js.map +0 -1
- package/dist/hooks/use-tambo-threads.d.ts +0 -158
- package/dist/hooks/use-tambo-threads.d.ts.map +0 -1
- package/dist/hooks/use-tambo-threads.js +0 -45
- package/dist/hooks/use-tambo-threads.js.map +0 -1
- package/dist/hooks/use-tambo-threads.test.d.ts +0 -2
- package/dist/hooks/use-tambo-threads.test.d.ts.map +0 -1
- package/dist/hooks/use-tambo-threads.test.js +0 -214
- package/dist/hooks/use-tambo-threads.test.js.map +0 -1
- package/dist/model/generate-component-response.d.ts +0 -37
- package/dist/model/generate-component-response.d.ts.map +0 -1
- package/dist/model/generate-component-response.js +0 -29
- package/dist/model/generate-component-response.js.map +0 -1
- package/dist/model/tambo-thread.d.ts +0 -15
- package/dist/model/tambo-thread.d.ts.map +0 -1
- package/dist/model/tambo-thread.js +0 -3
- package/dist/model/tambo-thread.js.map +0 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts +0 -2
- package/dist/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +0 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js +0 -592
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +0 -1
- package/dist/providers/index.d.ts +0 -13
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/providers/index.js +0 -41
- package/dist/providers/index.js.map +0 -1
- package/dist/providers/tambo-component-provider.d.ts +0 -23
- package/dist/providers/tambo-component-provider.d.ts.map +0 -1
- package/dist/providers/tambo-component-provider.js +0 -88
- package/dist/providers/tambo-component-provider.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/index.d.ts +0 -19
- package/dist/providers/tambo-prop-stream-provider/index.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/index.js +0 -43
- package/dist/providers/tambo-prop-stream-provider/index.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/pending.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/pending.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/pending.js +0 -31
- package/dist/providers/tambo-prop-stream-provider/pending.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/provider.d.ts +0 -17
- package/dist/providers/tambo-prop-stream-provider/provider.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/provider.js +0 -107
- package/dist/providers/tambo-prop-stream-provider/provider.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/streaming.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/streaming.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/streaming.js +0 -28
- package/dist/providers/tambo-prop-stream-provider/streaming.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/success.d.ts +0 -12
- package/dist/providers/tambo-prop-stream-provider/success.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/success.js +0 -28
- package/dist/providers/tambo-prop-stream-provider/success.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/types.d.ts +0 -25
- package/dist/providers/tambo-prop-stream-provider/types.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider/types.js +0 -6
- package/dist/providers/tambo-prop-stream-provider/types.js.map +0 -1
- package/dist/providers/tambo-prop-stream-provider.test.d.ts +0 -2
- package/dist/providers/tambo-prop-stream-provider.test.d.ts.map +0 -1
- package/dist/providers/tambo-prop-stream-provider.test.js +0 -275
- package/dist/providers/tambo-prop-stream-provider.test.js.map +0 -1
- package/dist/providers/tambo-provider.d.ts +0 -53
- package/dist/providers/tambo-provider.d.ts.map +0 -1
- package/dist/providers/tambo-provider.js +0 -133
- package/dist/providers/tambo-provider.js.map +0 -1
- package/dist/providers/tambo-stubs.d.ts +0 -89
- package/dist/providers/tambo-stubs.d.ts.map +0 -1
- package/dist/providers/tambo-stubs.js +0 -279
- package/dist/providers/tambo-stubs.js.map +0 -1
- package/dist/providers/tambo-stubs.test.d.ts +0 -2
- package/dist/providers/tambo-stubs.test.d.ts.map +0 -1
- package/dist/providers/tambo-stubs.test.js +0 -97
- package/dist/providers/tambo-stubs.test.js.map +0 -1
- package/dist/providers/tambo-thread-input-provider.d.ts +0 -65
- package/dist/providers/tambo-thread-input-provider.d.ts.map +0 -1
- package/dist/providers/tambo-thread-input-provider.js +0 -179
- package/dist/providers/tambo-thread-input-provider.js.map +0 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.d.ts +0 -2
- package/dist/providers/tambo-thread-provider-initial-messages.test.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js +0 -278
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +0 -1
- package/dist/providers/tambo-thread-provider.d.ts +0 -126
- package/dist/providers/tambo-thread-provider.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider.js +0 -931
- package/dist/providers/tambo-thread-provider.js.map +0 -1
- package/dist/providers/tambo-thread-provider.test.d.ts +0 -2
- package/dist/providers/tambo-thread-provider.test.d.ts.map +0 -1
- package/dist/providers/tambo-thread-provider.test.js +0 -1591
- package/dist/providers/tambo-thread-provider.test.js.map +0 -1
- package/dist/util/generate-component.d.ts +0 -12
- package/dist/util/generate-component.d.ts.map +0 -1
- package/dist/util/generate-component.js +0 -58
- package/dist/util/generate-component.js.map +0 -1
- package/dist/util/generate-component.test.d.ts +0 -2
- package/dist/util/generate-component.test.d.ts.map +0 -1
- package/dist/util/generate-component.test.js +0 -340
- package/dist/util/generate-component.test.js.map +0 -1
- package/esm/hooks/index.d.ts +0 -9
- package/esm/hooks/index.d.ts.map +0 -1
- package/esm/hooks/index.js +0 -10
- package/esm/hooks/index.js.map +0 -1
- package/esm/hooks/use-component-state.d.ts +0 -30
- package/esm/hooks/use-component-state.d.ts.map +0 -1
- package/esm/hooks/use-component-state.js +0 -136
- package/esm/hooks/use-component-state.js.map +0 -1
- package/esm/hooks/use-component-state.test.d.ts +0 -2
- package/esm/hooks/use-component-state.test.d.ts.map +0 -1
- package/esm/hooks/use-component-state.test.js +0 -401
- package/esm/hooks/use-component-state.test.js.map +0 -1
- package/esm/hooks/use-current-message.d.ts.map +0 -1
- package/esm/hooks/use-current-message.js.map +0 -1
- package/esm/hooks/use-current-message.test.d.ts +0 -2
- package/esm/hooks/use-current-message.test.d.ts.map +0 -1
- package/esm/hooks/use-current-message.test.js +0 -264
- package/esm/hooks/use-current-message.test.js.map +0 -1
- package/esm/hooks/use-streaming-props.d.ts +0 -11
- package/esm/hooks/use-streaming-props.d.ts.map +0 -1
- package/esm/hooks/use-streaming-props.js +0 -34
- package/esm/hooks/use-streaming-props.js.map +0 -1
- package/esm/hooks/use-suggestions.d.ts +0 -46
- package/esm/hooks/use-suggestions.d.ts.map +0 -1
- package/esm/hooks/use-suggestions.js +0 -115
- package/esm/hooks/use-suggestions.js.map +0 -1
- package/esm/hooks/use-suggestions.test.d.ts +0 -2
- package/esm/hooks/use-suggestions.test.d.ts.map +0 -1
- package/esm/hooks/use-suggestions.test.js +0 -245
- package/esm/hooks/use-suggestions.test.js.map +0 -1
- package/esm/hooks/use-tambo-stream-status.d.ts +0 -90
- package/esm/hooks/use-tambo-stream-status.d.ts.map +0 -1
- package/esm/hooks/use-tambo-stream-status.js +0 -210
- package/esm/hooks/use-tambo-stream-status.js.map +0 -1
- package/esm/hooks/use-tambo-stream-status.test.d.ts +0 -2
- package/esm/hooks/use-tambo-stream-status.test.d.ts.map +0 -1
- package/esm/hooks/use-tambo-stream-status.test.js +0 -376
- package/esm/hooks/use-tambo-stream-status.test.js.map +0 -1
- package/esm/hooks/use-tambo-threads.d.ts +0 -158
- package/esm/hooks/use-tambo-threads.d.ts.map +0 -1
- package/esm/hooks/use-tambo-threads.js +0 -42
- package/esm/hooks/use-tambo-threads.js.map +0 -1
- package/esm/hooks/use-tambo-threads.test.d.ts +0 -2
- package/esm/hooks/use-tambo-threads.test.d.ts.map +0 -1
- package/esm/hooks/use-tambo-threads.test.js +0 -212
- package/esm/hooks/use-tambo-threads.test.js.map +0 -1
- package/esm/model/generate-component-response.d.ts +0 -37
- package/esm/model/generate-component-response.d.ts.map +0 -1
- package/esm/model/generate-component-response.js +0 -25
- package/esm/model/generate-component-response.js.map +0 -1
- package/esm/model/tambo-thread.d.ts +0 -15
- package/esm/model/tambo-thread.d.ts.map +0 -1
- package/esm/model/tambo-thread.js +0 -2
- package/esm/model/tambo-thread.js.map +0 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts +0 -2
- package/esm/providers/__tests__/thread-input-resource-resolution.test.d.ts.map +0 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +0 -587
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +0 -1
- package/esm/providers/index.d.ts +0 -13
- package/esm/providers/index.d.ts.map +0 -1
- package/esm/providers/index.js +0 -11
- package/esm/providers/index.js.map +0 -1
- package/esm/providers/tambo-component-provider.d.ts +0 -23
- package/esm/providers/tambo-component-provider.d.ts.map +0 -1
- package/esm/providers/tambo-component-provider.js +0 -50
- package/esm/providers/tambo-component-provider.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/index.d.ts +0 -19
- package/esm/providers/tambo-prop-stream-provider/index.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/index.js +0 -22
- package/esm/providers/tambo-prop-stream-provider/index.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/pending.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/pending.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/pending.js +0 -24
- package/esm/providers/tambo-prop-stream-provider/pending.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/provider.d.ts +0 -17
- package/esm/providers/tambo-prop-stream-provider/provider.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/provider.js +0 -70
- package/esm/providers/tambo-prop-stream-provider/provider.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/streaming.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/streaming.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/streaming.js +0 -21
- package/esm/providers/tambo-prop-stream-provider/streaming.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/success.d.ts +0 -12
- package/esm/providers/tambo-prop-stream-provider/success.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/success.js +0 -21
- package/esm/providers/tambo-prop-stream-provider/success.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/types.d.ts +0 -25
- package/esm/providers/tambo-prop-stream-provider/types.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider/types.js +0 -3
- package/esm/providers/tambo-prop-stream-provider/types.js.map +0 -1
- package/esm/providers/tambo-prop-stream-provider.test.d.ts +0 -2
- package/esm/providers/tambo-prop-stream-provider.test.d.ts.map +0 -1
- package/esm/providers/tambo-prop-stream-provider.test.js +0 -270
- package/esm/providers/tambo-prop-stream-provider.test.js.map +0 -1
- package/esm/providers/tambo-provider.d.ts +0 -53
- package/esm/providers/tambo-provider.d.ts.map +0 -1
- package/esm/providers/tambo-provider.js +0 -94
- package/esm/providers/tambo-provider.js.map +0 -1
- package/esm/providers/tambo-stubs.d.ts +0 -89
- package/esm/providers/tambo-stubs.d.ts.map +0 -1
- package/esm/providers/tambo-stubs.js +0 -242
- package/esm/providers/tambo-stubs.js.map +0 -1
- package/esm/providers/tambo-stubs.test.d.ts +0 -2
- package/esm/providers/tambo-stubs.test.d.ts.map +0 -1
- package/esm/providers/tambo-stubs.test.js +0 -62
- package/esm/providers/tambo-stubs.test.js.map +0 -1
- package/esm/providers/tambo-thread-input-provider.d.ts +0 -65
- package/esm/providers/tambo-thread-input-provider.d.ts.map +0 -1
- package/esm/providers/tambo-thread-input-provider.js +0 -141
- package/esm/providers/tambo-thread-input-provider.js.map +0 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.d.ts +0 -2
- package/esm/providers/tambo-thread-provider-initial-messages.test.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +0 -273
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +0 -1
- package/esm/providers/tambo-thread-provider.d.ts +0 -126
- package/esm/providers/tambo-thread-provider.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider.js +0 -891
- package/esm/providers/tambo-thread-provider.js.map +0 -1
- package/esm/providers/tambo-thread-provider.test.d.ts +0 -2
- package/esm/providers/tambo-thread-provider.test.d.ts.map +0 -1
- package/esm/providers/tambo-thread-provider.test.js +0 -1553
- package/esm/providers/tambo-thread-provider.test.js.map +0 -1
- package/esm/util/generate-component.d.ts +0 -12
- package/esm/util/generate-component.d.ts.map +0 -1
- package/esm/util/generate-component.js +0 -52
- package/esm/util/generate-component.js.map +0 -1
- package/esm/util/generate-component.test.d.ts +0 -2
- package/esm/util/generate-component.test.d.ts.map +0 -1
- package/esm/util/generate-component.test.js +0 -302
- package/esm/util/generate-component.test.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Return type for
|
|
2
|
+
* Return type for useTamboComponentState hook.
|
|
3
3
|
* Similar to useState but with additional metadata.
|
|
4
4
|
*/
|
|
5
|
-
export type
|
|
5
|
+
export type UseTamboComponentStateReturn<S> = [
|
|
6
6
|
currentState: S,
|
|
7
7
|
setState: (newState: S | ((prev: S) => S)) => void,
|
|
8
8
|
meta: {
|
|
@@ -18,7 +18,8 @@ export type UseTamboV1ComponentStateReturn<S> = [
|
|
|
18
18
|
* to the Tambo backend. Server-side state updates are also reflected
|
|
19
19
|
* in the component.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* Can be used within rendered components, interactable components, or
|
|
22
|
+
* components awaiting provider context (acts as plain useState until context is available).
|
|
22
23
|
* @param keyName - The unique key to identify this state value within the component's state
|
|
23
24
|
* @param initialValue - Initial value for the state (used if no server state exists)
|
|
24
25
|
* @param debounceTime - Debounce time in milliseconds (default: 500ms)
|
|
@@ -26,7 +27,7 @@ export type UseTamboV1ComponentStateReturn<S> = [
|
|
|
26
27
|
* @example
|
|
27
28
|
* ```tsx
|
|
28
29
|
* function Counter() {
|
|
29
|
-
* const [count, setCount, { isPending }] =
|
|
30
|
+
* const [count, setCount, { isPending }] = useTamboComponentState('count', 0);
|
|
30
31
|
*
|
|
31
32
|
* return (
|
|
32
33
|
* <div>
|
|
@@ -39,6 +40,6 @@ export type UseTamboV1ComponentStateReturn<S> = [
|
|
|
39
40
|
* }
|
|
40
41
|
* ```
|
|
41
42
|
*/
|
|
42
|
-
export declare function
|
|
43
|
-
export declare function
|
|
43
|
+
export declare function useTamboComponentState<S = undefined>(keyName: string, initialValue?: S, debounceTime?: number): UseTamboComponentStateReturn<S | undefined>;
|
|
44
|
+
export declare function useTamboComponentState<S>(keyName: string, initialValue: S, debounceTime?: number): UseTamboComponentStateReturn<S>;
|
|
44
45
|
//# sourceMappingURL=use-tambo-v1-component-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-component-state.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-component-state.d.ts","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,MAAM,MAAM,4BAA4B,CAAC,CAAC,IAAI;IAC5C,YAAY,EAAE,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI;IAClD,IAAI,EAAE;QACJ,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,IAAI,CAAC;KACnB;CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,GAAG,SAAS,EAClD,OAAO,EAAE,MAAM,EACf,YAAY,CAAC,EAAE,CAAC,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,4BAA4B,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;AAC/C,wBAAgB,sBAAsB,CAAC,CAAC,EACtC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,EACf,YAAY,CAAC,EAAE,MAAM,GACpB,4BAA4B,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
"use client";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.useTamboComponentState = useTamboComponentState;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* useTamboComponentState - Component State Hook
|
|
7
7
|
*
|
|
8
8
|
* Provides bidirectional state synchronization between React components
|
|
9
9
|
* and the Tambo backend. State changes are debounced before syncing to
|
|
10
10
|
* the server, and server state updates are reflected in the component.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Works in three modes:
|
|
13
|
+
* - **Rendered components**: syncs state bidirectionally with the server
|
|
14
|
+
* - **Interactable components**: syncs state via the interactable provider
|
|
15
|
+
* - **No context yet**: acts as plain useState (no side effects) until a
|
|
16
|
+
* provider wraps the component (e.g., first render before withTamboInteractable)
|
|
13
17
|
*/
|
|
14
18
|
const react_1 = require("react");
|
|
15
19
|
const use_debounce_1 = require("use-debounce");
|
|
@@ -17,20 +21,30 @@ const fast_equals_1 = require("fast-equals");
|
|
|
17
21
|
const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
|
|
18
22
|
const tambo_interactable_provider_1 = require("../../providers/tambo-interactable-provider");
|
|
19
23
|
const component_renderer_1 = require("../utils/component-renderer");
|
|
24
|
+
const tambo_v1_provider_1 = require("../providers/tambo-v1-provider");
|
|
20
25
|
const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
|
|
21
26
|
const thread_utils_1 = require("../utils/thread-utils");
|
|
22
|
-
function
|
|
27
|
+
function useTamboComponentState(keyName, initialValue, debounceTime = 500) {
|
|
23
28
|
const client = (0, tambo_client_provider_1.useTamboClient)();
|
|
24
|
-
const {
|
|
29
|
+
const { userKey } = (0, tambo_v1_provider_1.useTamboConfig)();
|
|
30
|
+
const componentContent = (0, component_renderer_1.useComponentContentOptional)();
|
|
25
31
|
const streamState = (0, tambo_v1_stream_context_1.useStreamState)();
|
|
26
32
|
const { setInteractableState, getInteractableComponentState } = (0, tambo_interactable_provider_1.useTamboInteractable)();
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
//
|
|
30
|
-
const
|
|
33
|
+
// componentContent is null on the first render of interactable components
|
|
34
|
+
// (before withTamboInteractable sets the interactableId and wraps with provider).
|
|
35
|
+
// When null, we act as plain useState with no side effects.
|
|
36
|
+
const isContextAvailable = componentContent !== null;
|
|
37
|
+
const componentId = componentContent?.componentId ?? "";
|
|
38
|
+
const threadId = componentContent?.threadId ?? "";
|
|
39
|
+
// Only treat as interactable when we have real context with threadId=""
|
|
40
|
+
// (set by withTamboInteractable). When context is missing entirely,
|
|
41
|
+
// neither interactable nor server-sync paths should run.
|
|
42
|
+
const isInteractable = isContextAvailable && threadId === "";
|
|
43
|
+
// Find the component content to get server state (only for rendered components)
|
|
44
|
+
const renderedContent = isInteractable
|
|
31
45
|
? undefined
|
|
32
46
|
: (0, thread_utils_1.findComponentContent)(streamState, threadId, componentId);
|
|
33
|
-
const serverState =
|
|
47
|
+
const serverState = renderedContent?.state;
|
|
34
48
|
const serverValue = serverState?.[keyName];
|
|
35
49
|
// For interactable components, read state from the interactable provider
|
|
36
50
|
const interactableState = isInteractable
|
|
@@ -47,9 +61,9 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
47
61
|
const hasPendingLocalChangeRef = (0, react_1.useRef)(false);
|
|
48
62
|
// Track in-flight sync requests to avoid stale completions clearing pending state
|
|
49
63
|
const syncSeqRef = (0, react_1.useRef)(0);
|
|
50
|
-
// Debounced function to sync state to server (only used for
|
|
64
|
+
// Debounced function to sync state to server (only used for rendered components)
|
|
51
65
|
const syncToServer = (0, use_debounce_1.useDebouncedCallback)(async (newState) => {
|
|
52
|
-
if (isInteractable)
|
|
66
|
+
if (!isContextAvailable || isInteractable)
|
|
53
67
|
return;
|
|
54
68
|
const seq = ++syncSeqRef.current;
|
|
55
69
|
setIsPending(true);
|
|
@@ -59,6 +73,7 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
59
73
|
await client.threads.state.updateState(componentId, {
|
|
60
74
|
threadId,
|
|
61
75
|
state: { [keyName]: newState },
|
|
76
|
+
userKey,
|
|
62
77
|
});
|
|
63
78
|
// Clear pending flag after successful sync
|
|
64
79
|
hasPendingLocalChangeRef.current = false;
|
|
@@ -68,7 +83,7 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
68
83
|
hasPendingLocalChangeRef.current = false;
|
|
69
84
|
const syncError = err instanceof Error ? err : new Error(String(err));
|
|
70
85
|
setError(syncError);
|
|
71
|
-
console.error(`[
|
|
86
|
+
console.error(`[useTamboComponentState] Failed to sync state for ${componentId}:`, syncError);
|
|
72
87
|
}
|
|
73
88
|
finally {
|
|
74
89
|
// Only clear isPending if this is the most recent request
|
|
@@ -83,18 +98,29 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
83
98
|
const nextState = typeof newState === "function"
|
|
84
99
|
? newState(prev)
|
|
85
100
|
: newState;
|
|
101
|
+
// No side effects when context isn't available yet (local-only update)
|
|
102
|
+
if (!isContextAvailable) {
|
|
103
|
+
return nextState;
|
|
104
|
+
}
|
|
86
105
|
if (isInteractable) {
|
|
87
106
|
// For interactable components, update the interactable provider's state
|
|
88
107
|
setInteractableState(componentId, keyName, nextState);
|
|
89
108
|
}
|
|
90
109
|
else {
|
|
91
|
-
// For
|
|
110
|
+
// For rendered components, trigger debounced sync to server
|
|
92
111
|
hasPendingLocalChangeRef.current = true;
|
|
93
112
|
void syncToServer(nextState);
|
|
94
113
|
}
|
|
95
114
|
return nextState;
|
|
96
115
|
});
|
|
97
|
-
}, [
|
|
116
|
+
}, [
|
|
117
|
+
isContextAvailable,
|
|
118
|
+
isInteractable,
|
|
119
|
+
syncToServer,
|
|
120
|
+
setInteractableState,
|
|
121
|
+
componentId,
|
|
122
|
+
keyName,
|
|
123
|
+
]);
|
|
98
124
|
// Set initial value in interactable state on mount if no existing state
|
|
99
125
|
const existingInteractableState = isInteractable
|
|
100
126
|
? getInteractableComponentState(componentId)?.[keyName]
|
|
@@ -121,9 +147,9 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
121
147
|
return;
|
|
122
148
|
setLocalState((prev) => (0, fast_equals_1.deepEqual)(prev, interactableState) ? prev : interactableState);
|
|
123
149
|
}, [isInteractable, interactableState]);
|
|
124
|
-
// Sync from server state when it changes (e.g., from streaming events) -
|
|
150
|
+
// Sync from server state when it changes (e.g., from streaming events) - rendered components only
|
|
125
151
|
(0, react_1.useEffect)(() => {
|
|
126
|
-
if (isInteractable)
|
|
152
|
+
if (!isContextAvailable || isInteractable)
|
|
127
153
|
return;
|
|
128
154
|
if (serverValue === undefined)
|
|
129
155
|
return;
|
|
@@ -138,21 +164,21 @@ function useTamboV1ComponentState(keyName, initialValue, debounceTime = 500) {
|
|
|
138
164
|
}
|
|
139
165
|
// Use functional update to avoid localState in deps
|
|
140
166
|
setLocalState((prev) => (0, fast_equals_1.deepEqual)(serverValue, prev) ? prev : serverValue);
|
|
141
|
-
}, [isInteractable, serverValue]);
|
|
142
|
-
// Flush pending updates on unmount (only for
|
|
167
|
+
}, [isContextAvailable, isInteractable, serverValue]);
|
|
168
|
+
// Flush pending updates on unmount (only for rendered components)
|
|
143
169
|
(0, react_1.useEffect)(() => {
|
|
144
|
-
if (isInteractable)
|
|
170
|
+
if (!isContextAvailable || isInteractable)
|
|
145
171
|
return;
|
|
146
172
|
return () => {
|
|
147
173
|
void syncToServer.flush();
|
|
148
174
|
};
|
|
149
|
-
}, [isInteractable, syncToServer]);
|
|
150
|
-
// Flush function for immediate sync (noop
|
|
175
|
+
}, [isContextAvailable, isInteractable, syncToServer]);
|
|
176
|
+
// Flush function for immediate sync (noop when context is unavailable or interactable)
|
|
151
177
|
const flush = (0, react_1.useCallback)(() => {
|
|
152
|
-
if (isInteractable)
|
|
178
|
+
if (!isContextAvailable || isInteractable)
|
|
153
179
|
return;
|
|
154
180
|
void syncToServer.flush();
|
|
155
|
-
}, [isInteractable, syncToServer]);
|
|
181
|
+
}, [isContextAvailable, isInteractable, syncToServer]);
|
|
156
182
|
return [localState, setState, { isPending, error, flush }];
|
|
157
183
|
}
|
|
158
184
|
//# sourceMappingURL=use-tambo-v1-component-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tambo-v1-component-state.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboV1ComponentState - Component State Hook for v1 API\n *\n * Provides bidirectional state synchronization between React components\n * and the Tambo backend. State changes are debounced before syncing to\n * the server, and server state updates are reflected in the component.\n *\n * Must be used within a component rendered via the component renderer.\n */\n\nimport { useCallback, useEffect, useState, useRef } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { deepEqual } from \"fast-equals\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useTamboInteractable } from \"../../providers/tambo-interactable-provider\";\nimport { useV1ComponentContent } from \"../utils/component-renderer\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport { findComponentContent } from \"../utils/thread-utils\";\n\n/**\n * Return type for useTamboV1ComponentState hook.\n * Similar to useState but with additional metadata.\n */\nexport type UseTamboV1ComponentStateReturn<S> = [\n currentState: S,\n setState: (newState: S | ((prev: S) => S)) => void,\n meta: {\n isPending: boolean;\n error: Error | null;\n flush: () => void;\n },\n];\n\n/**\n * Hook for managing component state with bidirectional server sync.\n *\n * This hook acts like useState but automatically syncs state changes\n * to the Tambo backend. Server-side state updates are also reflected\n * in the component.\n *\n * Must be used within a component rendered via the component renderer.\n * @param keyName - The unique key to identify this state value within the component's state\n * @param initialValue - Initial value for the state (used if no server state exists)\n * @param debounceTime - Debounce time in milliseconds (default: 500ms)\n * @returns Tuple of [currentState, setState, meta]\n * @example\n * ```tsx\n * function Counter() {\n * const [count, setCount, { isPending }] = useTamboV1ComponentState('count', 0);\n *\n * return (\n * <div>\n * <span>{count}</span>\n * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>\n * Increment\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboV1ComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S | undefined>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): UseTamboV1ComponentStateReturn<S>;\nexport function useTamboV1ComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): UseTamboV1ComponentStateReturn<S> {\n const client = useTamboClient();\n const { componentId, threadId } = useV1ComponentContent();\n const streamState = useStreamState();\n const { setInteractableState, getInteractableComponentState } =\n useTamboInteractable();\n\n // Interactable components use threadId=\"\" (set by withTamboInteractable)\n const isInteractable = threadId === \"\";\n\n // Find the component content to get server state (only for v1-rendered components)\n const componentContent = isInteractable\n ? undefined\n : findComponentContent(streamState, threadId, componentId);\n const serverState = componentContent?.state as\n | Record<string, unknown>\n | undefined;\n const serverValue = serverState?.[keyName] as S | undefined;\n\n // For interactable components, read state from the interactable provider\n const interactableState = isInteractable\n ? (getInteractableComponentState(componentId)?.[keyName] as S | undefined)\n : undefined;\n\n // Local state - initialized from interactable state, server state, or initial value\n const [localState, setLocalState] = useState<S>(\n () => interactableState ?? serverValue ?? (initialValue as S),\n );\n\n // Track pending state and errors\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track the last value we sent to avoid overwriting with stale server state\n const lastSentValueRef = useRef<S | undefined>(undefined);\n\n // Track whether there's a pending local change that hasn't synced yet\n const hasPendingLocalChangeRef = useRef(false);\n\n // Track in-flight sync requests to avoid stale completions clearing pending state\n const syncSeqRef = useRef(0);\n\n // Debounced function to sync state to server (only used for v1-rendered components)\n const syncToServer = useDebouncedCallback(async (newState: S) => {\n if (isInteractable) return;\n\n const seq = ++syncSeqRef.current;\n setIsPending(true);\n setError(null);\n lastSentValueRef.current = newState;\n\n try {\n await client.threads.state.updateState(componentId, {\n threadId,\n state: { [keyName]: newState },\n });\n // Clear pending flag after successful sync\n hasPendingLocalChangeRef.current = false;\n } catch (err) {\n // Clear pending flag on error to allow server reconciliation\n hasPendingLocalChangeRef.current = false;\n const syncError = err instanceof Error ? err : new Error(String(err));\n setError(syncError);\n console.error(\n `[useTamboV1ComponentState] Failed to sync state for ${componentId}:`,\n syncError,\n );\n } finally {\n // Only clear isPending if this is the most recent request\n if (seq === syncSeqRef.current) {\n setIsPending(false);\n }\n }\n }, debounceTime);\n\n // setState function that updates local state and syncs appropriately\n const setState = useCallback(\n (newState: S | ((prev: S) => S)) => {\n setLocalState((prev) => {\n const nextState =\n typeof newState === \"function\"\n ? (newState as (prev: S) => S)(prev)\n : newState;\n\n if (isInteractable) {\n // For interactable components, update the interactable provider's state\n setInteractableState(componentId, keyName, nextState);\n } else {\n // For v1-rendered components, trigger debounced sync to server\n hasPendingLocalChangeRef.current = true;\n void syncToServer(nextState);\n }\n\n return nextState;\n });\n },\n [isInteractable, syncToServer, setInteractableState, componentId, keyName],\n );\n\n // Set initial value in interactable state on mount if no existing state\n const existingInteractableState = isInteractable\n ? getInteractableComponentState(componentId)?.[keyName]\n : undefined;\n const shouldUpdateInteractableInitial =\n isInteractable &&\n existingInteractableState === undefined &&\n initialValue !== undefined;\n\n useEffect(() => {\n if (!shouldUpdateInteractableInitial) return;\n setInteractableState(componentId, keyName, initialValue!);\n }, [\n shouldUpdateInteractableInitial,\n componentId,\n keyName,\n initialValue,\n setInteractableState,\n ]);\n\n // Sync from interactable provider when state changes externally (e.g., from AI tool call)\n useEffect(() => {\n if (!isInteractable) return;\n if (interactableState === undefined) return;\n setLocalState((prev) =>\n deepEqual(prev, interactableState) ? prev : (interactableState as S),\n );\n }, [isInteractable, interactableState]);\n\n // Sync from server state when it changes (e.g., from streaming events) - v1-rendered only\n useEffect(() => {\n if (isInteractable) return;\n if (serverValue === undefined) return;\n\n // Don't overwrite local changes that haven't synced yet\n if (hasPendingLocalChangeRef.current) return;\n\n // Only sync if the server value is different from what we last sent\n // This prevents overwriting local state with stale server values\n if (\n lastSentValueRef.current !== undefined &&\n deepEqual(serverValue, lastSentValueRef.current)\n ) {\n return;\n }\n\n // Use functional update to avoid localState in deps\n setLocalState((prev) =>\n deepEqual(serverValue, prev) ? prev : serverValue,\n );\n }, [isInteractable, serverValue]);\n\n // Flush pending updates on unmount (only for v1-rendered components)\n useEffect(() => {\n if (isInteractable) return;\n return () => {\n void syncToServer.flush();\n };\n }, [isInteractable, syncToServer]);\n\n // Flush function for immediate sync (noop for interactable)\n const flush = useCallback(() => {\n if (isInteractable) return;\n void syncToServer.flush();\n }, [isInteractable, syncToServer]);\n\n return [localState, setState, { isPending, error, flush }];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-tambo-v1-component-state.js","sourceRoot":"","sources":["../../../src/v1/hooks/use-tambo-v1-component-state.ts"],"names":[],"mappings":"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","sourcesContent":["\"use client\";\n\n/**\n * useTamboComponentState - Component State Hook\n *\n * Provides bidirectional state synchronization between React components\n * and the Tambo backend. State changes are debounced before syncing to\n * the server, and server state updates are reflected in the component.\n *\n * Works in three modes:\n * - **Rendered components**: syncs state bidirectionally with the server\n * - **Interactable components**: syncs state via the interactable provider\n * - **No context yet**: acts as plain useState (no side effects) until a\n * provider wraps the component (e.g., first render before withTamboInteractable)\n */\n\nimport { useCallback, useEffect, useState, useRef } from \"react\";\nimport { useDebouncedCallback } from \"use-debounce\";\nimport { deepEqual } from \"fast-equals\";\nimport { useTamboClient } from \"../../providers/tambo-client-provider\";\nimport { useTamboInteractable } from \"../../providers/tambo-interactable-provider\";\nimport { useComponentContentOptional } from \"../utils/component-renderer\";\nimport { useTamboConfig } from \"../providers/tambo-v1-provider\";\nimport { useStreamState } from \"../providers/tambo-v1-stream-context\";\nimport { findComponentContent } from \"../utils/thread-utils\";\n\n/**\n * Return type for useTamboComponentState hook.\n * Similar to useState but with additional metadata.\n */\nexport type UseTamboComponentStateReturn<S> = [\n currentState: S,\n setState: (newState: S | ((prev: S) => S)) => void,\n meta: {\n isPending: boolean;\n error: Error | null;\n flush: () => void;\n },\n];\n\n/**\n * Hook for managing component state with bidirectional server sync.\n *\n * This hook acts like useState but automatically syncs state changes\n * to the Tambo backend. Server-side state updates are also reflected\n * in the component.\n *\n * Can be used within rendered components, interactable components, or\n * components awaiting provider context (acts as plain useState until context is available).\n * @param keyName - The unique key to identify this state value within the component's state\n * @param initialValue - Initial value for the state (used if no server state exists)\n * @param debounceTime - Debounce time in milliseconds (default: 500ms)\n * @returns Tuple of [currentState, setState, meta]\n * @example\n * ```tsx\n * function Counter() {\n * const [count, setCount, { isPending }] = useTamboComponentState('count', 0);\n *\n * return (\n * <div>\n * <span>{count}</span>\n * <button onClick={() => setCount(c => c + 1)} disabled={isPending}>\n * Increment\n * </button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useTamboComponentState<S = undefined>(\n keyName: string,\n initialValue?: S,\n debounceTime?: number,\n): UseTamboComponentStateReturn<S | undefined>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue: S,\n debounceTime?: number,\n): UseTamboComponentStateReturn<S>;\nexport function useTamboComponentState<S>(\n keyName: string,\n initialValue?: S,\n debounceTime = 500,\n): UseTamboComponentStateReturn<S> {\n const client = useTamboClient();\n const { userKey } = useTamboConfig();\n const componentContent = useComponentContentOptional();\n const streamState = useStreamState();\n const { setInteractableState, getInteractableComponentState } =\n useTamboInteractable();\n\n // componentContent is null on the first render of interactable components\n // (before withTamboInteractable sets the interactableId and wraps with provider).\n // When null, we act as plain useState with no side effects.\n const isContextAvailable = componentContent !== null;\n const componentId = componentContent?.componentId ?? \"\";\n const threadId = componentContent?.threadId ?? \"\";\n\n // Only treat as interactable when we have real context with threadId=\"\"\n // (set by withTamboInteractable). When context is missing entirely,\n // neither interactable nor server-sync paths should run.\n const isInteractable = isContextAvailable && threadId === \"\";\n\n // Find the component content to get server state (only for rendered components)\n const renderedContent = isInteractable\n ? undefined\n : findComponentContent(streamState, threadId, componentId);\n const serverState = renderedContent?.state as\n | Record<string, unknown>\n | undefined;\n const serverValue = serverState?.[keyName] as S | undefined;\n\n // For interactable components, read state from the interactable provider\n const interactableState = isInteractable\n ? (getInteractableComponentState(componentId)?.[keyName] as S | undefined)\n : undefined;\n\n // Local state - initialized from interactable state, server state, or initial value\n const [localState, setLocalState] = useState<S>(\n () => interactableState ?? serverValue ?? (initialValue as S),\n );\n\n // Track pending state and errors\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track the last value we sent to avoid overwriting with stale server state\n const lastSentValueRef = useRef<S | undefined>(undefined);\n\n // Track whether there's a pending local change that hasn't synced yet\n const hasPendingLocalChangeRef = useRef(false);\n\n // Track in-flight sync requests to avoid stale completions clearing pending state\n const syncSeqRef = useRef(0);\n\n // Debounced function to sync state to server (only used for rendered components)\n const syncToServer = useDebouncedCallback(async (newState: S) => {\n if (!isContextAvailable || isInteractable) return;\n\n const seq = ++syncSeqRef.current;\n setIsPending(true);\n setError(null);\n lastSentValueRef.current = newState;\n\n try {\n await client.threads.state.updateState(componentId, {\n threadId,\n state: { [keyName]: newState },\n userKey,\n });\n // Clear pending flag after successful sync\n hasPendingLocalChangeRef.current = false;\n } catch (err) {\n // Clear pending flag on error to allow server reconciliation\n hasPendingLocalChangeRef.current = false;\n const syncError = err instanceof Error ? err : new Error(String(err));\n setError(syncError);\n console.error(\n `[useTamboComponentState] Failed to sync state for ${componentId}:`,\n syncError,\n );\n } finally {\n // Only clear isPending if this is the most recent request\n if (seq === syncSeqRef.current) {\n setIsPending(false);\n }\n }\n }, debounceTime);\n\n // setState function that updates local state and syncs appropriately\n const setState = useCallback(\n (newState: S | ((prev: S) => S)) => {\n setLocalState((prev) => {\n const nextState =\n typeof newState === \"function\"\n ? (newState as (prev: S) => S)(prev)\n : newState;\n\n // No side effects when context isn't available yet (local-only update)\n if (!isContextAvailable) {\n return nextState;\n }\n\n if (isInteractable) {\n // For interactable components, update the interactable provider's state\n setInteractableState(componentId, keyName, nextState);\n } else {\n // For rendered components, trigger debounced sync to server\n hasPendingLocalChangeRef.current = true;\n void syncToServer(nextState);\n }\n\n return nextState;\n });\n },\n [\n isContextAvailable,\n isInteractable,\n syncToServer,\n setInteractableState,\n componentId,\n keyName,\n ],\n );\n\n // Set initial value in interactable state on mount if no existing state\n const existingInteractableState = isInteractable\n ? getInteractableComponentState(componentId)?.[keyName]\n : undefined;\n const shouldUpdateInteractableInitial =\n isInteractable &&\n existingInteractableState === undefined &&\n initialValue !== undefined;\n\n useEffect(() => {\n if (!shouldUpdateInteractableInitial) return;\n setInteractableState(componentId, keyName, initialValue!);\n }, [\n shouldUpdateInteractableInitial,\n componentId,\n keyName,\n initialValue,\n setInteractableState,\n ]);\n\n // Sync from interactable provider when state changes externally (e.g., from AI tool call)\n useEffect(() => {\n if (!isInteractable) return;\n if (interactableState === undefined) return;\n setLocalState((prev) =>\n deepEqual(prev, interactableState) ? prev : (interactableState as S),\n );\n }, [isInteractable, interactableState]);\n\n // Sync from server state when it changes (e.g., from streaming events) - rendered components only\n useEffect(() => {\n if (!isContextAvailable || isInteractable) return;\n if (serverValue === undefined) return;\n\n // Don't overwrite local changes that haven't synced yet\n if (hasPendingLocalChangeRef.current) return;\n\n // Only sync if the server value is different from what we last sent\n // This prevents overwriting local state with stale server values\n if (\n lastSentValueRef.current !== undefined &&\n deepEqual(serverValue, lastSentValueRef.current)\n ) {\n return;\n }\n\n // Use functional update to avoid localState in deps\n setLocalState((prev) =>\n deepEqual(serverValue, prev) ? prev : serverValue,\n );\n }, [isContextAvailable, isInteractable, serverValue]);\n\n // Flush pending updates on unmount (only for rendered components)\n useEffect(() => {\n if (!isContextAvailable || isInteractable) return;\n return () => {\n void syncToServer.flush();\n };\n }, [isContextAvailable, isInteractable, syncToServer]);\n\n // Flush function for immediate sync (noop when context is unavailable or interactable)\n const flush = useCallback(() => {\n if (!isContextAvailable || isInteractable) return;\n void syncToServer.flush();\n }, [isContextAvailable, isInteractable, syncToServer]);\n\n return [localState, setState, { isPending, error, flush }];\n}\n"]}
|
|
@@ -10,10 +10,13 @@ jest.mock("../providers/tambo-v1-stream-context", () => ({
|
|
|
10
10
|
useStreamState: jest.fn(),
|
|
11
11
|
}));
|
|
12
12
|
jest.mock("../utils/component-renderer", () => ({
|
|
13
|
-
|
|
13
|
+
useComponentContentOptional: jest.fn(),
|
|
14
14
|
}));
|
|
15
15
|
const mockSetInteractableState = jest.fn();
|
|
16
16
|
const mockGetInteractableComponentState = jest.fn(() => undefined);
|
|
17
|
+
jest.mock("../providers/tambo-v1-provider", () => ({
|
|
18
|
+
useTamboConfig: jest.fn(() => ({})),
|
|
19
|
+
}));
|
|
17
20
|
jest.mock("../../providers/tambo-interactable-provider", () => ({
|
|
18
21
|
useTamboInteractable: () => ({
|
|
19
22
|
interactableComponents: [],
|
|
@@ -43,10 +46,11 @@ jest.mock("use-debounce", () => ({
|
|
|
43
46
|
}));
|
|
44
47
|
// Import the mocked modules
|
|
45
48
|
const tambo_client_provider_1 = require("../../providers/tambo-client-provider");
|
|
49
|
+
const tambo_v1_provider_1 = require("../providers/tambo-v1-provider");
|
|
46
50
|
const tambo_v1_stream_context_1 = require("../providers/tambo-v1-stream-context");
|
|
47
51
|
const component_renderer_1 = require("../utils/component-renderer");
|
|
48
52
|
const use_debounce_1 = require("use-debounce");
|
|
49
|
-
describe("
|
|
53
|
+
describe("useTamboComponentState", () => {
|
|
50
54
|
const mockUpdateState = jest.fn();
|
|
51
55
|
const mockComponentId = "comp_test123";
|
|
52
56
|
const mockThreadId = "thread_abc";
|
|
@@ -87,6 +91,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
87
91
|
});
|
|
88
92
|
beforeEach(() => {
|
|
89
93
|
jest.clearAllMocks();
|
|
94
|
+
jest.mocked(tambo_v1_provider_1.useTamboConfig).mockReturnValue({});
|
|
90
95
|
// Setup default mocks
|
|
91
96
|
jest.mocked(tambo_client_provider_1.useTamboClient).mockReturnValue({
|
|
92
97
|
threads: {
|
|
@@ -95,7 +100,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
95
100
|
},
|
|
96
101
|
},
|
|
97
102
|
});
|
|
98
|
-
jest.mocked(component_renderer_1.
|
|
103
|
+
jest.mocked(component_renderer_1.useComponentContentOptional).mockReturnValue({
|
|
99
104
|
componentId: mockComponentId,
|
|
100
105
|
threadId: mockThreadId,
|
|
101
106
|
messageId: mockMessageId,
|
|
@@ -118,7 +123,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
118
123
|
it("should initialize with initialValue when no server state exists", () => {
|
|
119
124
|
const initialValue = "test-initial";
|
|
120
125
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
121
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
126
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", initialValue));
|
|
122
127
|
expect(result.current[0]).toBe(initialValue);
|
|
123
128
|
});
|
|
124
129
|
it("should use server state over initialValue", () => {
|
|
@@ -127,12 +132,12 @@ describe("useTamboV1ComponentState", () => {
|
|
|
127
132
|
jest
|
|
128
133
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
129
134
|
.mockReturnValue(createMockStreamState({ testKey: serverValue }));
|
|
130
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
135
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", initialValue));
|
|
131
136
|
expect(result.current[0]).toBe(serverValue);
|
|
132
137
|
});
|
|
133
138
|
it("should handle undefined initialValue gracefully", () => {
|
|
134
139
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
135
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
140
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey"));
|
|
136
141
|
expect(result.current[0]).toBeUndefined();
|
|
137
142
|
});
|
|
138
143
|
it("should handle different data types correctly", () => {
|
|
@@ -147,7 +152,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
147
152
|
jest
|
|
148
153
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
149
154
|
.mockReturnValue(createMockStreamState({ testKey: value }));
|
|
150
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
155
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", value));
|
|
151
156
|
expect(result.current[0]).toEqual(value);
|
|
152
157
|
});
|
|
153
158
|
});
|
|
@@ -158,7 +163,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
158
163
|
jest
|
|
159
164
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
160
165
|
.mockReturnValue(createMockStreamState({ testKey: initialValue }));
|
|
161
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
166
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", initialValue));
|
|
162
167
|
const newValue = "updated";
|
|
163
168
|
(0, react_1.act)(() => {
|
|
164
169
|
result.current[1](newValue);
|
|
@@ -170,7 +175,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
170
175
|
jest
|
|
171
176
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
172
177
|
.mockReturnValue(createMockStreamState({ counter: initialValue }));
|
|
173
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
178
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("counter", initialValue));
|
|
174
179
|
(0, react_1.act)(() => {
|
|
175
180
|
result.current[1]((prev) => (prev ?? 0) + 1);
|
|
176
181
|
});
|
|
@@ -181,7 +186,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
181
186
|
jest
|
|
182
187
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
183
188
|
.mockReturnValue(createMockStreamState({ testKey: initialValue }));
|
|
184
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
189
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", initialValue));
|
|
185
190
|
const newValue = "updated";
|
|
186
191
|
(0, react_1.act)(() => {
|
|
187
192
|
result.current[1](newValue);
|
|
@@ -190,6 +195,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
190
195
|
expect(mockUpdateState).toHaveBeenCalledWith(mockComponentId, {
|
|
191
196
|
threadId: mockThreadId,
|
|
192
197
|
state: { testKey: newValue },
|
|
198
|
+
userKey: undefined,
|
|
193
199
|
});
|
|
194
200
|
});
|
|
195
201
|
it("should work with complex objects", () => {
|
|
@@ -197,7 +203,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
197
203
|
jest
|
|
198
204
|
.mocked(tambo_v1_stream_context_1.useStreamState)
|
|
199
205
|
.mockReturnValue(createMockStreamState({ data: initialValue }));
|
|
200
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
206
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("data", initialValue));
|
|
201
207
|
const newValue = { name: "updated", items: [4, 5, 6] };
|
|
202
208
|
(0, react_1.act)(() => {
|
|
203
209
|
result.current[1](newValue);
|
|
@@ -208,7 +214,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
208
214
|
describe("Metadata", () => {
|
|
209
215
|
it("should return isPending and error in meta", () => {
|
|
210
216
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
211
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
217
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
212
218
|
expect(result.current[2]).toEqual({
|
|
213
219
|
isPending: false,
|
|
214
220
|
error: null,
|
|
@@ -221,7 +227,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
221
227
|
mockDebouncedFn.flush = mockFlush;
|
|
222
228
|
jest.mocked(use_debounce_1.useDebouncedCallback).mockReturnValue(mockDebouncedFn);
|
|
223
229
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
224
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
230
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
225
231
|
(0, react_1.act)(() => {
|
|
226
232
|
result.current[2].flush();
|
|
227
233
|
});
|
|
@@ -231,13 +237,13 @@ describe("useTamboV1ComponentState", () => {
|
|
|
231
237
|
describe("Debouncing Behavior", () => {
|
|
232
238
|
it("should use default debounce time of 500ms", () => {
|
|
233
239
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
234
|
-
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
240
|
+
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
235
241
|
expect(use_debounce_1.useDebouncedCallback).toHaveBeenCalledWith(expect.any(Function), 500);
|
|
236
242
|
});
|
|
237
243
|
it("should use custom debounce time when provided", () => {
|
|
238
244
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
239
245
|
const customDebounceTime = 1000;
|
|
240
|
-
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
246
|
+
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial", customDebounceTime));
|
|
241
247
|
expect(use_debounce_1.useDebouncedCallback).toHaveBeenCalledWith(expect.any(Function), customDebounceTime);
|
|
242
248
|
});
|
|
243
249
|
it("should flush debounced callback on unmount", () => {
|
|
@@ -246,7 +252,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
246
252
|
mockDebouncedFn.flush = mockFlush;
|
|
247
253
|
jest.mocked(use_debounce_1.useDebouncedCallback).mockReturnValue(mockDebouncedFn);
|
|
248
254
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
249
|
-
const { unmount } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
255
|
+
const { unmount } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
250
256
|
unmount();
|
|
251
257
|
expect(mockFlush).toHaveBeenCalled();
|
|
252
258
|
});
|
|
@@ -255,7 +261,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
255
261
|
it("should sync with server state changes from streaming", () => {
|
|
256
262
|
const streamState = createMockStreamState({ testKey: "initial" });
|
|
257
263
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(streamState);
|
|
258
|
-
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
264
|
+
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
259
265
|
expect(result.current[0]).toBe("initial");
|
|
260
266
|
// Simulate server state change from streaming
|
|
261
267
|
const updatedStreamState = createMockStreamState({
|
|
@@ -271,7 +277,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
271
277
|
threadMap: {},
|
|
272
278
|
currentThreadId: "placeholder",
|
|
273
279
|
});
|
|
274
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
280
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "default"));
|
|
275
281
|
expect(result.current[0]).toBe("default");
|
|
276
282
|
});
|
|
277
283
|
});
|
|
@@ -290,7 +296,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
290
296
|
});
|
|
291
297
|
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue(createMockStreamState({}));
|
|
292
298
|
const consoleSpy = jest.spyOn(console, "error").mockImplementation();
|
|
293
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
299
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
294
300
|
await (0, react_1.act)(async () => {
|
|
295
301
|
result.current[1]("new-value");
|
|
296
302
|
// Wait for async operations
|
|
@@ -301,20 +307,39 @@ describe("useTamboV1ComponentState", () => {
|
|
|
301
307
|
});
|
|
302
308
|
});
|
|
303
309
|
describe("Context Requirements", () => {
|
|
304
|
-
it("should
|
|
305
|
-
jest.mocked(component_renderer_1.
|
|
306
|
-
|
|
310
|
+
it("should act as plain useState when component content context is missing", () => {
|
|
311
|
+
jest.mocked(component_renderer_1.useComponentContentOptional).mockReturnValue(null);
|
|
312
|
+
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue({
|
|
313
|
+
threadMap: {},
|
|
314
|
+
currentThreadId: "",
|
|
315
|
+
});
|
|
316
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
317
|
+
expect(result.current[0]).toBe("initial");
|
|
318
|
+
// No side effects when context is missing
|
|
319
|
+
expect(mockSetInteractableState).not.toHaveBeenCalled();
|
|
320
|
+
expect(mockUpdateState).not.toHaveBeenCalled();
|
|
321
|
+
});
|
|
322
|
+
it("should not trigger side effects on setState when context is missing", () => {
|
|
323
|
+
jest.mocked(component_renderer_1.useComponentContentOptional).mockReturnValue(null);
|
|
324
|
+
jest.mocked(tambo_v1_stream_context_1.useStreamState).mockReturnValue({
|
|
325
|
+
threadMap: {},
|
|
326
|
+
currentThreadId: "",
|
|
307
327
|
});
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
328
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("testKey", "initial"));
|
|
329
|
+
(0, react_1.act)(() => {
|
|
330
|
+
result.current[1]("updated");
|
|
331
|
+
});
|
|
332
|
+
// Local state updates, but no server sync or interactable writes
|
|
333
|
+
expect(result.current[0]).toBe("updated");
|
|
334
|
+
expect(mockSetInteractableState).not.toHaveBeenCalled();
|
|
335
|
+
expect(mockUpdateState).not.toHaveBeenCalled();
|
|
311
336
|
});
|
|
312
337
|
});
|
|
313
338
|
describe("Interactable Component Support", () => {
|
|
314
339
|
const interactableComponentId = "MyWidget-abc";
|
|
315
340
|
beforeEach(() => {
|
|
316
341
|
// Simulate interactable context: threadId="" signals interactable
|
|
317
|
-
jest.mocked(component_renderer_1.
|
|
342
|
+
jest.mocked(component_renderer_1.useComponentContentOptional).mockReturnValue({
|
|
318
343
|
componentId: interactableComponentId,
|
|
319
344
|
threadId: "",
|
|
320
345
|
messageId: "",
|
|
@@ -328,17 +353,17 @@ describe("useTamboV1ComponentState", () => {
|
|
|
328
353
|
});
|
|
329
354
|
it("should initialize with initialValue when no interactable state exists", () => {
|
|
330
355
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
331
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
356
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 42));
|
|
332
357
|
expect(result.current[0]).toBe(42);
|
|
333
358
|
});
|
|
334
359
|
it("should initialize from interactable state when it exists", () => {
|
|
335
360
|
mockGetInteractableComponentState.mockReturnValue({ count: 99 });
|
|
336
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
361
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
337
362
|
expect(result.current[0]).toBe(99);
|
|
338
363
|
});
|
|
339
364
|
it("should call setInteractableState when setState is called", () => {
|
|
340
365
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
341
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
366
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
342
367
|
(0, react_1.act)(() => {
|
|
343
368
|
result.current[1](10);
|
|
344
369
|
});
|
|
@@ -346,7 +371,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
346
371
|
});
|
|
347
372
|
it("should NOT call client.threads.state.updateState for interactable components", () => {
|
|
348
373
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
349
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
374
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
350
375
|
(0, react_1.act)(() => {
|
|
351
376
|
result.current[1](10);
|
|
352
377
|
});
|
|
@@ -354,7 +379,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
354
379
|
});
|
|
355
380
|
it("should sync from interactable provider when state changes externally", () => {
|
|
356
381
|
mockGetInteractableComponentState.mockReturnValue({ count: 0 });
|
|
357
|
-
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
382
|
+
const { result, rerender } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
358
383
|
expect(result.current[0]).toBe(0);
|
|
359
384
|
// Simulate external state change (e.g., AI tool call)
|
|
360
385
|
mockGetInteractableComponentState.mockReturnValue({ count: 77 });
|
|
@@ -363,18 +388,18 @@ describe("useTamboV1ComponentState", () => {
|
|
|
363
388
|
});
|
|
364
389
|
it("should have isPending as false in interactable context", () => {
|
|
365
390
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
366
|
-
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
391
|
+
const { result } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
367
392
|
expect(result.current[2].isPending).toBe(false);
|
|
368
393
|
expect(result.current[2].error).toBeNull();
|
|
369
394
|
});
|
|
370
395
|
it("should set initial value in interactable state on mount when no existing state", () => {
|
|
371
396
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
372
|
-
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
397
|
+
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 42));
|
|
373
398
|
expect(mockSetInteractableState).toHaveBeenCalledWith(interactableComponentId, "count", 42);
|
|
374
399
|
});
|
|
375
400
|
it("should NOT set initial value in interactable state when state already exists", () => {
|
|
376
401
|
mockGetInteractableComponentState.mockReturnValue({ count: 99 });
|
|
377
|
-
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
402
|
+
(0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 42));
|
|
378
403
|
// Should not be called because state already exists
|
|
379
404
|
expect(mockSetInteractableState).not.toHaveBeenCalled();
|
|
380
405
|
});
|
|
@@ -384,7 +409,7 @@ describe("useTamboV1ComponentState", () => {
|
|
|
384
409
|
mockDebouncedFn.flush = mockFlush;
|
|
385
410
|
jest.mocked(use_debounce_1.useDebouncedCallback).mockReturnValue(mockDebouncedFn);
|
|
386
411
|
mockGetInteractableComponentState.mockReturnValue(undefined);
|
|
387
|
-
const { unmount } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.
|
|
412
|
+
const { unmount } = (0, react_1.renderHook)(() => (0, use_tambo_v1_component_state_1.useTamboComponentState)("count", 0));
|
|
388
413
|
unmount();
|
|
389
414
|
expect(mockFlush).not.toHaveBeenCalled();
|
|
390
415
|
});
|