Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify contexts 4 #6

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/css/Assistant.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,20 @@
bottom: 1rem;
right: 1rem;
z-index: 30;
line-height: 1.5;
-webkit-text-size-adjust: 100%;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-feature-settings: normal;
font-variation-settings: normal;
touch-action: manipulation;
}

.beakAssistantWindow svg {
display: inline-block;
vertical-align: middle;
}
18 changes: 0 additions & 18 deletions packages/css/Theme.css

This file was deleted.

34 changes: 27 additions & 7 deletions packages/react/src/Assistant.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React, { useCallback, useEffect, useMemo } from "react";
import { useBeakContext } from "./Beak";
import {
BeakColorScheme,
BeakContext,
BeakIcons,
useBeakContext,
} from "./Beak";
import { Message } from "@beakjs/core";
import { ColorScheme, Icons, Theme } from "./Theme";
import {
ButtonProps,
HeaderProps,
Expand All @@ -21,8 +25,8 @@ interface AssistantWindowProps {
clickOutsideToClose?: boolean;
hitEscapeToClose?: boolean;
hotkey?: string;
icons?: Required<Icons>;
colorScheme?: ColorScheme;
icons?: BeakIcons;
colorScheme?: BeakColorScheme;
Window?: React.ComponentType<WindowProps>;
Button?: React.ComponentType<ButtonProps>;
Header?: React.ComponentType<HeaderProps>;
Expand Down Expand Up @@ -68,9 +72,25 @@ export const AssistantWindow: React.FC<AssistantWindowProps> = ({
await beak.runChatCompletion(message);
};

const ctx = useMemo(() => {
return {
...context,
icons: {
...context.icons,
...icons,
},
colorScheme: colorScheme || context.colorScheme,
};
}, [context, icons, colorScheme]);

const colorSchemeClass =
"beakColorScheme" +
ctx.colorScheme[0].toUpperCase() +
ctx.colorScheme.slice(1);

return (
<Theme colorScheme={colorScheme} icons={icons || {}}>
<div className="beakAssistantWindow">
<BeakContext.Provider value={ctx}>
<div className={`beakAssistantWindow ${colorSchemeClass}`}>
<Button open={open} setOpen={setOpen}></Button>
<Window
open={open}
Expand All @@ -84,7 +104,7 @@ export const AssistantWindow: React.FC<AssistantWindowProps> = ({
<Input inProgress={inProgress} onSend={sendMessage} />
</Window>
</div>
</Theme>
</BeakContext.Provider>
);
};

Expand Down
31 changes: 24 additions & 7 deletions packages/react/src/Beak.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import React, { useMemo } from "react";
import { BeakCore, OpenAIModel, DebugLogger } from "@beakjs/core";
import * as DefaultIcons from "./Icons";

const DEFAULT_DEBUG_LOGGER = new DebugLogger([]);

export type BeakColorScheme = "auto" | "light" | "dark";

export interface BeakIcons {
openIcon?: React.ReactNode;
closeIcon?: React.ReactNode;
headerCloseIcon?: React.ReactNode;
sendIcon?: React.ReactNode;
activityIcon?: React.ReactNode;
spinnerIcon?: React.ReactNode;
}

interface BeakLabels {
initial?: string | string[];
title?: string;
Expand All @@ -15,8 +27,9 @@ interface BeakLabels {
interface BeakContext {
beak: BeakCore;
labels: Required<BeakLabels>;
icons: Required<BeakIcons>;
colorScheme: BeakColorScheme;
debugLogger: DebugLogger;
theme: BeakTheme;
}

export const BeakContext = React.createContext<BeakContext | undefined>(
Expand All @@ -33,8 +46,6 @@ export function useBeakContext(): BeakContext {
return context;
}

type BeakTheme = "auto" | "light" | "dark";

interface BeakProps {
openAIApiKey: string;
openAIModel?: OpenAIModel;
Expand All @@ -43,7 +54,6 @@ interface BeakProps {
maxFeedback?: number;
labels?: BeakLabels;
debugLogger?: DebugLogger;
theme?: BeakTheme;
children?: React.ReactNode;
}

Expand All @@ -55,7 +65,6 @@ export const Beak: React.FC<BeakProps> = ({
maxFeedback,
labels,
debugLogger,
theme,
children,
}) => {
const beak = useMemo(
Expand Down Expand Up @@ -93,9 +102,17 @@ export const Beak: React.FC<BeakProps> = ({
},

debugLogger: debugLogger || DEFAULT_DEBUG_LOGGER,
theme: theme || "auto",
colorScheme: "auto" as BeakColorScheme,
icons: {
openIcon: DefaultIcons.OpenIcon,
closeIcon: DefaultIcons.CloseIcon,
headerCloseIcon: DefaultIcons.HeaderCloseIcon,
sendIcon: DefaultIcons.SendIcon,
activityIcon: DefaultIcons.ActivityIcon,
spinnerIcon: DefaultIcons.SpinnerIcon,
},
}),
[labels, debugLogger, theme]
[labels, debugLogger]
);
return (
<BeakContext.Provider value={context}>{children}</BeakContext.Provider>
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react";
import { ButtonProps } from "./props";
import { useBeakContext } from "./Beak";
import "../../css/Button.css";
import { useBeakThemeContext } from "./Theme";

export const Button: React.FC<ButtonProps> = ({ open, setOpen }) => {
const context = useBeakThemeContext();
const context = useBeakContext();
// To ensure that the mouse handler fires even when the button is scaled down
// we wrap the button in a div and attach the handler to the div
return (
Expand Down
4 changes: 1 addition & 3 deletions packages/react/src/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React from "react";
import { HeaderProps } from "./props";
import "../../css/Header.css";
import { useBeakThemeContext } from "./Theme";
import { useBeakContext } from "./Beak";

export const Header: React.FC<HeaderProps> = ({ setOpen }) => {
const context = useBeakContext();
const themeContext = useBeakThemeContext();

return (
<div className="beakHeader">
<div>{context.labels.title}</div>
<button onClick={() => setOpen(false)} aria-label="Close">
{themeContext.icons.headerCloseIcon}
{context.icons.headerCloseIcon}
</button>
</div>
);
Expand Down
6 changes: 1 addition & 5 deletions packages/react/src/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import React, { useRef, useState } from "react";
import TextareaAutosize from "react-textarea-autosize";
import { InputProps } from "./props";
import { useBeakContext } from "./Beak";
import { useBeakThemeContext } from "./Theme";
import "../../css/Input.css";

export const Input: React.FC<InputProps> = ({ inProgress, onSend }) => {
const context = useBeakContext();
const themeContext = useBeakThemeContext();
const textareaRef = useRef<HTMLTextAreaElement>(null);

const handleDivClick = (event: React.MouseEvent<HTMLDivElement>) => {
Expand All @@ -26,9 +24,7 @@ export const Input: React.FC<InputProps> = ({ inProgress, onSend }) => {
textareaRef.current?.focus();
};

const icon = inProgress
? themeContext.icons.activityIcon
: themeContext.icons.sendIcon;
const icon = inProgress ? context.icons.activityIcon : context.icons.sendIcon;
const disabled = inProgress || text.length === 0;

return (
Expand Down
6 changes: 2 additions & 4 deletions packages/react/src/Messages.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React, { useEffect } from "react";
import { MessagesProps } from "./props";
import { useBeakContext } from "./Beak";
import { useBeakThemeContext } from "./Theme";
import "../../css/Messages.css";

export const Messages: React.FC<MessagesProps> = ({ messages }) => {
const context = useBeakContext();
const themeContext = useBeakThemeContext();
const messagesEndRef = React.useRef<HTMLDivElement>(null);

const scrollToBottom = () => {
Expand Down Expand Up @@ -34,13 +32,13 @@ export const Messages: React.FC<MessagesProps> = ({ messages }) => {
if (message.status === "pending" && !message.content) {
return (
<div key={index} className={`beakMessage beakAssistantMessage`}>
{themeContext.icons.spinnerIcon}
{context.icons.spinnerIcon}
</div>
);
} else if (message.status === "partial") {
return (
<div key={index} className={`beakMessage beakAssistantMessage`}>
{context.labels.thinking} {themeContext.icons.spinnerIcon}
{context.labels.thinking} {context.icons.spinnerIcon}
</div>
);
} else if (message.content) {
Expand Down
72 changes: 0 additions & 72 deletions packages/react/src/Theme.tsx

This file was deleted.