1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
3import React, { useEffect, useRef, useState } from "https://esm.sh/react@18.2.0";
4import { Message } from "./App.tsx";
5
8}
9
10const ShadowDomWrapper: React.FC<ShadowDomWrapperProps> = ({ html }) => {
11 const containerRef = useRef<HTMLDivElement>(null);
12 const shadowRef = useRef<ShadowRoot | null>(null);
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import Anthropic, { MessageStreamEvent } from "https://esm.sh/@anthropic-ai/sdk";
3import React from "https://esm.sh/react@18.2.0";
4
5// External shared types
82
83export default function useAnthropicStream(config: AppConfig) {
84 const [status, setStatus] = React.useState<Status>("idle");
85 const [liveBlocks, setLiveBlocks] = React.useState<any[] | null>(null);
86 const abortRef = React.useRef<AbortController | null>(null);
87
88 /* Anthropic SDK instance – memoised so we don't recreate each render */
89 const anthropic = React.useMemo(() => {
90 if (!config.anthropicApiKey) return null;
91 return new Anthropic({
102
103 /* Abort helper */
104 const abort = React.useCallback(() => {
105 abortRef.current?.abort();
106 abortRef.current = null;
110
111 /* Main send/stream function – identical public contract */
112 const send = React.useCallback(
113 async (history: Message[], userText: string): Promise<AssistantMsg> => {
114 if (!anthropic) throw new Error("API key missing");
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3import React, {
4 useCallback,
5 useEffect,
6 useMemo,
7 useState,
8} from "https://esm.sh/react@18.2.0";
9import { formatTime, formatMinutes } from "../../shared/utils.ts";
10import type { SessionStats, TimerState } from "../../shared/types.ts";
19interface TimerContainerProps {
20 state: TimerState;
21 setState: React.Dispatch<React.SetStateAction<TimerState>>;
22 showNotification: (
23 message: string,
26}
27
28export const TimerContainer = React.memo(function TimerContainer({
29 state,
30 setState,
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3interface StatItem {
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3import type { SessionStats } from "../../shared/types.ts";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3import React from "https://esm.sh/react@18.2.0";
4import { Card } from "./Card.tsx";
5import { Link } from "./Link.tsx";
6
7const ListItem = ({ children }: { children: React.ReactNode }) => (
8 <li className="pl-1">{children}</li>
9);
10
11export const HelpText = React.memo(function HelpText() {
12 return (
13 <Card>
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2
3import React from "https://esm.sh/react@18.2.0";
4import { Link } from "./Link.tsx";
5
6export const SOURCE_URL = "https://val.town/x/nbbaier/thirdTimer";
7
8export const Footer = React.memo(function Footer() {
9 return (
10 <footer className="flex gap-2 items-center p-4 mx-auto my-0 max-w-5xl text-xs">
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3interface CardProps {
4 children: React.ReactNode;
5 className?: string;
6}
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3interface ButtonProps {
4 children: React.ReactNode;
5 onClick: () => void;
6 variant?:
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3import React from "https://esm.sh/react@18.2.0";
4import type { BreakFraction } from "../../shared/types.ts";
5import { Card, CardHeader } from "./Card.tsx";
19}
20
21export const BreakFractionSettings = React.memo(function BreakFractionSettings({
22 currentBreakFraction,
23 onBreakFractionChange,