mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
merge main
This commit is contained in:
commit
9b2a7de8f2
@ -14,7 +14,7 @@ const config: StorybookConfig = {
|
||||
"./custom-addons/theme/register",
|
||||
],
|
||||
|
||||
core: {},
|
||||
core: { builder: "@storybook/builder-vite" },
|
||||
|
||||
framework: {
|
||||
name: "@storybook/react-vite",
|
||||
@ -58,6 +58,7 @@ const config: StorybookConfig = {
|
||||
<link rel="stylesheet" href="./fontawesome/css/solid.min.css" />
|
||||
<link rel="stylesheet" href="./fontawesome/css/sharp-solid.min.css" />
|
||||
<link rel="stylesheet" href="./fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="./fontawesome/css/custom-icons.min.css" />
|
||||
<style>
|
||||
#storybook-docs {
|
||||
[id^="anchor--"],
|
||||
|
@ -9,7 +9,6 @@ import "../frontend/app/reset.scss";
|
||||
import "./global.css";
|
||||
import { light, dark } from "./theme";
|
||||
import { DocsContainer } from "@storybook/addon-docs";
|
||||
|
||||
import { addons } from "@storybook/preview-api";
|
||||
import { DARK_MODE_EVENT_NAME } from "storybook-dark-mode";
|
||||
|
||||
|
@ -18,7 +18,7 @@ Wave is an open-source terminal that can launch graphical widgets, controlled an
|
||||
|
||||
Wave isn't just another terminal emulator; it's a rethink on how terminals are built. For too long there has been a disconnect between the CLI and the web. If you want fast, keyboard-accessible, easy-to-write applications, you use the CLI, but if you want graphical interfaces, native widgets, copy/paste, scrolling, variable font sizes, then you'd have to turn to the web. Wave's goal is to bridge that gap.
|
||||
|
||||
![WaveTerm Screenshot](./assets/wave-screenshot.png)
|
||||
![WaveTerm Screenshot](./assets/wave-screenshot.webp)
|
||||
|
||||
## Installation
|
||||
|
||||
|
@ -120,6 +120,7 @@ tasks:
|
||||
sources:
|
||||
- "cmd/server/*.go"
|
||||
- "pkg/**/*.go"
|
||||
- "pkg/**/*.json"
|
||||
generates:
|
||||
- dist/bin/wavesrv.*
|
||||
|
||||
|
28
assets/wave-logo_icon-black.svg
Normal file
28
assets/wave-logo_icon-black.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:url(#SVGID_00000123405442604648655120000000636425700907447225_);}
|
||||
.st2{fill:#FFFFFF;}
|
||||
.st3{fill:#58C142;}
|
||||
.st4{fill:url(#SVGID_00000100361222533905006500000012948355425597525920_);}
|
||||
.st5{fill:url(#SVGID_00000039098984540155201650000005728924474174226367_);}
|
||||
.st6{fill:url(#SVGID_00000065066116668922763670000009055193333651929737_);}
|
||||
.st7{fill:url(#SVGID_00000046310373342220590360000000833566212213317053_);}
|
||||
.st8{fill:url(#SVGID_00000067914870925445215340000010520730682335284873_);}
|
||||
.st9{fill:url(#SVGID_00000139972009352615321800000011748188400644384138_);}
|
||||
.st10{fill:url(#SVGID_00000137813723102203423940000002281677718566419372_);}
|
||||
.st11{fill:url(#SVGID_00000117658585713214366330000001759073570098750902_);}
|
||||
.st12{fill:url(#SVGID_00000075146307645666362690000001517567647835044244_);}
|
||||
.st13{fill:url(#SVGID_00000169553343881037582000000012883033354483876241_);}
|
||||
</style>
|
||||
<g>
|
||||
<path d="M218.2,133.2c51,0,99.3,21.9,138.2,39.5c21.2,9.6,43.1,19.5,53.4,19.5c8,0,21.5,0,30.5-42.1l4.6-21.3l21.6,3.1l66.7,9.6
|
||||
c11.2-27.9,18.8-61.6,22.9-101.2L426.4,21.7c-8.6,40.3-24.5,60.5-53.3,60.5c-37.4,0-113.8-59.1-191.6-59.1
|
||||
C76.4,23.1,23.2,89.4,7.3,226.2l46,6.7c7.6-15.6,16.4-29.3,26.4-41.2C112.6,152.9,159.2,133.2,218.2,133.2z"/>
|
||||
<path d="M409.8,215.6c-37.4,0-113.8-59.1-191.6-59.1c-105.1,0-158.4,66.3-174.3,203.1l129.6,18.7c8.7-41.8,24.5-60.5,53.3-60.5
|
||||
c38.9,0,112.3,59.1,191.6,59.1c105.1,0,159.9-66.3,174.3-203.1l-129.6-18.7C454.4,195.4,438.6,215.6,409.8,215.6z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 438 KiB |
BIN
assets/wave-screenshot.webp
Normal file
BIN
assets/wave-screenshot.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 211 KiB |
@ -34,6 +34,7 @@ var editCmd = &cobra.Command{
|
||||
func init() {
|
||||
viewCmd.Flags().BoolVarP(&viewMagnified, "magnified", "m", false, "open view in magnified mode")
|
||||
rootCmd.AddCommand(viewCmd)
|
||||
editCmd.Flags().BoolVarP(&viewMagnified, "magnified", "m", false, "open view in magnified mode")
|
||||
rootCmd.AddCommand(editCmd)
|
||||
}
|
||||
|
||||
|
177
docs/docs/ai-presets.mdx
Normal file
177
docs/docs/ai-presets.mdx
Normal file
@ -0,0 +1,177 @@
|
||||
---
|
||||
sidebar_position: 3.6
|
||||
id: "ai-presets"
|
||||
title: "AI Presets"
|
||||
---
|
||||
|
||||
<img
|
||||
title="AI Presets Menu"
|
||||
style={{ float: "right", margin: "0 0 10px 10px" }}
|
||||
src="./img/ai-presets.png"
|
||||
width="300"
|
||||
/>
|
||||
|
||||
Wave's AI widget can be configured to work with various AI providers and models through presets. Presets allow you to define multiple AI configurations and easily switch between them using the dropdown menu in the AI widget.
|
||||
|
||||
## How AI Presets Work
|
||||
|
||||
AI presets are defined in `~/.config/waveterm/presets/ai.json`. You can easily edit this file using:
|
||||
|
||||
```bash
|
||||
wsh editconfig presets/ai.json
|
||||
```
|
||||
|
||||
Each preset defines a complete set of configuration values for the AI widget. When you select a preset from the dropdown menu, those configuration values are applied to the widget. If no preset is selected, the widget uses the default values from `settings.json`.
|
||||
|
||||
Here's a basic example using Claude:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@claude-sonnet": {
|
||||
"display:name": "Claude 3 Sonnet",
|
||||
"display:order": 1,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "anthropic",
|
||||
"ai:model": "claude-3-5-sonnet-latest",
|
||||
"ai:apitoken": "<your anthropic API key>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To make a preset your default, add this single line to your `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai:preset": "ai@claude-sonnet"
|
||||
}
|
||||
```
|
||||
|
||||
:::info
|
||||
You can quickly set your default preset using the `setconfig` command:
|
||||
|
||||
```bash
|
||||
wsh setconfig ai:preset=ai@claude-sonnet
|
||||
```
|
||||
|
||||
This is easier than editing settings.json directly!
|
||||
:::
|
||||
|
||||
## Provider-Specific Configurations
|
||||
|
||||
### Anthropic (Claude)
|
||||
|
||||
To use Claude models, create a preset like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@claude-sonnet": {
|
||||
"display:name": "Claude 3 Sonnet",
|
||||
"display:order": 1,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "anthropic",
|
||||
"ai:model": "claude-3-5-sonnet-latest",
|
||||
"ai:apitoken": "<your anthropic API key>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Local LLMs (Ollama)
|
||||
|
||||
To connect to a local Ollama instance:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@ollama-llama": {
|
||||
"display:name": "Ollama - Llama2",
|
||||
"display:order": 2,
|
||||
"ai:*": true,
|
||||
"ai:baseurl": "http://localhost:11434/v1",
|
||||
"ai:name": "llama2",
|
||||
"ai:model": "llama2",
|
||||
"ai:apitoken": "ollama"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: The `ai:apitoken` is required but can be any value as Ollama ignores it. See [Ollama OpenAI compatibility docs](https://github.com/ollama/ollama/blob/main/docs/openai.md) for more details.
|
||||
|
||||
### Azure OpenAI
|
||||
|
||||
To connect to Azure AI services:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@azure-gpt4": {
|
||||
"display:name": "Azure GPT-4",
|
||||
"display:order": 3,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "azure",
|
||||
"ai:baseurl": "<your Azure AI base URL>",
|
||||
"ai:model": "<your model deployment name>",
|
||||
"ai:apitoken": "<your Azure API key>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: Do not include query parameters or `api-version` in the `ai:baseurl`. The `ai:model` should be your model deployment name in Azure.
|
||||
|
||||
### Perplexity
|
||||
|
||||
To use Perplexity's models:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@perplexity-sonar": {
|
||||
"display:name": "Perplexity Sonar",
|
||||
"display:order": 4,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "perplexity",
|
||||
"ai:model": "llama-3.1-sonar-small-128k-online",
|
||||
"ai:apitoken": "<your perplexity API key>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple Presets Example
|
||||
|
||||
You can define multiple presets in your `ai.json` file:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@claude-sonnet": {
|
||||
"display:name": "Claude 3 Sonnet",
|
||||
"display:order": 1,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "anthropic",
|
||||
"ai:model": "claude-3-5-sonnet-latest",
|
||||
"ai:apitoken": "<your anthropic API key>"
|
||||
},
|
||||
"ai@ollama-llama": {
|
||||
"display:name": "Ollama - Llama2",
|
||||
"display:order": 2,
|
||||
"ai:*": true,
|
||||
"ai:baseurl": "http://localhost:11434/v1",
|
||||
"ai:name": "llama2",
|
||||
"ai:model": "llama2",
|
||||
"ai:apitoken": "ollama"
|
||||
},
|
||||
"ai@perplexity-sonar": {
|
||||
"display:name": "Perplexity Sonar",
|
||||
"display:order": 3,
|
||||
"ai:*": true,
|
||||
"ai:apitype": "perplexity",
|
||||
"ai:model": "llama-3.1-sonar-small-128k-online",
|
||||
"ai:apitoken": "<your perplexity API key>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `display:order` value determines the order in which presets appear in the dropdown menu.
|
||||
|
||||
Remember to set your default preset in `settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai:preset": "ai@claude-sonnet"
|
||||
}
|
||||
```
|
@ -54,6 +54,7 @@ wsh editconfig
|
||||
| autoupdate:intervalms | float64 | time in milliseconds to wait between update checks (requires app restart) |
|
||||
| autoupdate:installonquit | bool | whether to automatically install updates on quit (requires app restart) |
|
||||
| autoupdate:channel | string | the auto update channel "latest" (stable builds), or "beta" (updated more frequently) (requires app restart) |
|
||||
| tab:preset | string | a "bg@" preset to automatically apply to new tabs. e.g. `bg@green`. should match the preset key |
|
||||
| widget:showhelp | bool | whether to show help/tips widgets in right sidebar |
|
||||
| window:transparent | bool | set to true to enable window transparency (cannot be combined with `window:blur`) (macOS and Windows only, requires app restart, see [note on Windows compatibility](https://www.electronjs.org/docs/latest/tutorial/window-customization#limitations)) |
|
||||
| window:blur | bool | set to enable window background blurring (cannot be combined with `window:transparent`) (macOS and Windows only, requires app restart, see [note on Windows compatibility](https://www.electronjs.org/docs/latest/tutorial/window-customization#limitations)) |
|
||||
|
@ -16,7 +16,7 @@ The easiest way to access connections is to click the <i className="fa-sharp fa-
|
||||
|
||||
## What are wsh Shell Extensions?
|
||||
|
||||
`wsh` is a small program that helps manage waveterm regardless of which machine you are currently connected to. It is always included on your host machine, but you also have the option to install it when connecting to a remote machine. If it is installed on the remote machine, it is installed at `~/.waveterm/bin/wsh`. Then, when wave connects to your connection (and only when wave connects to your connection), `~/.waveterm/bin` is added to your `PATH` for that individual session. For more info on what `wsh` is capable of, see [wsh command](/wsh). And if you wish to view the source code of `wsh`, you can find it [here](https://github.com/wavetermdev/waveterm/tree/main/cmd/wsh).
|
||||
`wsh` is a small program that helps manage waveterm regardless of which machine you are currently connected to. It is always included on your host machine, but you also have the option to install it when connecting to a remote machine. If it is installed on the remote machine, it is installed at `~/.waveterm/bin/wsh`. Then, when wave connects to your connection (and only when wave connects to your connection), `~/.waveterm/bin` is added to your `PATH` for that individual session. If this fails for some reason, Wave will attempt to run without wsh. You will see this indicated by a small **<code><i className="fa-link-slash fa-solid fa-sharp"/></code>** icon in the block header. For more info on what `wsh` is capable of, see [wsh command](/wsh). And if you wish to view the source code of `wsh`, you can find it [here](https://github.com/wavetermdev/waveterm/tree/main/cmd/wsh).
|
||||
|
||||
With `wsh` installed, you have the ability to view certain widgets from the remote machine as if it were your host. In addition, `wsh` can be used to influence the widgets across various machines. As a very simple example, you can close a widget on the host machine by using the `wsh` command in a terminal window on a remote machine. For more information on what you can accomplish with `wsh`, take a look [here](/wsh).
|
||||
|
||||
|
@ -38,6 +38,8 @@ in the [default termthemes.json file](https://github.com/wavetermdev/waveterm/bl
|
||||
|
||||
If you add your own termthemes.json file in the config directory, you can also add your own custom terminal themes (just follow the same format).
|
||||
|
||||
You can set the key `tab:preset` in your [Wave Config File](/config) to apply a theme to all new tabs.
|
||||
|
||||
<div style={{ clear: "both" }} />
|
||||
|
||||
#### Font Size
|
||||
|
@ -126,7 +126,7 @@ Suppose I want a widget that will run speedtest-go when opened. Then, I can defi
|
||||
"view": "term",
|
||||
"controller": "cmd",
|
||||
"cmd": "speedtest-go --unix",
|
||||
"cmd:clearonstart"
|
||||
"cmd:clearonstart": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -144,13 +144,13 @@ Now suppose I wanted to run a TUI app, for instance, `dua`. Well, it turns out t
|
||||
```json
|
||||
<... other widgets go here ...>,
|
||||
"dua" : {
|
||||
"icon": "brands@linux",
|
||||
"label": "dua",
|
||||
"blockdef": {
|
||||
"meta": {
|
||||
"view": "term",
|
||||
"controller": "cmd",
|
||||
"cmd": "dua"
|
||||
"icon": "brands@linux",
|
||||
"label": "dua",
|
||||
"blockdef": {
|
||||
"meta": {
|
||||
"view": "term",
|
||||
"controller": "cmd",
|
||||
"cmd": "dua"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6,84 +6,11 @@ title: "FAQ"
|
||||
|
||||
# FAQ
|
||||
|
||||
### How do I set up my own LLM?
|
||||
### How do I configure Wave to use different AI models/providers?
|
||||
|
||||
Open your [config file](./config) in Wave using `wsh editconfig` (the config file is normally located
|
||||
at `~/.config/waveterm/settings.json`).
|
||||
Wave supports various AI providers including local LLMs (via Ollama), Azure OpenAI, Anthropic's Claude, and Perplexity. The recommended way to configure these is through AI presets, which let you set up and easily switch between different providers and models.
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| ------------ | ------ | ----------------------------------------------- |
|
||||
| ai:baseurl | string | Set the AI Base Url (must be OpenAI compatible) |
|
||||
| ai:apitoken | string | your AI api token |
|
||||
| ai:name | string | string to display in the Wave AI block header |
|
||||
| ai:model | string | model name to pass to API |
|
||||
| ai:maxtokens | int | max tokens to pass to API |
|
||||
| ai:timeoutms | int | timeout (in milliseconds) for AI calls |
|
||||
|
||||
Here's an example of pointing it to a local Ollama instance. Note that to get the text in the header of the AI block
|
||||
to update, you'll need to set the "ai:name" key. For ollama, you'll also need to provide something for the
|
||||
apitoken (even though it is ignored).
|
||||
|
||||
Here are the ollma open AI compatibility docs: https://github.com/ollama/ollama/blob/main/docs/openai.md
|
||||
|
||||
```json
|
||||
{
|
||||
"ai:*": true,
|
||||
"ai:baseurl": "http://localhost:11434/v1",
|
||||
"ai:name": "llama3.2",
|
||||
"ai:model": "llama3.2",
|
||||
"ai:apitoken": "ollama"
|
||||
}
|
||||
```
|
||||
|
||||
Note: we set the `ai:*` key to true to clear all the existing "ai" keys so this config is a clean slate.
|
||||
|
||||
To switch between multiple models, consider [adding AI Presets](./presets) instead.
|
||||
|
||||
### How can I connect to Azure AI?
|
||||
|
||||
Open your [config file](./config) in Wave using `wsh editconfig` (the config file is normally located
|
||||
at `~/.config/waveterm/settings.json`).
|
||||
|
||||
You'll need to set your `ai:baseurl` to your Azure AI Base URL (do not include query parameters or `api-version`).
|
||||
You'll also need to set `ai:apitype` to `azure`. You can then set the `ai:model`, and `ai:apitoken` appropriately
|
||||
for your setup.
|
||||
|
||||
### How can I connect to Claude?
|
||||
|
||||
Open your [config file](./config) in Wave using `wsh editconfig`.
|
||||
|
||||
Set these keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai:*": true,
|
||||
"ai:apitype": "anthropic",
|
||||
"ai:model": "claude-3-5-sonnet-latest",
|
||||
"ai:apitoken": "<your anthropic API key>"
|
||||
}
|
||||
```
|
||||
|
||||
Note: we set the `ai:*` key to true to clear all the existing "ai" keys so this config is a clean slate.
|
||||
|
||||
### How can I connect to Perplexity?
|
||||
|
||||
Open your [config file](./config) in Wave using `wsh editconfig`.
|
||||
|
||||
Set these keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai:*": true,
|
||||
"ai:apitype": "perplexity",
|
||||
"ai:model": "llama-3.1-sonar-small-128k-online",
|
||||
"ai:apitoken": "<your perplexity API key>"
|
||||
}
|
||||
```
|
||||
|
||||
Note: we set the `ai:*` key to true to clear all the existing "ai" keys so this config is a clean slate.
|
||||
|
||||
To switch between models, consider [adding AI Presets](./presets) instead.
|
||||
See our [AI Presets documentation](/ai-presets) for detailed setup instructions for each provider.
|
||||
|
||||
### How can I see the block numbers?
|
||||
|
||||
|
@ -1,127 +1,94 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
sidebar_position: 3.5
|
||||
id: "presets"
|
||||
title: "Presets"
|
||||
---
|
||||
|
||||
Presets can be used to apply multiple setting overrides at once to either a tab or a block. They are currently supported in two scenarios: tab backgrounds and AI models.
|
||||
# Presets
|
||||
|
||||
You can set presets either by placing them in `~/.config/waveterm/presets.json` or by placing them in a JSON file in the `~/.config/waveterm/presets/` directory. All presets will be aggregated regardless of which file they're placed in so you can use the `presets` directory to organize them as you see fit.
|
||||
Wave's preset system allows you to save and apply multiple configuration settings at once. Presets can be used in two different scenarios:
|
||||
|
||||
- AI models: Configure different AI providers and models (see [AI Presets](/ai-presets))
|
||||
- Tab backgrounds: Apply visual styles to your tabs
|
||||
|
||||
## Managing Presets
|
||||
|
||||
You can store presets in two locations:
|
||||
|
||||
- `~/.config/waveterm/presets.json`: Main presets file
|
||||
- `~/.config/waveterm/presets/`: Directory for organizing presets into separate files
|
||||
|
||||
All presets are aggregated regardless of which file they're in, so you can use the `presets` directory to organize them (e.g., `presets/backgrounds.json`, `presets/ai.json`).
|
||||
|
||||
:::info
|
||||
You can easily edit your presets using the built-in editor:
|
||||
|
||||
You can open up the main presets config file in Wave by running:
|
||||
|
||||
```
|
||||
wsh editconfig presets.json
|
||||
```bash
|
||||
wsh editconfig presets.json # Edit main presets file
|
||||
wsh editconfig presets/ai.json # Edit AI presets
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## File format
|
||||
## File Format
|
||||
|
||||
Presets follow the following format:
|
||||
Presets follow this format:
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"<preset-type>@<preset-key>": {
|
||||
"display:name": "<Preset name>",
|
||||
"display:order": "<number>", // optional
|
||||
"<overridden-config-key-1>": "<overridden-config-value-1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A complete example of a preset for a tab background is the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"bg@rainbow": {
|
||||
"display:name": "Rainbow",
|
||||
"display:order": 2.1,
|
||||
"bg:*": true,
|
||||
"bg": "linear-gradient( 226.4deg, rgba(255,26,1,1) 28.9%, rgba(254,155,1,1) 33%, rgba(255,241,0,1) 48.6%, rgba(34,218,1,1) 65.3%, rgba(0,141,254,1) 80.6%, rgba(113,63,254,1) 100.1% )",
|
||||
"bg:opacity": 0.3
|
||||
"<preset-type>@<preset-key>": {
|
||||
"display:name": "<Preset name>",
|
||||
"display:order": "<number>", // optional
|
||||
"<overridden-config-key-1>": "<overridden-config-value-1>"
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A complete example of a preset for an AI model is the following:
|
||||
The `preset-type` determines where the preset appears in Wave's interface:
|
||||
|
||||
```json
|
||||
{
|
||||
"ai@wave": {
|
||||
"display:name": "Ollama - llama3.1",
|
||||
"display:order": 0,
|
||||
"ai:baseurl": "http://localhost:11434",
|
||||
"ai:model": "llama3.1:latest"
|
||||
}
|
||||
}
|
||||
```
|
||||
- `ai`: Appears in the models dropdown in the "Wave AI" widget header (see [AI Presets](/ai-presets))
|
||||
- `bg`: Appears in the "Backgrounds" submenu when right-clicking a tab
|
||||
|
||||
## Preset Types
|
||||
### Common Keys
|
||||
|
||||
The type of the preset determines where it can be discovered in the app. Currently, the two types that will be discovered in the app are `bg` and `ai`.
|
||||
|
||||
`bg` will be served in the "Backgrounds" submenu of the Tab context menu (which can be found by right-clicking on a tab).
|
||||
|
||||
![screenshot showing the default options in the backgrounds submenu of the tab context menu](./img/backgrounds-menu.png)
|
||||
|
||||
`ai` will be served in the models dropdown in the block header of the "Wave AI" widget.
|
||||
|
||||
![screenshot showing the default options in the models dropdown in the block header of the "Wave AI" widget](./img/waveai-model-dropdown.png)
|
||||
|
||||
### Available configuration keys
|
||||
|
||||
The following configuration keys are available for use in presets:
|
||||
|
||||
#### Common keys
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| ------------- | ------ | ---------------------------------------------------------------------- |
|
||||
| display:name | string | the name to use when displaying the preset in a menu (required) |
|
||||
| display:order | float | the order in which the preset should be displayed in a menu (optional) |
|
||||
| Key Name | Type | Function |
|
||||
| ------------- | ------ | ----------------------------------------- |
|
||||
| display:name | string | Name shown in the UI menu (required) |
|
||||
| display:order | float | Controls the order in the menu (optional) |
|
||||
|
||||
:::info
|
||||
|
||||
Configs in a preset are applied in order to override the default config values, which will persist for the remainder of the tab or block's lifetime. Setting `bg:*` or `ai:*` to `"true"` will clear the values of any previously overridden Background or AI configurations, respectively, setting them back to their defaults. You almost always want to add these keys to your presets in order to create a clean slate and prevent previously set values from leaking in.
|
||||
|
||||
When a preset is applied, it overrides the default configuration values for that tab or block. Using `bg:*` or `ai:*` will clear any previously overridden values, setting them back to defaults. It's recommended to include these keys in your presets to ensure a clean slate.
|
||||
:::
|
||||
|
||||
## AI Configurations
|
||||
## AI Presets
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| ------------- | ------ | -------------------------------------------------------------------------------------------------- |
|
||||
| ai:\* | bool | reset all existing ai keys |
|
||||
| ai:preset | string | the default AI preset to use |
|
||||
| ai:baseurl | string | Set the AI Base Url (must be OpenAI compatible) |
|
||||
| ai:apitoken | string | your AI api token |
|
||||
| ai:apitype | string | defaults to "open_ai", but can also set to "azure" (for special Azure AI handling), or "anthropic" |
|
||||
| ai:name | string | string to display in the Wave AI block header |
|
||||
| ai:model | string | model name to pass to API |
|
||||
| ai:apiversion | string | for Azure AI only (when apitype is "azure", this will default to "2023-05-15") |
|
||||
| ai:orgid | string | |
|
||||
| ai:maxtokens | int | max tokens to pass to API |
|
||||
| ai:timeoutms | int | timeout (in milliseconds) for AI calls |
|
||||
For configuring AI providers and models, see our dedicated [AI Presets](/ai-presets) documentation. It covers setting up presets for:
|
||||
|
||||
<a name="background-configurations" />
|
||||
- Local LLMs via Ollama
|
||||
- Azure OpenAI
|
||||
- Anthropic's Claude
|
||||
- Perplexity
|
||||
- And more
|
||||
|
||||
## Background Configurations
|
||||
## Background Presets
|
||||
|
||||
Wave's background system harnesses the full power of CSS backgrounds, letting you create rich visual effects through the "background" attribute. You can apply solid colors, gradients (both linear and radial), images, and even blend multiple elements together. The system offers preset configurations while maintaining the flexibility of pure CSS, making it both powerful and easy to use.
|
||||
Wave's background system harnesses the full power of CSS backgrounds, letting you create rich visual effects through the "background" attribute. You can apply solid colors, gradients (both linear and radial), images, and even blend multiple elements together.
|
||||
|
||||
### Configuration Keys
|
||||
|
||||
| Key Name | Type | Function |
|
||||
| -------------------- | ------ | ------------------------------------------------------------------------------------------------------- |
|
||||
| bg:\* | bool | reset all existing bg keys (recommended to prevent any existing background settings from carrying over) |
|
||||
| bg:\* | bool | Reset all existing bg keys (recommended to prevent any existing background settings from carrying over) |
|
||||
| bg | string | CSS `background` attribute for the tab (supports colors, gradients images, etc.) |
|
||||
| bg:opacity | float | the opacity of the background (defaults to 0.5) |
|
||||
| bg:blendmode | string | the [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
|
||||
| bg:bordercolor | string | the color of the border when a block is not active (rarely used) |
|
||||
| bg:activebordercolor | string | the color of the border when a block is active |
|
||||
| bg:opacity | float | The opacity of the background (defaults to 0.5) |
|
||||
| bg:blendmode | string | The [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
|
||||
| bg:bordercolor | string | The color of the border when a block is not active (rarely used) |
|
||||
| bg:activebordercolor | string | The color of the border when a block is active |
|
||||
|
||||
### Simple solid color with opacity:
|
||||
### Examples
|
||||
|
||||
#### Simple solid color:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -135,7 +102,7 @@ Wave's background system harnesses the full power of CSS backgrounds, letting yo
|
||||
}
|
||||
```
|
||||
|
||||
### Complex gradient combining multiple effects:
|
||||
#### Complex gradient:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -149,24 +116,11 @@ Wave's background system harnesses the full power of CSS backgrounds, letting yo
|
||||
}
|
||||
```
|
||||
|
||||
### Repeating pattern background:
|
||||
#### Background image:
|
||||
|
||||
```json
|
||||
{
|
||||
"bg@pattern": {
|
||||
"display:name": "Diamond Pattern",
|
||||
"bg:*": true,
|
||||
"bg": "url('/path/to/pattern.png') repeat",
|
||||
"bg:opacity": 0.15
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Full-cover background image:
|
||||
|
||||
```json
|
||||
{
|
||||
"bg@cover": {
|
||||
"bg@ocean": {
|
||||
"display:name": "Ocean Scene",
|
||||
"bg:*": true,
|
||||
"bg": "url('/path/to/ocean.jpg') center/cover no-repeat",
|
||||
@ -175,25 +129,23 @@ Wave's background system harnesses the full power of CSS backgrounds, letting yo
|
||||
}
|
||||
```
|
||||
|
||||
Replace image URLs with your own assets. All examples use reduced opacity to work well with dark themes.
|
||||
|
||||
:::info
|
||||
Background images can be specified using URLs or local file paths. While URLs are supported, it's recommended to download and serve images locally for better reliability. For local files, you must use absolute paths or paths starting with `~` (e.g. `~/Downloads/background.png`). The system will automatically rewrite local paths to ensure proper access. We support all common web image formats: PNG, JPEG/JPG, WebP, GIF, and SVG.
|
||||
Background images support both URLs and local file paths. For better reliability, we recommend using local files. Local paths must be absolute or start with `~` (e.g., `~/Downloads/background.png`). We support common web formats: PNG, JPEG/JPG, WebP, GIF, and SVG.
|
||||
:::
|
||||
|
||||
:::tip
|
||||
You can use `wsh setbg --print` to help generate the JSON for your background presets. For example:
|
||||
The `setbg` command can help generate background preset JSON:
|
||||
|
||||
```bash
|
||||
# Preview the metadata for a gradient background
|
||||
wsh setbg --print "#ff0000"
|
||||
# Preview a solid color preset
|
||||
wsh setbg --print "#ff0000"
|
||||
{
|
||||
"bg:*": true,
|
||||
"bg": "#ff0000",
|
||||
"bg:opacity": 0.5
|
||||
}
|
||||
|
||||
# Preview a centered logo configuration
|
||||
# Preview a centered image preset
|
||||
wsh setbg --print --center --opacity 0.3 ~/logo.png
|
||||
{
|
||||
"bg:*": true,
|
||||
@ -202,9 +154,5 @@ wsh setbg --print --center --opacity 0.3 ~/logo.png
|
||||
}
|
||||
```
|
||||
|
||||
Copy the output and use it as a starting point for your preset configuration, just add the required `display:name` field!
|
||||
Just add the required `display:name` field to complete your preset!
|
||||
:::
|
||||
|
||||
#### Unset a default value
|
||||
|
||||
To unset a default value in a preset, add an override that sets it to an empty string, like `""`.
|
||||
|
@ -6,6 +6,28 @@ sidebar_position: 200
|
||||
|
||||
# Release Notes
|
||||
|
||||
### v0.10.0 — Dec 10, 2024
|
||||
|
||||
Wave Terminal v0.10.0 introduces workspaces, making it easier to manage multiple work environments. We've added powerful new command execution capabilities with `wsh run`, allowing you to launch and control commands in dedicated blocks. This release also brings significant improvements to SSH with a new connections configuration system for managing your remote environments.
|
||||
|
||||
- **Workspaces**: Organize your work into separate environments, each with their own tabs, layouts, and settings
|
||||
- **Command Blocks**: New `wsh run` command for launching terminal commands in dedicated blocks, with support for magnification, auto-closing, and execution control ([docs](/wsh#run))
|
||||
- **Connections**: New configuration system for managing SSH connections, with support for wsh-free operation, per-connection themes, and more ([docs](/connections))
|
||||
- Improved tab management with better switching behavior and context menus (many bug fixes)
|
||||
- New tab features including pinned tabs and drag-and-drop improvements
|
||||
- Create, rename, and delete files/directories directly in directory preview
|
||||
- Attempt wsh-free connection as a fallback if wsh installation or execution fails
|
||||
- New `-i` flag to add identity files with the `wsh ssh` command
|
||||
- Added Perplexity API integration ([docs](/faq#perplexity))
|
||||
- `wsh setbg` command for background handling ([docs](/wsh#setbg))
|
||||
- Switched from Less to SCSS for styling
|
||||
- [bugfix] Fixed tab flickering issues during tab switches
|
||||
- [bugfix] Corrected WaveAI text area resize behavior
|
||||
- [bugfix] Fixed concurrent block controller start issues
|
||||
- [bugfix] Fixed Preview Blocks for uninitialized connections
|
||||
- Upgraded Go toolchain to 1.23.4
|
||||
- Other bug fixes, performance improvements, and dependency updates
|
||||
|
||||
### v0.9.3 — Nov 20, 2024
|
||||
|
||||
New minor release that introduces Wave's connected computing extensions. We've introduced new `wsh` commands that allow you to store variables and files, and access them across terminal sessions (on both local and remote machines).
|
||||
|
BIN
docs/static/img/ai-presets.png
vendored
Normal file
BIN
docs/static/img/ai-presets.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
BIN
docs/static/img/wave-screenshot.webp
vendored
BIN
docs/static/img/wave-screenshot.webp
vendored
Binary file not shown.
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 211 KiB |
@ -23,7 +23,10 @@ export type WindowOpts = {
|
||||
};
|
||||
|
||||
export const waveWindowMap = new Map<string, WaveBrowserWindow>(); // waveWindowId -> WaveBrowserWindow
|
||||
export let focusedWaveWindow = null; // on blur we do not set this to null (but on destroy we do)
|
||||
|
||||
// on blur we do not set this to null (but on destroy we do), so this tracks the *last* focused window
|
||||
// e.g. it persists when the app itself is not focused
|
||||
export let focusedWaveWindow: WaveBrowserWindow = null;
|
||||
|
||||
let cachedClientId: string = null;
|
||||
|
||||
@ -55,10 +58,13 @@ type WindowActionQueueEntry =
|
||||
workspaceId: string;
|
||||
};
|
||||
|
||||
function showCloseConfirmDialog(workspace: Workspace): boolean {
|
||||
return !workspace.name && !workspace.icon && (workspace.tabids?.length > 1 || workspace.pinnedtabids?.length > 1);
|
||||
}
|
||||
|
||||
export class WaveBrowserWindow extends BaseWindow {
|
||||
waveWindowId: string;
|
||||
workspaceId: string;
|
||||
waveReadyPromise: Promise<void>;
|
||||
allLoadedTabViews: Map<string, WaveTabView>;
|
||||
activeTabView: WaveTabView;
|
||||
private canClose: boolean;
|
||||
@ -207,12 +213,7 @@ export class WaveBrowserWindow extends BaseWindow {
|
||||
setWasActive(true);
|
||||
});
|
||||
this.on("blur", () => {
|
||||
if (this.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
if (focusedWaveWindow == this) {
|
||||
focusedWaveWindow = null;
|
||||
}
|
||||
// nothing for now
|
||||
});
|
||||
this.on("close", (e) => {
|
||||
if (this.canClose) {
|
||||
@ -232,14 +233,13 @@ export class WaveBrowserWindow extends BaseWindow {
|
||||
console.log("numWindows > 1", numWindows);
|
||||
const workspace = await WorkspaceService.GetWorkspace(this.workspaceId);
|
||||
console.log("workspace", workspace);
|
||||
if (!workspace.name && !workspace.icon && workspace.tabids.length > 1) {
|
||||
if (showCloseConfirmDialog(workspace)) {
|
||||
console.log("workspace has no name, icon, and multiple tabs", workspace);
|
||||
const choice = dialog.showMessageBoxSync(this, {
|
||||
type: "question",
|
||||
buttons: ["Cancel", "Yes"],
|
||||
buttons: ["Cancel", "Close Window"],
|
||||
title: "Confirm",
|
||||
message:
|
||||
"Are you sure you want to close this window (all tabs and blocks will be deleted)?",
|
||||
message: "Window has unsaved tabs, closing window will delete existing tabs.\n\nContinue?",
|
||||
});
|
||||
if (choice === 0) {
|
||||
console.log("user cancelled close window", this.waveWindowId);
|
||||
@ -303,16 +303,12 @@ export class WaveBrowserWindow extends BaseWindow {
|
||||
const workspaceList = await WorkspaceService.ListWorkspaces();
|
||||
if (!workspaceList.find((wse) => wse.workspaceid === workspaceId)?.windowid) {
|
||||
const curWorkspace = await WorkspaceService.GetWorkspace(this.workspaceId);
|
||||
if (
|
||||
(curWorkspace.tabids?.length || curWorkspace.pinnedtabids?.length) &&
|
||||
(!curWorkspace.name || !curWorkspace.icon)
|
||||
) {
|
||||
if (showCloseConfirmDialog(curWorkspace)) {
|
||||
const choice = dialog.showMessageBoxSync(this, {
|
||||
type: "question",
|
||||
buttons: ["Cancel", "Open in New Window", "Yes"],
|
||||
buttons: ["Cancel", "Open in New Window", "Switch Workspace"],
|
||||
title: "Confirm",
|
||||
message:
|
||||
"This window has unsaved tabs, switching workspaces will delete the existing tabs. Would you like to continue?",
|
||||
message: "Window has unsaved tabs, switching workspaces will delete existing tabs.\n\nContinue?",
|
||||
});
|
||||
if (choice === 0) {
|
||||
console.log("user cancelled switch workspace", this.waveWindowId);
|
||||
@ -471,6 +467,9 @@ export class WaveBrowserWindow extends BaseWindow {
|
||||
private async processActionQueue() {
|
||||
while (this.actionQueue.length > 0) {
|
||||
try {
|
||||
if (this.isDestroyed()) {
|
||||
break;
|
||||
}
|
||||
const entry = this.actionQueue[0];
|
||||
let tabId: string = null;
|
||||
// have to use "===" here to get the typechecker to work :/
|
||||
@ -689,6 +688,21 @@ ipcMain.on("delete-workspace", (event, workspaceId) => {
|
||||
fireAndForget(async () => {
|
||||
const ww = getWaveWindowByWebContentsId(event.sender.id);
|
||||
console.log("delete-workspace", workspaceId, ww?.waveWindowId);
|
||||
|
||||
const workspaceList = await WorkspaceService.ListWorkspaces();
|
||||
|
||||
const workspaceHasWindow = !!workspaceList.find((wse) => wse.workspaceid === workspaceId)?.windowid;
|
||||
|
||||
const choice = dialog.showMessageBoxSync(this, {
|
||||
type: "question",
|
||||
buttons: ["Cancel", "Delete Workspace"],
|
||||
title: "Confirm",
|
||||
message: `Deleting workspace will also delete its contents.${workspaceHasWindow ? "\nWorkspace is open in a window, which will be closed." : ""}\n\nContinue?`,
|
||||
});
|
||||
if (choice === 0) {
|
||||
console.log("user cancelled workspace delete", workspaceId, ww?.waveWindowId);
|
||||
return;
|
||||
}
|
||||
await WorkspaceService.DeleteWorkspace(workspaceId);
|
||||
console.log("delete-workspace done", workspaceId, ww?.waveWindowId);
|
||||
if (ww?.workspaceId == workspaceId) {
|
||||
@ -711,7 +725,6 @@ export async function createNewWaveWindow() {
|
||||
const existingWindowData = (await ObjectService.GetObject("window:" + existingWindowId)) as WaveWindow;
|
||||
if (existingWindowData != null) {
|
||||
const win = await createBrowserWindow(existingWindowData, fullConfig, { unamePlatform });
|
||||
await win.waveReadyPromise;
|
||||
win.show();
|
||||
recreatedWindow = true;
|
||||
}
|
||||
@ -722,7 +735,6 @@ export async function createNewWaveWindow() {
|
||||
}
|
||||
console.log("creating new window");
|
||||
const newBrowserWindow = await createBrowserWindow(null, fullConfig, { unamePlatform });
|
||||
await newBrowserWindow.waveReadyPromise;
|
||||
newBrowserWindow.show();
|
||||
}
|
||||
|
||||
@ -754,7 +766,6 @@ export async function relaunchBrowserWindows() {
|
||||
wins.push(win);
|
||||
}
|
||||
for (const win of wins) {
|
||||
await win.waveReadyPromise;
|
||||
console.log("show window", win.waveWindowId);
|
||||
win.show();
|
||||
}
|
||||
|
@ -94,7 +94,6 @@ function handleWSEvent(evtMsg: WSEventType) {
|
||||
}
|
||||
const fullConfig = await services.FileService.GetFullConfig();
|
||||
const newWin = await createBrowserWindow(windowData, fullConfig, { unamePlatform });
|
||||
await newWin.waveReadyPromise;
|
||||
newWin.show();
|
||||
} else if (evtMsg.eventtype == "electron:closewindow") {
|
||||
console.log("electron:closewindow", evtMsg.data);
|
||||
@ -378,6 +377,9 @@ function saveImageFileWithNativeDialog(defaultFileName: string, mimeType: string
|
||||
defaultFileName = "image";
|
||||
}
|
||||
const ww = focusedWaveWindow;
|
||||
if (ww == null) {
|
||||
return;
|
||||
}
|
||||
const mimeToExtension: { [key: string]: string } = {
|
||||
"image/png": "png",
|
||||
"image/jpeg": "jpg",
|
||||
|
@ -164,7 +164,9 @@ export class Updater {
|
||||
type: "info",
|
||||
message: "There are currently no updates available.",
|
||||
};
|
||||
dialog.showMessageBox(focusedWaveWindow, dialogOpts);
|
||||
if (focusedWaveWindow) {
|
||||
dialog.showMessageBox(focusedWaveWindow, dialogOpts);
|
||||
}
|
||||
}
|
||||
|
||||
// Only update the last check time if this is an automatic check. This ensures the interval remains consistent.
|
||||
|
@ -637,7 +637,7 @@ const ChangeConnectionBlockModal = React.memo(
|
||||
const connStatusMap = new Map<string, ConnStatus>();
|
||||
const fullConfig = jotai.useAtomValue(atoms.fullConfigAtom);
|
||||
const connectionsConfig = fullConfig.connections;
|
||||
let filterOutNowsh = util.useAtomValueSafe(viewModel.filterOutNowsh) || true;
|
||||
let filterOutNowsh = util.useAtomValueSafe(viewModel.filterOutNowsh) ?? true;
|
||||
|
||||
let maxActiveConnNum = 1;
|
||||
for (const conn of allConnStatus) {
|
||||
@ -706,9 +706,6 @@ const ChangeConnectionBlockModal = React.memo(
|
||||
}
|
||||
const filteredList: Array<string> = [];
|
||||
for (const conn of connList) {
|
||||
if (conn === connSelected) {
|
||||
createNew = false;
|
||||
}
|
||||
if (
|
||||
conn.includes(connSelected) &&
|
||||
connectionsConfig?.[conn]?.["display:hidden"] != true &&
|
||||
@ -716,13 +713,13 @@ const ChangeConnectionBlockModal = React.memo(
|
||||
// != false is necessary because of defaults
|
||||
) {
|
||||
filteredList.push(conn);
|
||||
if (conn === connSelected) {
|
||||
createNew = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
const filteredWslList: Array<string> = [];
|
||||
for (const conn of wslList) {
|
||||
if (conn === connSelected) {
|
||||
createNew = false;
|
||||
}
|
||||
if (
|
||||
conn.includes(connSelected) &&
|
||||
connectionsConfig?.[conn]?.["display:hidden"] != true &&
|
||||
@ -730,6 +727,9 @@ const ChangeConnectionBlockModal = React.memo(
|
||||
// != false is necessary because of defaults
|
||||
) {
|
||||
filteredWslList.push(conn);
|
||||
if (conn === connSelected) {
|
||||
createNew = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// priority handles special suggestions when necessary
|
||||
|
@ -146,6 +146,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
|
@ -67,6 +67,7 @@ interface InputProps {
|
||||
required?: boolean;
|
||||
maxLength?: number;
|
||||
autoFocus?: boolean;
|
||||
autoSelect?: boolean;
|
||||
disabled?: boolean;
|
||||
isNumber?: boolean;
|
||||
inputRef?: React.MutableRefObject<any>;
|
||||
@ -88,6 +89,7 @@ const Input = memo(
|
||||
required,
|
||||
maxLength,
|
||||
autoFocus,
|
||||
autoSelect,
|
||||
disabled,
|
||||
isNumber,
|
||||
manageFocus,
|
||||
@ -114,6 +116,9 @@ const Input = memo(
|
||||
};
|
||||
|
||||
const handleFocus = () => {
|
||||
if (autoSelect) {
|
||||
inputRef.current?.select();
|
||||
}
|
||||
manageFocus?.(true);
|
||||
onFocus?.();
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
@import url("../../../node_modules/highlight.js/scss/github-dark-dimmed.scss");
|
||||
|
||||
.markdown {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -2,6 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
.window-drag {
|
||||
-webkit-app-region: drag;
|
||||
-webkit-app-region: drag !important;
|
||||
z-index: var(--zindex-window-drag);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
position: absolute;
|
||||
width: 130px;
|
||||
height: calc(100% - 1px);
|
||||
padding: 6px 0px 0px;
|
||||
padding: 0 0 0 0;
|
||||
box-sizing: border-box;
|
||||
font-weight: bold;
|
||||
color: var(--secondary-text-color);
|
||||
|
@ -28,17 +28,23 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: env(titlebar-area-width);
|
||||
-webkit-app-region: drag;
|
||||
|
||||
* {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.tabs-wrapper {
|
||||
transition: var(--tabs-wrapper-transition);
|
||||
height: 32px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
margin-top: 6px;
|
||||
position: relative; // Needed for absolute positioning of child tabs
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 33px;
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.pinned-tab-spacer {
|
||||
|
@ -99,6 +99,43 @@ const ConfigErrorIcon = ({ buttonRef }: { buttonRef: React.RefObject<HTMLElement
|
||||
);
|
||||
};
|
||||
|
||||
function strArrayIsEqual(a: string[], b: string[]) {
|
||||
// null check
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function setIsEqual(a: Set<string> | null, b: Set<string> | null): boolean {
|
||||
if (a == null && b == null) {
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
if (a.size !== b.size) {
|
||||
return false;
|
||||
}
|
||||
for (const item of a) {
|
||||
if (!b.has(item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const TabBar = memo(({ workspace }: TabBarProps) => {
|
||||
const [tabIds, setTabIds] = useState([]);
|
||||
const [pinnedTabIds, setPinnedTabIds] = useState<Set<string>>(new Set());
|
||||
@ -149,22 +186,22 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
|
||||
}, [tabIds]);
|
||||
|
||||
useEffect(() => {
|
||||
if (workspace) {
|
||||
// Compare current tabIds with new workspace.tabids
|
||||
const newTabIds = new Set([...(workspace.pinnedtabids ?? []), ...(workspace.tabids ?? [])]);
|
||||
const newPinnedTabIds = workspace.pinnedtabids ?? [];
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
// Compare current tabIds with new workspace.tabids
|
||||
console.log("tabbar workspace", workspace);
|
||||
|
||||
const areEqual =
|
||||
tabIds.length === newTabIds.size &&
|
||||
tabIds.every((id) => newTabIds.has(id)) &&
|
||||
newPinnedTabIds.length === pinnedTabIds.size;
|
||||
const newTabIdsArr = [...(workspace.pinnedtabids ?? []), ...(workspace.tabids ?? [])];
|
||||
const newPinnedTabSet = new Set(workspace.pinnedtabids ?? []);
|
||||
|
||||
if (!areEqual) {
|
||||
const newPinnedTabIdSet = new Set(newPinnedTabIds);
|
||||
const newTabIdList = newPinnedTabIds.concat([...newTabIds].filter((id) => !newPinnedTabIdSet.has(id))); // Corrects for any duplicates between the two lists
|
||||
setTabIds(newTabIdList);
|
||||
setPinnedTabIds(newPinnedTabIdSet);
|
||||
}
|
||||
const areEqual = strArrayIsEqual(tabIds, newTabIdsArr) && setIsEqual(pinnedTabIds, newPinnedTabSet);
|
||||
|
||||
if (!areEqual) {
|
||||
console.log("newPinnedTabIds", newPinnedTabSet);
|
||||
console.log("newTabIdList", newTabIdsArr);
|
||||
setTabIds(newTabIdsArr);
|
||||
setPinnedTabIds(newPinnedTabSet);
|
||||
}
|
||||
}, [workspace, tabIds, pinnedTabIds]);
|
||||
|
||||
|
@ -143,14 +143,9 @@
|
||||
.expandable-menu-item-group-title {
|
||||
height: 29px;
|
||||
padding: 0;
|
||||
|
||||
.left-icon {
|
||||
font-size: 14px;
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.color-icon-selector {
|
||||
.workspace-editor {
|
||||
width: 100%;
|
||||
.input {
|
||||
margin: 5px 0 10px;
|
||||
@ -223,7 +218,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ const colors = [
|
||||
];
|
||||
|
||||
const icons = [
|
||||
"circle",
|
||||
"custom@wave-logo-solid",
|
||||
"triangle",
|
||||
"star",
|
||||
"heart",
|
||||
@ -93,7 +93,7 @@ const IconSelector = memo(({ icons, selectedIcon, onSelect, className }: IconSel
|
||||
return (
|
||||
<div className={clsx("icon-selector", className)}>
|
||||
{icons.map((icon) => {
|
||||
const iconClass = makeIconClass(icon, false);
|
||||
const iconClass = makeIconClass(icon, true);
|
||||
return (
|
||||
<i
|
||||
key={icon}
|
||||
@ -106,7 +106,7 @@ const IconSelector = memo(({ icons, selectedIcon, onSelect, className }: IconSel
|
||||
);
|
||||
});
|
||||
|
||||
interface ColorAndIconSelectorProps {
|
||||
interface WorkspaceEditorProps {
|
||||
title: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
@ -116,7 +116,7 @@ interface ColorAndIconSelectorProps {
|
||||
onIconChange: (newIcon: string) => void;
|
||||
onDeleteWorkspace: () => void;
|
||||
}
|
||||
const ColorAndIconSelector = memo(
|
||||
const WorkspaceEditor = memo(
|
||||
({
|
||||
title,
|
||||
icon,
|
||||
@ -126,28 +126,30 @@ const ColorAndIconSelector = memo(
|
||||
onColorChange,
|
||||
onIconChange,
|
||||
onDeleteWorkspace,
|
||||
}: ColorAndIconSelectorProps) => {
|
||||
}: WorkspaceEditorProps) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (focusInput && inputRef.current) {
|
||||
inputRef.current.focus();
|
||||
inputRef.current.select();
|
||||
}
|
||||
}, [focusInput]);
|
||||
|
||||
return (
|
||||
<div className="color-icon-selector">
|
||||
<div className="workspace-editor">
|
||||
<Input
|
||||
ref={inputRef}
|
||||
className={clsx("vertical-padding-3", { error: title === "" })}
|
||||
onChange={onTitleChange}
|
||||
value={title}
|
||||
autoFocus
|
||||
autoSelect
|
||||
/>
|
||||
<ColorSelector selectedColor={color} colors={colors} onSelect={onColorChange} />
|
||||
<IconSelector selectedIcon={icon} icons={icons} onSelect={onIconChange} />
|
||||
<div className="delete-ws-btn-wrapper">
|
||||
<Button className="ghost red font-size-12" onClick={onDeleteWorkspace}>
|
||||
<Button className="ghost red font-size-12 bold" onClick={onDeleteWorkspace}>
|
||||
Delete workspace
|
||||
</Button>
|
||||
</div>
|
||||
@ -221,6 +223,7 @@ const WorkspaceSwitcher = forwardRef<HTMLDivElement, {}>(({}, ref) => {
|
||||
setTimeout(() => {
|
||||
fireAndForget(updateWorkspaceList);
|
||||
}, 10);
|
||||
setEditingWorkspace(activeWorkspace.oid);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -335,7 +338,7 @@ const WorkspaceSwitcherItem = ({
|
||||
>
|
||||
<ExpandableMenuItemLeftElement>
|
||||
<i
|
||||
className={clsx("left-icon", makeIconClass(workspace.icon, false))}
|
||||
className={clsx("left-icon", makeIconClass(workspace.icon, true))}
|
||||
style={{ color: workspace.color }}
|
||||
/>
|
||||
</ExpandableMenuItemLeftElement>
|
||||
@ -349,7 +352,7 @@ const WorkspaceSwitcherItem = ({
|
||||
</div>
|
||||
</ExpandableMenuItemGroupTitle>
|
||||
<ExpandableMenuItem>
|
||||
<ColorAndIconSelector
|
||||
<WorkspaceEditor
|
||||
title={workspace.name}
|
||||
icon={workspace.icon}
|
||||
color={workspace.color}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Used for syntax highlighting in markdown
|
||||
@import url("../../node_modules/highlight.js/styles/github-dark-dimmed.min.css");
|
||||
|
||||
:root {
|
||||
--main-text-color: #f7f7f7;
|
||||
|
@ -293,7 +293,8 @@ function DirectoryTable({
|
||||
newPath = path.replace(fileName, newName);
|
||||
console.log(`replacing ${fileName} with ${newName}: ${path}`);
|
||||
fireAndForget(async () => {
|
||||
await FileService.Rename(globalStore.get(model.connection), path, newPath);
|
||||
const connection = await globalStore.get(model.connection);
|
||||
await FileService.Rename(connection, path, newPath);
|
||||
model.refreshCallback();
|
||||
});
|
||||
}
|
||||
@ -804,7 +805,8 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
|
||||
onSave: (newName: string) => {
|
||||
console.log(`newFile: ${newName}`);
|
||||
fireAndForget(async () => {
|
||||
await FileService.TouchFile(globalStore.get(model.connection), `${dirPath}/${newName}`);
|
||||
const connection = await globalStore.get(model.connection);
|
||||
await FileService.TouchFile(connection, `${dirPath}/${newName}`);
|
||||
model.refreshCallback();
|
||||
});
|
||||
setEntryManagerProps(undefined);
|
||||
@ -817,7 +819,8 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
|
||||
onSave: (newName: string) => {
|
||||
console.log(`newDirectory: ${newName}`);
|
||||
fireAndForget(async () => {
|
||||
await FileService.Mkdir(globalStore.get(model.connection), `${dirPath}/${newName}`);
|
||||
const connection = await globalStore.get(model.connection);
|
||||
await FileService.Mkdir(connection, `${dirPath}/${newName}`);
|
||||
model.refreshCallback();
|
||||
});
|
||||
setEntryManagerProps(undefined);
|
||||
|
@ -128,7 +128,7 @@ export class PreviewModel implements ViewModel {
|
||||
normFilePath: Atom<Promise<string>>;
|
||||
loadableStatFilePath: Atom<Loadable<string>>;
|
||||
loadableFileInfo: Atom<Loadable<FileInfo>>;
|
||||
connection: Atom<string>;
|
||||
connection: Atom<Promise<string>>;
|
||||
statFile: Atom<Promise<FileInfo>>;
|
||||
fullFile: Atom<Promise<FullFile>>;
|
||||
fileMimeType: Atom<Promise<string>>;
|
||||
@ -136,6 +136,7 @@ export class PreviewModel implements ViewModel {
|
||||
fileContentSaved: PrimitiveAtom<string | null>;
|
||||
fileContent: WritableAtom<Promise<string>, [string], void>;
|
||||
newFileContent: PrimitiveAtom<string | null>;
|
||||
connectionError: PrimitiveAtom<string>;
|
||||
|
||||
openFileModal: PrimitiveAtom<boolean>;
|
||||
openFileError: PrimitiveAtom<string>;
|
||||
@ -167,6 +168,7 @@ export class PreviewModel implements ViewModel {
|
||||
this.markdownShowToc = atom(false);
|
||||
this.filterOutNowsh = atom(true);
|
||||
this.monacoRef = createRef();
|
||||
this.connectionError = atom("");
|
||||
this.viewIcon = atom((get) => {
|
||||
const blockData = get(this.blockAtom);
|
||||
if (blockData?.meta?.icon) {
|
||||
@ -359,15 +361,22 @@ export class PreviewModel implements ViewModel {
|
||||
return fileInfo.dir + "/" + fileInfo.name;
|
||||
});
|
||||
this.loadableStatFilePath = loadable(this.statFilePath);
|
||||
this.connection = atom<string>((get) => {
|
||||
return get(this.blockAtom)?.meta?.connection;
|
||||
this.connection = atom<Promise<string>>(async (get) => {
|
||||
const connName = get(this.blockAtom)?.meta?.connection;
|
||||
try {
|
||||
await RpcApi.ConnEnsureCommand(TabRpcClient, connName, { timeout: 60000 });
|
||||
globalStore.set(this.connectionError, "");
|
||||
} catch (e) {
|
||||
globalStore.set(this.connectionError, e as string);
|
||||
}
|
||||
return connName;
|
||||
});
|
||||
this.statFile = atom<Promise<FileInfo>>(async (get) => {
|
||||
const fileName = get(this.metaFilePath);
|
||||
if (fileName == null) {
|
||||
return null;
|
||||
}
|
||||
const conn = get(this.connection) ?? "";
|
||||
const conn = (await get(this.connection)) ?? "";
|
||||
const statFile = await services.FileService.StatFile(conn, fileName);
|
||||
return statFile;
|
||||
});
|
||||
@ -384,7 +393,7 @@ export class PreviewModel implements ViewModel {
|
||||
if (fileName == null) {
|
||||
return null;
|
||||
}
|
||||
const conn = get(this.connection) ?? "";
|
||||
const conn = (await get(this.connection)) ?? "";
|
||||
const file = await services.FileService.ReadFile(conn, fileName);
|
||||
return file;
|
||||
});
|
||||
@ -434,10 +443,14 @@ export class PreviewModel implements ViewModel {
|
||||
const mimeType = await getFn(this.fileMimeType);
|
||||
const fileInfo = await getFn(this.statFile);
|
||||
const fileName = await getFn(this.statFilePath);
|
||||
const connErr = getFn(this.connectionError);
|
||||
const editMode = getFn(this.editMode);
|
||||
const parentFileInfo = await this.getParentInfo(fileInfo);
|
||||
console.log(parentFileInfo);
|
||||
|
||||
if (connErr != "") {
|
||||
return { errorStr: `Connection Error: ${connErr}` };
|
||||
}
|
||||
if (parentFileInfo?.notfound ?? false) {
|
||||
return { errorStr: `Parent Directory Not Found: ${fileInfo.path}` };
|
||||
}
|
||||
@ -505,7 +518,7 @@ export class PreviewModel implements ViewModel {
|
||||
}
|
||||
|
||||
async getParentInfo(fileInfo: FileInfo): Promise<FileInfo | undefined> {
|
||||
const conn = globalStore.get(this.connection);
|
||||
const conn = await globalStore.get(this.connection);
|
||||
try {
|
||||
const parentFileInfo = await RpcApi.RemoteFileJoinCommand(TabRpcClient, [fileInfo.path, ".."], {
|
||||
route: makeConnRoute(conn),
|
||||
@ -526,7 +539,7 @@ export class PreviewModel implements ViewModel {
|
||||
this.updateOpenFileModalAndError(false);
|
||||
return true;
|
||||
}
|
||||
const conn = globalStore.get(this.connection);
|
||||
const conn = await globalStore.get(this.connection);
|
||||
try {
|
||||
const newFileInfo = await RpcApi.RemoteFileJoinCommand(TabRpcClient, [fileInfo.path, ".."], {
|
||||
route: makeConnRoute(conn),
|
||||
@ -586,7 +599,7 @@ export class PreviewModel implements ViewModel {
|
||||
console.log("not saving file, newFileContent is null");
|
||||
return;
|
||||
}
|
||||
const conn = globalStore.get(this.connection) ?? "";
|
||||
const conn = (await globalStore.get(this.connection)) ?? "";
|
||||
try {
|
||||
await services.FileService.SaveFile(conn, filePath, stringToBase64(newFileContent));
|
||||
globalStore.set(this.fileContent, newFileContent);
|
||||
@ -609,7 +622,7 @@ export class PreviewModel implements ViewModel {
|
||||
this.updateOpenFileModalAndError(false);
|
||||
return true;
|
||||
}
|
||||
const conn = globalStore.get(this.connection);
|
||||
const conn = await globalStore.get(this.connection);
|
||||
try {
|
||||
const newFileInfo = await RpcApi.RemoteFileJoinCommand(TabRpcClient, [fileInfo.dir, filePath], {
|
||||
route: makeConnRoute(conn),
|
||||
|
@ -103,6 +103,11 @@ function makeIconClass(icon: string, fw: boolean, opts?: { spin?: boolean; defau
|
||||
icon = icon.replace(/^brands@/, "");
|
||||
return clsx(`fa fa-brands fa-${icon}`, fw ? "fa-fw" : null, opts?.spin ? "fa-spin" : null);
|
||||
}
|
||||
if (icon.match(/^custom@[a-z0-9-]+$/)) {
|
||||
// strip off the "custom@" prefix if it exists
|
||||
icon = icon.replace(/^custom@/, "");
|
||||
return clsx(`fa fa-kit fa-${icon}`, fw ? "fa-fw" : null, opts?.spin ? "fa-spin" : null);
|
||||
}
|
||||
if (opts?.defaultIcon != null) {
|
||||
return makeIconClass(opts.defaultIcon, fw, { spin: opts?.spin });
|
||||
}
|
||||
|
@ -109,21 +109,27 @@ async function reinitWave() {
|
||||
}
|
||||
|
||||
function reloadAllWorkspaceTabs(ws: Workspace) {
|
||||
if (ws == null || ws.tabids == null) {
|
||||
if (ws == null || (!ws.tabids?.length && !ws.pinnedtabids?.length)) {
|
||||
return;
|
||||
}
|
||||
ws.tabids.forEach((tabid) => {
|
||||
ws?.tabids.forEach((tabid) => {
|
||||
WOS.reloadWaveObject<Tab>(WOS.makeORef("tab", tabid));
|
||||
});
|
||||
ws?.pinnedtabids?.forEach((tabid) => {
|
||||
WOS.reloadWaveObject<Tab>(WOS.makeORef("tab", tabid));
|
||||
});
|
||||
}
|
||||
|
||||
function loadAllWorkspaceTabs(ws: Workspace) {
|
||||
if (ws == null || ws.tabids == null) {
|
||||
if (ws == null || (!ws.tabids?.length && !ws.pinnedtabids?.length)) {
|
||||
return;
|
||||
}
|
||||
ws.tabids.forEach((tabid) => {
|
||||
WOS.getObjectValue<Tab>(WOS.makeORef("tab", tabid));
|
||||
});
|
||||
ws.pinnedtabids.forEach((tabid) => {
|
||||
WOS.getObjectValue<Tab>(WOS.makeORef("tab", tabid));
|
||||
});
|
||||
}
|
||||
|
||||
async function initWave(initOpts: WaveInitOpts) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
<link rel="stylesheet" href="/fontawesome/css/solid.min.css" />
|
||||
<link rel="stylesheet" href="/fontawesome/css/sharp-solid.min.css" />
|
||||
<link rel="stylesheet" href="/fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="/fontawesome/css/custom-icons.min.css" />
|
||||
<script type="module" src="frontend/wave.ts"></script>
|
||||
</head>
|
||||
<body class="init">
|
||||
|
21
package.json
21
package.json
@ -7,7 +7,7 @@
|
||||
"productName": "Wave",
|
||||
"description": "Open-Source AI-Native Terminal Built for Seamless Workflows",
|
||||
"license": "Apache-2.0",
|
||||
"version": "0.10.0-beta.2",
|
||||
"version": "0.10.0-beta.4",
|
||||
"homepage": "https://waveterm.dev",
|
||||
"build": {
|
||||
"appId": "dev.commandline.waveterm"
|
||||
@ -30,14 +30,15 @@
|
||||
"@chromatic-com/storybook": "^3.2.2",
|
||||
"@eslint/js": "^9.16.0",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@storybook/addon-essentials": "^8.4.6",
|
||||
"@storybook/addon-interactions": "^8.4.6",
|
||||
"@storybook/addon-links": "^8.4.6",
|
||||
"@storybook/blocks": "^8.4.6",
|
||||
"@storybook/react": "^8.4.6",
|
||||
"@storybook/react-vite": "^8.4.6",
|
||||
"@storybook/test": "^8.4.6",
|
||||
"@storybook/theming": "^8.4.6",
|
||||
"@storybook/addon-essentials": "^8.4.7",
|
||||
"@storybook/addon-interactions": "^8.4.7",
|
||||
"@storybook/addon-links": "^8.4.7",
|
||||
"@storybook/blocks": "^8.4.7",
|
||||
"@storybook/builder-vite": "^8.4.7",
|
||||
"@storybook/react": "^8.4.7",
|
||||
"@storybook/react-vite": "^8.4.7",
|
||||
"@storybook/test": "^8.4.7",
|
||||
"@storybook/theming": "^8.4.7",
|
||||
"@types/color": "^4.2.0",
|
||||
"@types/css-tree": "^2",
|
||||
"@types/debug": "^4",
|
||||
@ -68,7 +69,7 @@
|
||||
"rollup-plugin-flow": "^1.1.1",
|
||||
"sass": "^1.82.0",
|
||||
"semver": "^7.6.3",
|
||||
"storybook": "^8.4.6",
|
||||
"storybook": "^8.4.7",
|
||||
"storybook-dark-mode": "^4.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslib": "^2.8.1",
|
||||
|
@ -733,6 +733,10 @@ func GetConnectionsFromInternalConfig() []string {
|
||||
var internalNames []string
|
||||
config := wconfig.ReadFullConfig()
|
||||
for internalName := range config.Connections {
|
||||
if strings.HasPrefix(internalName, "wsl://") {
|
||||
// don't add wsl conns to this list
|
||||
continue
|
||||
}
|
||||
internalNames = append(internalNames, internalName)
|
||||
}
|
||||
return internalNames
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package workspaceservice
|
||||
|
||||
import (
|
||||
|
@ -96,5 +96,13 @@
|
||||
"bg": "linear-gradient(120deg,hsla(350, 65%, 57%, 1),hsla(30,60%,60%, .75), hsla(208,69%,50%,.15), hsl(230,60%,40%)),radial-gradient(at top right,hsla(300,60%,70%,0.3),transparent),radial-gradient(at top left,hsla(330,100%,70%,.20),transparent),radial-gradient(at top right,hsla(190,100%,40%,.20),transparent),radial-gradient(at bottom left,hsla(323,54%,50%,.5),transparent),radial-gradient(at bottom left,hsla(144,54%,50%,.25),transparent)",
|
||||
"bg:blendmode": "overlay",
|
||||
"bg:text": "rgb(200, 200, 200)"
|
||||
},
|
||||
"bg@cosmic-tide": {
|
||||
"display:name": "Cosmic Tide",
|
||||
"display:order": 3.6,
|
||||
"bg:activebordercolor": "#ff55aa",
|
||||
"bg:*": true,
|
||||
"bg": "linear-gradient(135deg, #00d9d9, #ff55aa, #1e1e2f, #2f3b57, #ff99ff)",
|
||||
"bg:opacity": 0.6
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wcore
|
||||
|
||||
import (
|
||||
|
@ -54,7 +54,7 @@ func EnsureInitialData() error {
|
||||
return nil
|
||||
}
|
||||
log.Println("client has no windows, creating starter workspace")
|
||||
starterWs, err := CreateWorkspace(ctx, "Starter workspace", "circle", "#58C142", true)
|
||||
starterWs, err := CreateWorkspace(ctx, "Starter workspace", "custom@wave-logo-solid", "#58C142", true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating starter workspace: %w", err)
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wcore
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,6 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package wcore
|
||||
|
||||
import (
|
||||
|
1
public/fontawesome/css/custom-icons.min.css
vendored
Normal file
1
public/fontawesome/css/custom-icons.min.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
@charset "utf-8";.fak.fa-wave-logo-solid,.fa-kit.fa-wave-logo-solid{--fa:"";--fa--fa:""}.fak,.fa-kit{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:var(--fa-display,inline-block);font-variant:normal;text-rendering:auto;font-family:Font Awesome Kit;font-style:normal;font-weight:400;line-height:1}.fak:before,.fa-kit:before{content:var(--fa)}@font-face{font-family:Font Awesome Kit;font-style:normal;font-display:block;src:url(../webfonts/custom-icons.woff2)format("woff2"),url(../webfonts/custom-icons.ttf)format("truetype")}
|
10
public/fontawesome/css/fontawesome.min.css
vendored
10
public/fontawesome/css/fontawesome.min.css
vendored
File diff suppressed because one or more lines are too long
BIN
public/fontawesome/webfonts/custom-icons.woff2
Normal file
BIN
public/fontawesome/webfonts/custom-icons.woff2
Normal file
Binary file not shown.
317
yarn.lock
317
yarn.lock
@ -5167,9 +5167,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-actions@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-actions@npm:8.4.6"
|
||||
"@storybook/addon-actions@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-actions@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@types/uuid": "npm:^9.0.1"
|
||||
@ -5177,164 +5177,164 @@ __metadata:
|
||||
polished: "npm:^4.2.2"
|
||||
uuid: "npm:^9.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/80b2feceacb4ebe7f2be06b2fe3f49ded5ee08ca8bd036ff47a65d45d8796d29081ccadd0526984c8022bcfa24348e0ad4ce3f37cee4a60a928bae372bfc8afe
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/411be60f358101291cbd4ff8e5ddbac58fa0583c95338b82b410dc030a73632b654eaf7004b421c7e309cf0bfa709c4f93728b943e1b59dcfff5a249686501c1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-backgrounds@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-backgrounds@npm:8.4.6"
|
||||
"@storybook/addon-backgrounds@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-backgrounds@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
memoizerific: "npm:^1.11.3"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/2125d6905bf44194adf79e92698753d5e4ff75fac1ffbba1fc95ae705ba9ac8dc6ca9249c9a862aa05ea207d916d23142faefa759bb9ce21c6e16f0e329d28d2
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/d22c4acd1d99f616865dde11c70b444a0aac7fe7623904479a29a0142b504f284ddc2407eacfd1203c3b0856e5497e7902eb86e287516364c7735b90e224bbcb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-controls@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-controls@npm:8.4.6"
|
||||
"@storybook/addon-controls@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-controls@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
dequal: "npm:^2.0.2"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/f5f0ab2de8de80c8c3726de81802042cc29a6f2ec50de3b8bd463286c9056e87800e4ea9b350c6a41ce4c4175a11cb7d3d490da5cfc20bbf2a2e3549f77a82a7
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/900c71d172e9f75a1c39a87de1d411890fcea012586be02e3293c705c500a3a62a2bdecb10c11ba9c9f6117706dfbc34aaa40d2ca8e8a9d7b8a6a739d6a73e0c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-docs@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-docs@npm:8.4.6"
|
||||
"@storybook/addon-docs@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-docs@npm:8.4.7"
|
||||
dependencies:
|
||||
"@mdx-js/react": "npm:^3.0.0"
|
||||
"@storybook/blocks": "npm:8.4.6"
|
||||
"@storybook/csf-plugin": "npm:8.4.6"
|
||||
"@storybook/react-dom-shim": "npm:8.4.6"
|
||||
"@storybook/blocks": "npm:8.4.7"
|
||||
"@storybook/csf-plugin": "npm:8.4.7"
|
||||
"@storybook/react-dom-shim": "npm:8.4.7"
|
||||
react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/ae53bf71048fe7476862ae733f0f765a22d0d1da32457f7ca7e3bdd23bb1cd452c56bc4e1f586cf978599c3f5acb835caeb569ff394eaec09d3259382f4954be
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/0eb1854ddb6dbef1b32f89746944ee7a16db986403fe0a3712f43d39faa6335e0bce4ac21a8c20d09955ae73cccd1962f3b45037ab1144f61c1317d686e8695f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-essentials@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-essentials@npm:8.4.6"
|
||||
"@storybook/addon-essentials@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-essentials@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/addon-actions": "npm:8.4.6"
|
||||
"@storybook/addon-backgrounds": "npm:8.4.6"
|
||||
"@storybook/addon-controls": "npm:8.4.6"
|
||||
"@storybook/addon-docs": "npm:8.4.6"
|
||||
"@storybook/addon-highlight": "npm:8.4.6"
|
||||
"@storybook/addon-measure": "npm:8.4.6"
|
||||
"@storybook/addon-outline": "npm:8.4.6"
|
||||
"@storybook/addon-toolbars": "npm:8.4.6"
|
||||
"@storybook/addon-viewport": "npm:8.4.6"
|
||||
"@storybook/addon-actions": "npm:8.4.7"
|
||||
"@storybook/addon-backgrounds": "npm:8.4.7"
|
||||
"@storybook/addon-controls": "npm:8.4.7"
|
||||
"@storybook/addon-docs": "npm:8.4.7"
|
||||
"@storybook/addon-highlight": "npm:8.4.7"
|
||||
"@storybook/addon-measure": "npm:8.4.7"
|
||||
"@storybook/addon-outline": "npm:8.4.7"
|
||||
"@storybook/addon-toolbars": "npm:8.4.7"
|
||||
"@storybook/addon-viewport": "npm:8.4.7"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/b8fb83e018fcb1e8cad04b371af5f8ce9933e3a500a78a889715ecfe4efd9faa52acce2d0f97fb04fe9ae0898e661112816c052bfe9b5f01189938b122055a44
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/82ddd8424dfd5bf0ef44cee6a320f8395c63678bc0d4566307b2c68bd83c39f6bd447fb421681e3ab581c35c9d991207b01bebf20269c083931f581bb4651d6d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-highlight@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-highlight@npm:8.4.6"
|
||||
"@storybook/addon-highlight@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-highlight@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/67a23a5e3b8f7740c7101e8fa886f3f9c6c61b6db3cb3430d2c805231f7ad170d2d926c12e7c9bfc4af327c5abac5b4155f4c0d70ea423b04704fe3def845acc
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/2256b880d1f83c86c64287988bd4f4b76a8e1990f2a2a080a322994a9a8e553013fc21b7503c218ec394a880c1b72b131975e6eeadec6accb7eb35d3cb85a6ce
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-interactions@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-interactions@npm:8.4.6"
|
||||
"@storybook/addon-interactions@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-interactions@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/instrumenter": "npm:8.4.6"
|
||||
"@storybook/test": "npm:8.4.6"
|
||||
"@storybook/instrumenter": "npm:8.4.7"
|
||||
"@storybook/test": "npm:8.4.7"
|
||||
polished: "npm:^4.2.2"
|
||||
ts-dedent: "npm:^2.2.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/42e4bc2df354dba10217385687ac20fb355f4e1a2a7390812081d6b387151b67bca868211794e531c1e112dc4ce50c70dffa55c8f4338b0bd860d59363d58d5b
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/5c35d2f33122f053568a746c36eb99eb1764ee990146ea374b0fc01defd3f0b33674d2758c027c760fe2966f8683193e8c414089c07e1136ffc562e3346ce479
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-links@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-links@npm:8.4.6"
|
||||
"@storybook/addon-links@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-links@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/csf": "npm:^0.1.11"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.4.6
|
||||
storybook: ^8.4.7
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
checksum: 10c0/9360122d9c5370706a583526fb72efd0901d7e64c7467bfb4d832712cc41928d4fcfa397a53cfa17a1ae3875b8ef92ce6a10fb0bf0ce00149dc0d0eb1d66e27b
|
||||
checksum: 10c0/475d3231ac6c6531cfa5d01e8816b90cbf51e993c1575fa7bf541540bf76af52d7f1087e929b87d771ce41ae4fd7762df1e25c9d8543200630f8618d85b16520
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-measure@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-measure@npm:8.4.6"
|
||||
"@storybook/addon-measure@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-measure@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
tiny-invariant: "npm:^1.3.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/fd05b49fdb102a991fc696a0f75fde08d372b692778340ab2abc2c73fbd31a07dfa27a7a9d775dda7baaa9bd8a18972ed0bd86e9ce27948afb0305778f7b5a95
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/a9e87c91cbcade2d0059cdc471e8ba479ad6d9dee0c2558c3b706e37d58b4cb3d986924ea0ff623aa791300ee2a8d2429e8fb3ef32eeec9d49861f8677815ac2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-outline@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-outline@npm:8.4.6"
|
||||
"@storybook/addon-outline@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-outline@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/62600a9f4164a8d91118d37cd7be4f4dd871e849a156ba7728f463bc2cfc5a8a233df09055dd5e5733a042fde7a63b08616cb3c61b26c363c1e2d4ce20d92584
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/13e8579ad1e9c8e338a66935331764351d9681e177469c7be72bc8383d6ab0441a783b2089ac3a730979d9a97c347800a47769b1f1ab5b4dfd7fc31f29e1709f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-toolbars@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-toolbars@npm:8.4.6"
|
||||
"@storybook/addon-toolbars@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-toolbars@npm:8.4.7"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/6525e71aaa3870ae97d407b662323022ade98859f89975110f5fb4a1d3f34b6c918d47fcc8a6a271f4a77acfcaadc963a846a83ebc6c748b37df50422ad60e7e
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/1c315d5ad07291f35ad780ef69fbd6570a582c008ab911cf14bff84061546b9ea1373d1127213844652d73a47c3011d28c1ad08d465fc120969c133dabfe7638
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-viewport@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/addon-viewport@npm:8.4.6"
|
||||
"@storybook/addon-viewport@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/addon-viewport@npm:8.4.7"
|
||||
dependencies:
|
||||
memoizerific: "npm:^1.11.3"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/824438cc44a45f90748ac5f20ac148a36d975a94fa89504a583e0e1188de8c574e042ad3cd537bc16ddb30d4e44e90f5a63263239b13419aec5334e2ece18cd0
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/4dec3b59be1f3b99d3c9eaab695a7e346d975b772f6691f8286005d78a13a204c5680c6c8733ae83060c7639b56efed9f3580cee7413834ac6595b56345183ef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/blocks@npm:8.4.6, @storybook/blocks@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/blocks@npm:8.4.6"
|
||||
"@storybook/blocks@npm:8.4.7, @storybook/blocks@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/blocks@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/csf": "npm:^0.1.11"
|
||||
"@storybook/icons": "npm:^1.2.12"
|
||||
@ -5342,36 +5342,36 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.4.6
|
||||
storybook: ^8.4.7
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
checksum: 10c0/36d79c3aeb3d27f4ba966d62302e13fc17fd7b450dbfbcf538adfc6df3cfecb13c92f9d2542871fa747a77d7c770e413b358623049135355fb01454d6eb52d9a
|
||||
checksum: 10c0/1cb87811f9c7bad087dca752fb0d6483c237cb5776abea59cb555d8fce9ca14f4d5487725f5d8679a49f7e3f38bbe84189703498a31f2a9aa306f9fb3c8e65c8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/builder-vite@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/builder-vite@npm:8.4.6"
|
||||
"@storybook/builder-vite@npm:8.4.7, @storybook/builder-vite@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/builder-vite@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/csf-plugin": "npm:8.4.6"
|
||||
"@storybook/csf-plugin": "npm:8.4.7"
|
||||
browser-assert: "npm:^1.2.1"
|
||||
ts-dedent: "npm:^2.0.0"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
storybook: ^8.4.7
|
||||
vite: ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||
checksum: 10c0/36998ffea04023a9f634ebbafe0d1ab3bd3e7c7fec8e8e6c4caef3ce0c94ce01fa44f332f40d0053edb788548f95096baf8561cd35c23fe3c9bcfd872f74f631
|
||||
checksum: 10c0/138651b9042356972580a121eb3116c745f9fbc8b188ae0a5e543070dc54fcb6c1f14d35bc0cd1294ee763993a5f0e3a30cbe92508e74d183fed04a4d4125591
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/components@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/components@npm:8.4.6"
|
||||
"@storybook/components@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/components@npm:8.4.7"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10c0/1622b2f12b6d18e5c495a623deb2930888b3e8b173a271cbe42a7cbd6e14e80b736c57792ea97d5269dff0e6c0db40385d3ea80ab6e46d4cb6e104aee6cac6bc
|
||||
checksum: 10c0/7c1eb12fe2310a306f3c2f77a499c3a0caeb4694d4af8dde418f3b2d2ac8a3549b3f56cdc4629b9c15d79177c72e8668dd781a71bf257948f799b0e9cba201fa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -5393,9 +5393,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/core@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/core@npm:8.4.6"
|
||||
"@storybook/core@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/core@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/csf": "npm:^0.1.11"
|
||||
better-opn: "npm:^3.0.2"
|
||||
@ -5413,18 +5413,18 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
prettier:
|
||||
optional: true
|
||||
checksum: 10c0/1e30268eec18458dd78ed4b97fb12ac47b2c3cb41ffcbe9e9f5934b3f0c83b0bfcb0c0d508926344779383cc5260f992dcd534ffffab3f05425c7cee8c90687c
|
||||
checksum: 10c0/0943ea7cd092739834ae4347cb46c66aa1c238ee9494af60345364f11568ee60d6290875a593808cd7aeb79715ae27365c2448e6ae5c644e316cd194af184755
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/csf-plugin@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/csf-plugin@npm:8.4.6"
|
||||
"@storybook/csf-plugin@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/csf-plugin@npm:8.4.7"
|
||||
dependencies:
|
||||
unplugin: "npm:^1.3.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/d771f36ee768c6ff62ecd930c6ff64a4ba45bdbb7f7fb41e5f4ffd02204e3f54b17ed091049b265a6d371922bf599bfe749eb9deabfcd7e2b4fb5a5444655241
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/da38e2422e474e323e237e569b3dd678af77d975a4a08fa36108e66c9228858e510246628e18b013bd859a4e674c1a3d0072952a71dac0d7058e03e7c3417b3f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -5454,24 +5454,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/instrumenter@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/instrumenter@npm:8.4.6"
|
||||
"@storybook/instrumenter@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/instrumenter@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@vitest/utils": "npm:^2.1.1"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/602017872236124dc9dfa77d6bc2c5987d540063f15c7ace83bf91060d9343fdbe113a61cba44e17cae2247aeeb69875ebf45ff66ce9c28d364d2d3638eb3ec8
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/bc0865fed7f3c8242cd97978257e3d48f1880ad01e9794cc45122c4bcc7cf4a498c6ff8deebffcc70332b4a096e98b00e695ac152e40d0ef2c23160009c86f5d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/manager-api@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/manager-api@npm:8.4.6"
|
||||
"@storybook/manager-api@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/manager-api@npm:8.4.7"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10c0/5921ec72df0be765bd398aa906186c9b121a8b3415a7e1a10014a8d17c44aec386b59de3d240017bfc925be00c40a4da8d26991b5fa39023f23ba8efe1b0d58e
|
||||
checksum: 10c0/a3aeed441a2cca1a8fac73336a853b389a00a1e7dbbbbcd54492a90f2f12f86e976235fd1272f27a606532fb7e0f82dec3f7ecd1f2b87b03ffa74b667830152a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -5484,34 +5484,34 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/preview-api@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/preview-api@npm:8.4.6"
|
||||
"@storybook/preview-api@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/preview-api@npm:8.4.7"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10c0/63967f4813c75e410634bff20189b5a670a061cfeeaa601ec07f0de82e2b4955af292836030d5a8432c3c7e48968285e121ed2bb55d2b5c70d17dbb4ada3c051
|
||||
checksum: 10c0/86e8dd8e46b20a4cab99655ded093a76ae5a2b2b9ab03af57292022c8143d76e0f76a137f8768b8f6847fd1b522abf3dee8504f0ba5ff16b5779120d3875967c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react-dom-shim@npm:8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/react-dom-shim@npm:8.4.6"
|
||||
"@storybook/react-dom-shim@npm:8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/react-dom-shim@npm:8.4.7"
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/b97c6faa3adc3efe1b7b6f5e38476e040c0a988b14db68e368d704c68f3f4d4bf7866b36607c118a0483242921b34944b5f5f72614d9852476476f6ead462e5c
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/5db1306c844a36264587836860d17f3fd44e5981a2417e66ccb0699d2b05364736f29df2ebc605ae19a7f7b9b9d6a19845771c3052b167ce27702e20337cd334
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react-vite@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/react-vite@npm:8.4.6"
|
||||
"@storybook/react-vite@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/react-vite@npm:8.4.7"
|
||||
dependencies:
|
||||
"@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.4.2"
|
||||
"@rollup/pluginutils": "npm:^5.0.2"
|
||||
"@storybook/builder-vite": "npm:8.4.6"
|
||||
"@storybook/react": "npm:8.4.6"
|
||||
"@storybook/builder-vite": "npm:8.4.7"
|
||||
"@storybook/react": "npm:8.4.7"
|
||||
find-up: "npm:^5.0.0"
|
||||
magic-string: "npm:^0.30.0"
|
||||
react-docgen: "npm:^7.0.0"
|
||||
@ -5520,61 +5520,61 @@ __metadata:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.4.6
|
||||
storybook: ^8.4.7
|
||||
vite: ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||
checksum: 10c0/9f81a19461dbbf11932a13f8fb611dbcd95fbfa695ee5536daf7e078bf0feb5ddda2738606073826131e3fee710e230dce9042e3f7f985203392376aa8407643
|
||||
checksum: 10c0/105d967cc7aa9168b60723b6325d1d011836a2d6a5b9a4e45a13a64ccae26b7794fb3eb70042ab4b4af2af705078e34250c834bfe305c090b3dd22cf67301978
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react@npm:8.4.6, @storybook/react@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/react@npm:8.4.6"
|
||||
"@storybook/react@npm:8.4.7, @storybook/react@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/react@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/components": "npm:8.4.6"
|
||||
"@storybook/components": "npm:8.4.7"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/manager-api": "npm:8.4.6"
|
||||
"@storybook/preview-api": "npm:8.4.6"
|
||||
"@storybook/react-dom-shim": "npm:8.4.6"
|
||||
"@storybook/theming": "npm:8.4.6"
|
||||
"@storybook/manager-api": "npm:8.4.7"
|
||||
"@storybook/preview-api": "npm:8.4.7"
|
||||
"@storybook/react-dom-shim": "npm:8.4.7"
|
||||
"@storybook/theming": "npm:8.4.7"
|
||||
peerDependencies:
|
||||
"@storybook/test": 8.4.6
|
||||
"@storybook/test": 8.4.7
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta
|
||||
storybook: ^8.4.6
|
||||
storybook: ^8.4.7
|
||||
typescript: ">= 4.2.x"
|
||||
peerDependenciesMeta:
|
||||
"@storybook/test":
|
||||
optional: true
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 10c0/1441f8ab3be91757647c6b1a05eb1ef0d78a454ffd14b01a14fdde00e92a8be8fc7c8408c4670b46bc20a5a04995514f0890e98ed6ee35c362ff36141da02f02
|
||||
checksum: 10c0/9ca588446171491458e9adb5f9cf69b17517feddb4edd876da495843a45fa48a9c9272d4823090546e24a78dd7a93f1dcedef96257054383eb5678bfae6ccc09
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/test@npm:8.4.6, @storybook/test@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/test@npm:8.4.6"
|
||||
"@storybook/test@npm:8.4.7, @storybook/test@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/test@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/csf": "npm:^0.1.11"
|
||||
"@storybook/global": "npm:^5.0.0"
|
||||
"@storybook/instrumenter": "npm:8.4.6"
|
||||
"@storybook/instrumenter": "npm:8.4.7"
|
||||
"@testing-library/dom": "npm:10.4.0"
|
||||
"@testing-library/jest-dom": "npm:6.5.0"
|
||||
"@testing-library/user-event": "npm:14.5.2"
|
||||
"@vitest/expect": "npm:2.0.5"
|
||||
"@vitest/spy": "npm:2.0.5"
|
||||
peerDependencies:
|
||||
storybook: ^8.4.6
|
||||
checksum: 10c0/fbf7c2ac7773a7fe18145876eb67491ce90b000ba5f8e364a319569e56d56e706fdd1c7ef24d3ab2ffa3dfcdb92377d8050c8ffbd457d2d8b613aba2a4845a04
|
||||
storybook: ^8.4.7
|
||||
checksum: 10c0/4b100eacdca6d016a08358b1bf4c17f36450dffc9005557e0184814e546e71d200afccfb652fd2d45404fbd15e75f61fb4b93d869694249769ca919a0a2111f1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/theming@npm:8.4.6, @storybook/theming@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "@storybook/theming@npm:8.4.6"
|
||||
"@storybook/theming@npm:8.4.7, @storybook/theming@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "@storybook/theming@npm:8.4.7"
|
||||
peerDependencies:
|
||||
storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0
|
||||
checksum: 10c0/7d9c8e5ef2c1d974cd5258301350a2345890326e7be7a5ed6bdd0db70fd1648c0bbb8ee1d905f8e66fa57b75c47aefe7ec9772ec0bfb9691d127dcc19286e4c9
|
||||
checksum: 10c0/20a4975478063cea616ce6ab6b1e9ec181af1424280678ed74dc5afc15b828c043e843696a1643601331c4fd266169ec4bcc5bb43fd2f1f3c01c0e21443a658a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -20174,11 +20174,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"storybook@npm:^8.4.6":
|
||||
version: 8.4.6
|
||||
resolution: "storybook@npm:8.4.6"
|
||||
"storybook@npm:^8.4.7":
|
||||
version: 8.4.7
|
||||
resolution: "storybook@npm:8.4.7"
|
||||
dependencies:
|
||||
"@storybook/core": "npm:8.4.6"
|
||||
"@storybook/core": "npm:8.4.7"
|
||||
peerDependencies:
|
||||
prettier: ^2 || ^3
|
||||
peerDependenciesMeta:
|
||||
@ -20188,7 +20188,7 @@ __metadata:
|
||||
getstorybook: ./bin/index.cjs
|
||||
sb: ./bin/index.cjs
|
||||
storybook: ./bin/index.cjs
|
||||
checksum: 10c0/e15249718c1efab3d3d05f3152df28fc8f7e2e988bf7414cd4abf2adfb5d6c3b802f05dad5be0521c30d0ba43e55abf516e6f874b0671e0d1e84a7096cb47d3d
|
||||
checksum: 10c0/795b79950b88b41ee0158fe2e2583a8ce97ff843c054f91e3c55310967b9e5c4e4d72814773380b543c33bd6d57ce6b5f377ce93ce73962e803b250a751be37c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -21954,14 +21954,15 @@ __metadata:
|
||||
"@observablehq/plot": "npm:^0.6.16"
|
||||
"@react-hook/resize-observer": "npm:^2.0.2"
|
||||
"@rollup/plugin-node-resolve": "npm:^15.3.0"
|
||||
"@storybook/addon-essentials": "npm:^8.4.6"
|
||||
"@storybook/addon-interactions": "npm:^8.4.6"
|
||||
"@storybook/addon-links": "npm:^8.4.6"
|
||||
"@storybook/blocks": "npm:^8.4.6"
|
||||
"@storybook/react": "npm:^8.4.6"
|
||||
"@storybook/react-vite": "npm:^8.4.6"
|
||||
"@storybook/test": "npm:^8.4.6"
|
||||
"@storybook/theming": "npm:^8.4.6"
|
||||
"@storybook/addon-essentials": "npm:^8.4.7"
|
||||
"@storybook/addon-interactions": "npm:^8.4.7"
|
||||
"@storybook/addon-links": "npm:^8.4.7"
|
||||
"@storybook/blocks": "npm:^8.4.7"
|
||||
"@storybook/builder-vite": "npm:^8.4.7"
|
||||
"@storybook/react": "npm:^8.4.7"
|
||||
"@storybook/react-vite": "npm:^8.4.7"
|
||||
"@storybook/test": "npm:^8.4.7"
|
||||
"@storybook/theming": "npm:^8.4.7"
|
||||
"@table-nav/core": "npm:^0.0.7"
|
||||
"@table-nav/react": "npm:^0.0.7"
|
||||
"@tanstack/react-table": "npm:^8.20.5"
|
||||
@ -22039,7 +22040,7 @@ __metadata:
|
||||
sharp: "npm:^0.33.5"
|
||||
shell-quote: "npm:^1.8.2"
|
||||
sprintf-js: "npm:^1.1.3"
|
||||
storybook: "npm:^8.4.6"
|
||||
storybook: "npm:^8.4.7"
|
||||
storybook-dark-mode: "npm:^4.0.2"
|
||||
throttle-debounce: "npm:^5.0.2"
|
||||
tinycolor2: "npm:^1.6.0"
|
||||
|
Loading…
Reference in New Issue
Block a user