Pārlūkot izejas kodu

wip: desktop work

Adam 3 mēneši atpakaļ
vecāks
revīzija
3b20935959

+ 0 - 48
packages/desktop/src/components/progress-circle.tsx

@@ -1,48 +0,0 @@
-import { Component, createMemo } from "solid-js"
-
-interface ProgressCircleProps {
-  percentage: number
-  size?: number
-  strokeWidth?: number
-}
-
-export const ProgressCircle: Component<ProgressCircleProps> = (props) => {
-  // --- Set default values for props ---
-  const size = () => props.size || 16
-  const strokeWidth = () => props.strokeWidth || 3
-
-  // --- Constants for SVG calculation ---
-  const viewBoxSize = 16
-  const center = viewBoxSize / 2
-  const radius = () => center - strokeWidth() / 2
-  const circumference = createMemo(() => 2 * Math.PI * radius())
-
-  // --- Reactive Calculation for the progress offset ---
-  const offset = createMemo(() => {
-    const clampedPercentage = Math.max(0, Math.min(100, props.percentage || 0))
-    const progress = clampedPercentage / 100
-    return circumference() * (1 - progress)
-  })
-
-  return (
-    <svg
-      width={size()}
-      height={size()}
-      viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
-      fill="none"
-      class="transform -rotate-90"
-    >
-      <circle cx={center} cy={center} r={radius()} class="stroke-border-weak-base" stroke-width={strokeWidth()} />
-      <circle
-        cx={center}
-        cy={center}
-        r={radius()}
-        class="stroke-border-active"
-        stroke-width={strokeWidth()}
-        stroke-dasharray={circumference().toString()}
-        stroke-dashoffset={offset()}
-        style={{ transition: "stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1)" }}
-      />
-    </svg>
-  )
-}

+ 2 - 2
packages/desktop/src/pages/index.tsx

@@ -10,6 +10,8 @@ import {
   Diff,
   Collapsible,
   Part,
+  DiffChanges,
+  ProgressCircle,
 } from "@opencode-ai/ui"
 import { FileIcon } from "@/ui"
 import FileTree from "@/components/file-tree"
@@ -33,10 +35,8 @@ import type { JSX } from "solid-js"
 import { Code } from "@/components/code"
 import { useSync } from "@/context/sync"
 import { useSDK } from "@/context/sdk"
-import { ProgressCircle } from "@/components/progress-circle"
 import { Message } from "@/components/message"
 import { type AssistantMessage as AssistantMessageType } from "@opencode-ai/sdk"
-import { DiffChanges } from "@opencode-ai/ui"
 import { Markdown } from "@/components/markdown"
 
 export default function Page() {

+ 1 - 0
packages/ui/src/components/index.ts

@@ -11,6 +11,7 @@ export * from "./input"
 export * from "./fonts"
 export * from "./list"
 export * from "./message-part"
+export * from "./progress-circle"
 export * from "./select"
 export * from "./select-dialog"
 export * from "./tabs"

+ 12 - 0
packages/ui/src/components/progress-circle.css

@@ -0,0 +1,12 @@
+[data-component="progress-circle"] {
+  transform: rotate(-90deg);
+
+  [data-slot="background"] {
+    stroke: var(--border-weak-base);
+  }
+
+  [data-slot="progress"] {
+    stroke: var(--border-active);
+    transition: stroke-dashoffset 0.35s cubic-bezier(0.65, 0, 0.35, 1);
+  }
+}

+ 63 - 0
packages/ui/src/components/progress-circle.tsx

@@ -0,0 +1,63 @@
+import { type ComponentProps, createMemo, splitProps } from "solid-js"
+
+export interface ProgressCircleProps extends Pick<ComponentProps<"svg">, "class" | "classList"> {
+  percentage: number
+  size?: number
+  strokeWidth?: number
+}
+
+export function ProgressCircle(props: ProgressCircleProps) {
+  const [split, rest] = splitProps(props, [
+    "percentage",
+    "size",
+    "strokeWidth",
+    "class",
+    "classList",
+  ])
+
+  const size = () => split.size || 16
+  const strokeWidth = () => split.strokeWidth || 3
+
+  const viewBoxSize = 16
+  const center = viewBoxSize / 2
+  const radius = () => center - strokeWidth() / 2
+  const circumference = createMemo(() => 2 * Math.PI * radius())
+
+  const offset = createMemo(() => {
+    const clampedPercentage = Math.max(0, Math.min(100, split.percentage || 0))
+    const progress = clampedPercentage / 100
+    return circumference() * (1 - progress)
+  })
+
+  return (
+    <svg
+      {...rest}
+      width={size()}
+      height={size()}
+      viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
+      fill="none"
+      data-component="progress-circle"
+      classList={{
+        ...(split.classList ?? {}),
+        [split.class ?? ""]: !!split.class,
+      }}
+    >
+      <circle
+        cx={center}
+        cy={center}
+        r={radius()}
+        data-slot="background"
+        stroke-width={strokeWidth()}
+      />
+      <circle
+        cx={center}
+        cy={center}
+        r={radius()}
+        data-slot="progress"
+        stroke-width={strokeWidth()}
+        stroke-dasharray={circumference().toString()}
+        stroke-dashoffset={offset()}
+      />
+    </svg>
+  )
+}

+ 1 - 0
packages/ui/src/styles/index.css

@@ -17,6 +17,7 @@
 @import "../components/input.css" layer(components);
 @import "../components/list.css" layer(components);
 @import "../components/message-part.css" layer(components);
+@import "../components/progress-circle.css" layer(components);
 @import "../components/select.css" layer(components);
 @import "../components/select-dialog.css" layer(components);
 @import "../components/tabs.css" layer(components);