mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a8e08433d | |||
| 630e46d4ba | |||
| f41ac1d5e3 | |||
| 0024f0f3e8 | |||
| 8a3d9628ba | |||
| 7c2265f3e3 | |||
| 4f6c2ee39b | |||
| a1e4e807cc | |||
| 5c85b2b786 | |||
| 4879e90e91 | |||
| a61310afc3 | |||
| 80c781bf4c | |||
| 33400e65ff | |||
| 7b58949027 | |||
| 3be96c949d | |||
| 052645e0df | |||
| 3abc1ac3d7 | |||
| e7ed962944 | |||
| d99102b8e3 | |||
| abe6d6a6ba | |||
| 4eb215b99d | |||
| 404f7eaac0 | |||
| 28dd9410fe | |||
| b308334038 | |||
| 964751aae1 | |||
| d3c771efb1 | |||
| aca197037d | |||
| 5734a7bc7a | |||
| bed191186c | |||
| 9809ca634d | |||
| e867bcb398 | |||
| 3e4ba1bf72 | |||
| d21182f7e0 | |||
| 49e1fc9133 | |||
| 195ee98424 | |||
| 3c3eec73aa | |||
| 6065ee931f |
+6423
-6447
File diff suppressed because one or more lines are too long
+20
-16
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"productName": "Wave",
|
||||
"description": "An Open-Source, AI-Native, Terminal Built for Seamless Workflows",
|
||||
"version": "0.7.1",
|
||||
"version": "0.7.2",
|
||||
"main": "dist/emain.js",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
@@ -23,7 +23,6 @@
|
||||
"@table-nav/react": "^0.0.7",
|
||||
"@tanstack/match-sorter-utils": "^8.8.4",
|
||||
"@tanstack/react-table": "^8.10.3",
|
||||
"@types/semver": "^7.5.6",
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"classnames": "^2.3.1",
|
||||
@@ -33,23 +32,28 @@
|
||||
"electron-updater": "^6.1.8",
|
||||
"framer-motion": "^10.16.16",
|
||||
"mobx": "6.12",
|
||||
"mobx-react": "^7.5.0",
|
||||
"mobx-preact": "^7.5.0",
|
||||
"monaco-editor": "^0.44.0",
|
||||
"mustache": "^4.2.0",
|
||||
"node-fetch": "^3.2.10",
|
||||
"overlayscrollbars": "^2.6.1",
|
||||
"overlayscrollbars-react": "^0.5.5",
|
||||
"papaparse": "^5.4.1",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"preact": "^10.20.1",
|
||||
"react": "npm:@preact/compat",
|
||||
"react-dom": "npm:@preact/compat",
|
||||
"react-markdown": "^9.0.0",
|
||||
"remark": "^15.0.1",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"sprintf-js": "^1.1.2",
|
||||
"throttle-debounce": "^5.0.0",
|
||||
"tsx-control-statements": "^4.1.1",
|
||||
"tsx-control-statements": "^5.1.1",
|
||||
"uuid": "^9.0.0",
|
||||
"winston": "^3.8.2",
|
||||
"xterm": "^5.0.0",
|
||||
"xterm-addon-web-links": "^0.9.0"
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-serialize": "^0.11.0",
|
||||
"xterm-addon-web-links": "^0.9.0",
|
||||
"xterm-addon-webgl": "^0.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.17.10",
|
||||
@@ -66,24 +70,24 @@
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@types/classnames": "^2.3.1",
|
||||
"@types/electron": "^1.6.10",
|
||||
"@types/node": "20.11.0",
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/papaparse": "^5.3.10",
|
||||
"@types/react": "^18.0.12",
|
||||
"@types/semver": "^7.5.6",
|
||||
"@types/sprintf-js": "^1.1.3",
|
||||
"@types/throttle-debounce": "^5.0.1",
|
||||
"@types/uuid": "9.0.7",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"copy-webpack-plugin": "^12.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"electron": "29.0.1",
|
||||
"electron": "^29.0.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron-builder-squirrel-windows": "^24.13.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"http-server": "^14.1.1",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^11.0.0",
|
||||
"less-loader": "^12.0.0",
|
||||
"lodash-webpack-plugin": "^0.11.6",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"prettier": "^2.8.8",
|
||||
@@ -94,11 +98,11 @@
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^4.9.1",
|
||||
"webpack-dev-server": "^5.0.4",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"yaml": "^2.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<base href="../" />
|
||||
<script charset="UTF-8" src="dist-dev/waveterm.js"></script>
|
||||
<link rel="stylesheet" href="public/bulma-0.9.4.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="dist-dev/waveterm.css" />
|
||||
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css">
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
|
||||
+6
-6
@@ -5,14 +5,14 @@
|
||||
<base href="../" />
|
||||
<script charset="UTF-8" src="dist/waveterm.js"></script>
|
||||
<link rel="stylesheet" href="public/bulma-0.9.4.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="dist/waveterm.css" />
|
||||
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
--scrollbar-background-color: var(--app-bg-color);
|
||||
--scrollbar-thumb-color: rgba(255, 255, 255, 0.3);
|
||||
--scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.5);
|
||||
--scrollbar-thumb-active-color: rgba(255, 255, 255, 0.6);
|
||||
|
||||
/* code color */
|
||||
--pre-bg-color: rgb(0, 0, 0);
|
||||
@@ -86,6 +87,7 @@
|
||||
--form-element-border-color: rgba(241, 246, 243, 0.15);
|
||||
--form-element-bg-color: var(--app-bg-color);
|
||||
--form-element-text-color: var(--app-text-primary-color);
|
||||
--form-element-primary-text-color: var(--app-text-primary-color);
|
||||
--form-element-label-color: var(--app-text-secondary-color);
|
||||
--form-element-primary-color: var(--app-accent-color);
|
||||
--form-element-secondary-color: rgba(255, 255, 255, 0.2);
|
||||
@@ -112,7 +114,7 @@
|
||||
--hotkey-text-color: var(--app-text-secondary-color);
|
||||
|
||||
/* sidebar colors */
|
||||
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
|
||||
--sidebar-highlight-color: var(--app-accent-bg-color);
|
||||
--sidebar-font-size: 15px;
|
||||
--sidebar-line-height: 1.5;
|
||||
--sidebar-font-weight: normal;
|
||||
@@ -186,4 +188,11 @@
|
||||
--datepicker-header-fade-color: rgba(255, 255, 255, 0.4);
|
||||
--datepicker-year-header-bg-color: rgba(255, 255, 255, 0.2); /* Light grey background */
|
||||
--datepicker-year-header-border-color: rgba(241, 246, 243, 0.15); /* Light grey border */
|
||||
|
||||
/* OverlayScrollbars styling */
|
||||
.os-scrollbar {
|
||||
--os-handle-bg: var(--scrollbar-thumb-color);
|
||||
--os-handle-bg-hover: var(--scrollbar-thumb-hover-color);
|
||||
--os-handle-bg-active: var(--scrollbar-thumb-active-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/* Copyright 2024, Command Line Inc.
|
||||
SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
@import "./default.css";
|
||||
@import "./term-default.css";
|
||||
@import "./term-light.css";
|
||||
@import url("./term-default.css");
|
||||
@import url("./term-light.css");
|
||||
|
||||
:root {
|
||||
--app-bg-color: #fefefe;
|
||||
@@ -25,11 +24,6 @@
|
||||
--tab-white: rgb(0, 0, 0, 0.6);
|
||||
--tab-mint: rgb(70, 235, 156);
|
||||
|
||||
/* button colors */
|
||||
--button-text-color: rgb(50, 50, 50); /* Dark gray for light theme */
|
||||
--button-primary-color: #fefefe;
|
||||
--button-secondary-bg-color: rgba(200, 200, 200, 0.3); /* Semi-transparent light gray */
|
||||
|
||||
/* table colors */
|
||||
--table-thead-border-top-color: rgba(0, 0, 0, 0.2);
|
||||
--table-thead-border-bottom-color: rgba(0, 0, 0, 0.3);
|
||||
@@ -42,7 +36,8 @@
|
||||
/* form colors */
|
||||
--form-element-border-color: rgba(0, 0, 0, 0.3);
|
||||
--form-element-bg-color: var(--app-bg-color);
|
||||
--form-element-text-color: var(--app-text-color);
|
||||
--form-element-text-color: var(--app-text-primary-color);
|
||||
--form-element-primary-text-color: var(--app-text-primary-color);
|
||||
--form-element-label-color: rgba(0, 0, 0, 0.6);
|
||||
--form-element-secondary-color: rgba(0, 0, 0, 0.09);
|
||||
--form-element-icon-color: rgb(0, 0, 0, 0.6);
|
||||
@@ -62,6 +57,7 @@
|
||||
--scrollbar-background-color: var(--app-bg-color);
|
||||
--scrollbar-thumb-color: rgba(0, 0, 0, 0.2);
|
||||
--scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.4);
|
||||
--scrollbar-thumb-active-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
/* line color */
|
||||
--line-actions-bg-color: rgba(0, 0, 0, 0.1);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
@import url("./default.css") screen;
|
||||
|
||||
@import url("./light.css") screen and (prefers-color-scheme: light);
|
||||
+3
-3
@@ -44,7 +44,7 @@ rm -rf bin/
|
||||
rm -rf build/
|
||||
node_modules/.bin/webpack --env prod
|
||||
WAVESRV_VERSION=$(node -e 'console.log(require("./version.js"))')
|
||||
WAVESHELL_VERSION=v0.5
|
||||
WAVESHELL_VERSION=v0.6
|
||||
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
|
||||
function buildWaveShell {
|
||||
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
|
||||
@@ -69,7 +69,7 @@ rm -rf bin/
|
||||
rm -rf build/
|
||||
node_modules/.bin/webpack --env prod
|
||||
WAVESRV_VERSION=$(node -e 'console.log(require("./version.js"))')
|
||||
WAVESHELL_VERSION=v0.5
|
||||
WAVESHELL_VERSION=v0.6
|
||||
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
|
||||
function buildWaveShell {
|
||||
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
|
||||
@@ -96,7 +96,7 @@ CGO_ENABLED=1 go build -tags "osusergo,netgo,sqlite_omit_load_extension" -ldflag
|
||||
```bash
|
||||
# @scripthaus command fullbuild-waveshell
|
||||
set -e
|
||||
WAVESHELL_VERSION=v0.5
|
||||
WAVESHELL_VERSION=v0.6
|
||||
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
|
||||
function buildWaveShell {
|
||||
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
|
||||
|
||||
+77
-39
@@ -251,6 +251,13 @@ input[type="checkbox"] {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flex-centered-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a.a-block {
|
||||
display: block;
|
||||
}
|
||||
@@ -786,6 +793,75 @@ a.a-block {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.conn-dropdown {
|
||||
width: 412px;
|
||||
|
||||
.lefticon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.globe-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
fill: var(--app-text-secondary-color);
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 8px;
|
||||
circle {
|
||||
stroke: var(--app-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wave-dropdown-display {
|
||||
bottom: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-colors,
|
||||
.tab-icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.tab-color-sep,
|
||||
.tab-icon-sep {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-icon,
|
||||
.tab-icon-icon {
|
||||
width: 1.1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tab-color-name,
|
||||
.tab-icon-name {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
min-width: 70px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-select,
|
||||
.tab-icon-select {
|
||||
cursor: pointer;
|
||||
margin: 3px;
|
||||
&:hover {
|
||||
outline: 2px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -847,7 +923,7 @@ a.a-block {
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
input:not(.wave-input) {
|
||||
padding: 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
@@ -858,44 +934,6 @@ a.a-block {
|
||||
}
|
||||
}
|
||||
|
||||
.tab-colors,
|
||||
.tab-icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.tab-color-sep,
|
||||
.tab-icon-sep {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-icon,
|
||||
.tab-icon-icon {
|
||||
width: 1.1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tab-color-name,
|
||||
.tab-icon-name {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
min-width: 70px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-select,
|
||||
.tab-icon-select {
|
||||
cursor: pointer;
|
||||
margin: 3px;
|
||||
&:hover {
|
||||
outline: 2px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-text {
|
||||
margin-left: 20px;
|
||||
|
||||
|
||||
+10
-9
@@ -1,14 +1,15 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import React, { PureComponent } from "preact/compat";
|
||||
import { createRef, RefObject } from "preact";
|
||||
import * as mobxReact from "mobx-preact";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalCommandRunner, GlobalModel } from "@/models";
|
||||
import { GlobalModel } from "@/models";
|
||||
import { isBlank } from "@/util/util";
|
||||
import { WorkspaceView } from "./workspace/workspaceview";
|
||||
import { PluginsView } from "./pluginsview/pluginsview";
|
||||
@@ -28,9 +29,9 @@ import "./app.less";
|
||||
dayjs.extend(localizedFormat);
|
||||
|
||||
@mobxReact.observer
|
||||
class App extends React.Component<{}, {}> {
|
||||
class App extends PureComponent<{}, {}> {
|
||||
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
|
||||
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||
mainContentRef: RefObject<HTMLDivElement> = createRef();
|
||||
|
||||
constructor(props: {}) {
|
||||
super(props);
|
||||
@@ -101,7 +102,7 @@ class App extends React.Component<{}, {}> {
|
||||
return (
|
||||
<div id="main" className={"platform-" + platform} onContextMenu={this.handleContextMenu}>
|
||||
<div ref={this.mainContentRef} className="main-content">
|
||||
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
<MainSideBar parentRef={this.mainContentRef} />
|
||||
<div className="session-view" />
|
||||
</div>
|
||||
<If condition={dcWait}>
|
||||
@@ -123,7 +124,7 @@ class App extends React.Component<{}, {}> {
|
||||
const mainSidebarCollapsed = GlobalModel.mainSidebarModel.getCollapsed();
|
||||
const rightSidebarCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
|
||||
const activeMainView = GlobalModel.activeMainView.get();
|
||||
const lightDarkClass = GlobalModel.isThemeDark() ? "is-dark" : "is-light";
|
||||
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
|
||||
return (
|
||||
<div
|
||||
key={"version-" + renderVersion}
|
||||
@@ -151,7 +152,7 @@ class App extends React.Component<{}, {}> {
|
||||
</div>
|
||||
</If>
|
||||
<div ref={this.mainContentRef} className="main-content">
|
||||
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
<MainSideBar parentRef={this.mainContentRef} />
|
||||
<ErrorBoundary>
|
||||
<PluginsView />
|
||||
<WorkspaceView />
|
||||
@@ -160,7 +161,7 @@ class App extends React.Component<{}, {}> {
|
||||
<ConnectionsView model={remotesModel} />
|
||||
<ClientSettingsView model={remotesModel} />
|
||||
</ErrorBoundary>
|
||||
<RightSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
<RightSideBar parentRef={this.mainContentRef} />
|
||||
</div>
|
||||
<ModalsProvider />
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import React, { PureComponent } from "preact/compat";
|
||||
import * as mobxReact from "mobx-preact";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If, For } from "tsx-control-statements/components";
|
||||
@@ -22,7 +22,7 @@ type BookmarkProps = {
|
||||
bookmark: BookmarkType;
|
||||
};
|
||||
|
||||
class BookmarkKeybindings extends React.Component<{}, {}> {
|
||||
class BookmarkKeybindings extends PureComponent<{}, {}> {
|
||||
@boundMethod
|
||||
componentDidMount(): void {
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
@@ -76,7 +76,7 @@ class BookmarkKeybindings extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class Bookmark extends React.Component<BookmarkProps, {}> {
|
||||
class Bookmark extends PureComponent<BookmarkProps, {}> {
|
||||
@boundMethod
|
||||
handleDeleteClick(): void {
|
||||
let { bookmark } = this.props;
|
||||
@@ -232,7 +232,7 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class BookmarksView extends React.Component<{}, {}> {
|
||||
class BookmarksView extends PureComponent<{}, {}> {
|
||||
@boundMethod
|
||||
handleClose() {
|
||||
GlobalModel.bookmarksModel.closeView();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import React, { PureComponent } from "preact/compat";
|
||||
import * as mobxReact from "mobx-preact";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
@@ -14,7 +14,7 @@ import * as appconst from "@/app/appconst";
|
||||
import "./clientsettings.less";
|
||||
import { MainView } from "../common/elements/mainview";
|
||||
|
||||
class ClientSettingsKeybindings extends React.Component<{}, {}> {
|
||||
class ClientSettingsKeybindings extends PureComponent<{}, {}> {
|
||||
componentDidMount() {
|
||||
let clientSettingsViewModel = GlobalModel.clientSettingsViewModel;
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
@@ -34,7 +34,7 @@ class ClientSettingsKeybindings extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
|
||||
class ClientSettingsView extends PureComponent<{ model: RemotesModel }, { hoveredItemId: string }> {
|
||||
errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" });
|
||||
|
||||
@boundMethod
|
||||
@@ -64,11 +64,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeTheme(theme: string): void {
|
||||
if (GlobalModel.getTheme() == theme) {
|
||||
handleChangeThemeSource(themeSource: NativeThemeSource): void {
|
||||
if (GlobalModel.getThemeSource() == themeSource) {
|
||||
return;
|
||||
}
|
||||
const prtn = GlobalCommandRunner.setTheme(theme, false);
|
||||
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
|
||||
getApi().setNativeThemeSource(themeSource);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -111,11 +112,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
return availableFontFamilies;
|
||||
}
|
||||
|
||||
getThemes(): DropdownItem[] {
|
||||
const themes: DropdownItem[] = [];
|
||||
themes.push({ label: "Dark", value: "dark" });
|
||||
themes.push({ label: "Light", value: "light" });
|
||||
return themes;
|
||||
getThemeSources(): DropdownItem[] {
|
||||
const themeSources: DropdownItem[] = [];
|
||||
themeSources.push({ label: "Dark", value: "dark" });
|
||||
themeSources.push({ label: "Light", value: "light" });
|
||||
themeSources.push({ label: "System", value: "system" });
|
||||
return themeSources;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -190,7 +192,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
);
|
||||
const curFontSize = GlobalModel.getTermFontSize();
|
||||
const curFontFamily = GlobalModel.getTermFontFamily();
|
||||
const curTheme = GlobalModel.getTheme();
|
||||
const curTheme = GlobalModel.getThemeSource();
|
||||
|
||||
return (
|
||||
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
|
||||
@@ -225,9 +227,9 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
<div className="settings-input">
|
||||
<Dropdown
|
||||
className="theme-dropdown"
|
||||
options={this.getThemes()}
|
||||
options={this.getThemeSources()}
|
||||
defaultValue={curTheme}
|
||||
onChange={this.handleChangeTheme}
|
||||
onChange={this.handleChangeThemeSource}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -281,7 +283,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
text={isBlank(openAIOpts.baseurl) ? "openai default" : openAIOpts.baseurl}
|
||||
value={openAIOpts.baseurl ?? ""}
|
||||
onChange={this.inlineUpdateOpenAIBaseURL}
|
||||
maxLength={10}
|
||||
maxLength={200}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
border-radius: 6px;
|
||||
height: auto;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
|
||||
@@ -21,13 +20,17 @@
|
||||
}
|
||||
|
||||
&.primary {
|
||||
color: var(--form-element-text-color);
|
||||
color: var(--form-element-primary-text-color);
|
||||
background: var(--form-element-primary-color);
|
||||
i {
|
||||
fill: var(--form-element-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.danger {
|
||||
background: var(--app-error-color);
|
||||
}
|
||||
|
||||
&.primary.outlined {
|
||||
background: none;
|
||||
border: 1px solid var(--form-element-primary-color);
|
||||
@@ -37,6 +40,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.greyoutlined {
|
||||
background: none;
|
||||
border: 1px solid var(--app-text-secondary-color);
|
||||
|
||||
i {
|
||||
fill: var(--app-text-secondary-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.outlined,
|
||||
&.primary.greyoutlined {
|
||||
&.hover-danger:hover {
|
||||
color: var(--form-element-primary-text-color);
|
||||
border: 1px solid var(--app-error-color);
|
||||
background: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.outlined.danger {
|
||||
background: none;
|
||||
border: 1px solid var(--app-error-color);
|
||||
|
||||
i {
|
||||
fill: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.greytext {
|
||||
color: var(--app-text-secondary-color);
|
||||
}
|
||||
|
||||
&.primary.ghost {
|
||||
background: none;
|
||||
i {
|
||||
@@ -44,6 +78,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.ghost.danger {
|
||||
background: none;
|
||||
i {
|
||||
fill: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: var(--form-element-text-color);
|
||||
background: var(--form-element-secondary-color);
|
||||
@@ -57,6 +98,11 @@
|
||||
border: 1px solid var(--form-element-text-color);
|
||||
}
|
||||
|
||||
&.secondary.outlined.danger {
|
||||
background: none;
|
||||
border: 1px solid var(--app-error-color);
|
||||
}
|
||||
|
||||
&.secondary.ghost {
|
||||
background: none;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import * as React from "react";
|
||||
import React, { PureComponent, ReactNode, CSSProperties } from "preact/compat";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
|
||||
import "./button.less";
|
||||
|
||||
interface ButtonProps {
|
||||
children: React.ReactNode;
|
||||
children: ReactNode;
|
||||
onClick?: () => void;
|
||||
disabled?: boolean;
|
||||
leftIcon?: React.ReactNode;
|
||||
rightIcon?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
leftIcon?: ReactNode;
|
||||
rightIcon?: ReactNode;
|
||||
style?: CSSProperties;
|
||||
autoFocus?: boolean;
|
||||
className?: string;
|
||||
termInline?: boolean;
|
||||
}
|
||||
|
||||
class Button extends React.Component<ButtonProps> {
|
||||
class Button extends PureComponent<ButtonProps> {
|
||||
static defaultProps = {
|
||||
style: {},
|
||||
className: "primary",
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobx from "mobx";
|
||||
import { PureComponent, ReactNode } from "preact/compat";
|
||||
import cn from "classnames";
|
||||
|
||||
import "./checkbox.less";
|
||||
|
||||
class Checkbox extends React.Component<
|
||||
class Checkbox extends PureComponent<
|
||||
{
|
||||
checked?: boolean;
|
||||
defaultChecked?: boolean;
|
||||
onChange: (value: boolean) => void;
|
||||
label: React.ReactNode;
|
||||
label: ReactNode;
|
||||
className?: string;
|
||||
id?: string;
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import React, { PureComponent } from "preact/compat";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
@@ -11,7 +11,7 @@ import { ReactComponent as CopyIcon } from "@/assets/icons/history/copy.svg";
|
||||
|
||||
import "./cmdstrcode.less";
|
||||
|
||||
class CmdStrCode extends React.Component<
|
||||
class CmdStrCode extends PureComponent<
|
||||
{
|
||||
cmdstr: string;
|
||||
onUse: () => void;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import React, { PureComponent } from "preact/compat";
|
||||
|
||||
function renderCmdText(text: string): any {
|
||||
return <span>⌘{text}</span>;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--form-element-bg-color);
|
||||
|
||||
input {
|
||||
outline: none !important;
|
||||
@@ -29,6 +30,7 @@
|
||||
height: 100%;
|
||||
padding: 0 !important;
|
||||
cursor: default !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
.fa-calendar {
|
||||
@@ -99,6 +101,7 @@
|
||||
background-color: var(--datepicker-cell-hover-bg-color);
|
||||
}
|
||||
&.selected {
|
||||
color: var(--form-element-primary-text-color);
|
||||
background-color: var(--form-element-primary-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -157,6 +160,7 @@
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: var(--form-element-primary-text-color);
|
||||
background-color: var(--form-element-primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useState, useEffect, useRef, createRef } from "react";
|
||||
import { RefObject, FunctionComponent, createRef, Fragment } from "preact";
|
||||
import { useState, useEffect, useRef, CSSProperties } from "preact/compat";
|
||||
import * as mobx from "mobx";
|
||||
import ReactDOM from "react-dom";
|
||||
import dayjs from "dayjs";
|
||||
import cs from "classnames";
|
||||
import cn from "classnames";
|
||||
import { Button } from "@/elements";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { GlobalModel } from "@/models";
|
||||
@@ -11,7 +12,7 @@ import { v4 as uuidv4 } from "uuid";
|
||||
import "./datepicker.less";
|
||||
|
||||
interface YearRefs {
|
||||
[key: number]: React.RefObject<HTMLDivElement>;
|
||||
[key: number]: RefObject<HTMLDivElement>;
|
||||
}
|
||||
|
||||
type DatePickerProps = {
|
||||
@@ -20,7 +21,7 @@ type DatePickerProps = {
|
||||
format?: string;
|
||||
};
|
||||
|
||||
const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/YYYY", onSelectDate }) => {
|
||||
const DatePicker: FunctionComponent<DatePickerProps> = ({ selectedDate, format = "MM/DD/YYYY", onSelectDate }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selDate, setSelDate] = useState(dayjs(selectedDate)); // Initialize with dayjs object
|
||||
const [showYearAccordion, setShowYearAccordion] = useState(false);
|
||||
@@ -39,8 +40,8 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
MM: selDate.format("MM"),
|
||||
DD: selDate.format("DD"),
|
||||
});
|
||||
let curUuid = uuidv4();
|
||||
let keybindsRegistered = mobx.observable.box(false, {
|
||||
const curUuid = uuidv4();
|
||||
const keybindsRegistered = mobx.observable.box(false, {
|
||||
name: "datepicker-keybinds-registered",
|
||||
});
|
||||
|
||||
@@ -90,7 +91,6 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
const newDate = dayjs(date);
|
||||
setSelDate(newDate); // Update selDate with the new dayjs object
|
||||
onSelectDate && onSelectDate(date); // Call parent's onSelectDate
|
||||
setIsOpen(false); // Close the picker
|
||||
};
|
||||
|
||||
const changeMonth = (delta: number) => {
|
||||
@@ -103,7 +103,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
return (
|
||||
<div className="day-picker-header">
|
||||
<div
|
||||
className={cs({ fade: showYearAccordion })}
|
||||
className={cn({ fade: showYearAccordion })}
|
||||
onClick={() => {
|
||||
if (!showYearAccordion) {
|
||||
setExpandedYear(selDate.year()); // Set expandedYear when opening accordion
|
||||
@@ -112,7 +112,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}}
|
||||
>
|
||||
{selDate.format("MMMM YYYY")}
|
||||
<span className={cs("dropdown-arrow", { fade: showYearAccordion })}></span>
|
||||
<span className={cn("dropdown-arrow", { fade: showYearAccordion })}></span>
|
||||
</div>
|
||||
<If condition={!showYearAccordion}>
|
||||
<div className="arrows">
|
||||
@@ -183,9 +183,9 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
|
||||
// Next month's filler days
|
||||
let overFlowIndex = 1;
|
||||
while (days.length < 42) {
|
||||
const fillerDayCount = days.length - daysInPreviousMonth - endDay.date();
|
||||
const dayDate = endDay.add(fillerDayCount + 1, "day");
|
||||
const dayDate = endDay.add(overFlowIndex++, "day");
|
||||
days.push(
|
||||
<div
|
||||
key={`next-month-day-${dayDate.format("YYYY-MM-DD")}`}
|
||||
@@ -200,7 +200,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
return days;
|
||||
};
|
||||
|
||||
const calculatePosition = (): React.CSSProperties => {
|
||||
const calculatePosition = (): CSSProperties => {
|
||||
if (wrapperRef.current) {
|
||||
const rect = wrapperRef.current.getBoundingClientRect();
|
||||
return {
|
||||
@@ -220,7 +220,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
|
||||
for (let year = startYear; year <= endYear; year++) {
|
||||
yearsRange.push(year);
|
||||
yearRefs.current[year] = React.createRef();
|
||||
yearRefs.current[year] = createRef();
|
||||
}
|
||||
|
||||
return yearsRange;
|
||||
@@ -251,14 +251,14 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
</div>
|
||||
<If condition={expandedYear === year}>
|
||||
<div
|
||||
className={cs("month-container", {
|
||||
className={cn("month-container", {
|
||||
expanded: expandedYear === year,
|
||||
})}
|
||||
>
|
||||
{Array.from({ length: 12 }, (_, i) => i + 1).map((month) => (
|
||||
<div
|
||||
key={month}
|
||||
className={cs("month", {
|
||||
className={cn("month", {
|
||||
selected: year === currentYear && month === selDate.month() + 1,
|
||||
})}
|
||||
onClick={() => handleMonthYearSelect(month, year)}
|
||||
@@ -301,7 +301,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
)
|
||||
: null;
|
||||
|
||||
const handleDatePartChange = (part, value) => {
|
||||
const handleDatePartChange = (part: string, value: string) => {
|
||||
const newDateParts = { ...dateParts, [part]: value };
|
||||
setDateParts(newDateParts);
|
||||
|
||||
@@ -312,7 +312,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
};
|
||||
|
||||
const handleArrowNavigation = (key, currentPart) => {
|
||||
const handleArrowNavigation = (key: string, currentPart: string) => {
|
||||
const currentIndex = formatParts.indexOf(currentPart);
|
||||
let targetInput;
|
||||
|
||||
@@ -327,9 +327,9 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event, currentPart) => {};
|
||||
const handleKeyDown = (event, currentPart: string) => {};
|
||||
|
||||
const handleFocus = (event, part) => {
|
||||
const handleFocus = (event, part: string) => {
|
||||
event.target.select();
|
||||
registerKeybindings(event, part);
|
||||
};
|
||||
@@ -341,74 +341,69 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
mobx.action(() => {
|
||||
keybindsRegistered.set(true);
|
||||
})();
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
let domain = "datepicker-" + curUuid + "-" + part;
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectLeft", (waveEvent) => {
|
||||
const keybindManager = GlobalModel.keybindManager;
|
||||
const domain = "datepicker-" + curUuid + "-" + part;
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectLeft", (_) => {
|
||||
handleArrowNavigation("ArrowLeft", part);
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectRight", (waveEvent) => {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectRight", (_) => {
|
||||
handleArrowNavigation("ArrowRight", part);
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:space", (waveEvent) => {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:space", (_) => {
|
||||
toggleModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:confirm", (_) => {
|
||||
toggleModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (_) => {
|
||||
closeModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:tab", (waveEvent) => {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:tab", (_) => {
|
||||
handleArrowNavigation("ArrowRight", part);
|
||||
return true;
|
||||
});
|
||||
for (let numpadKey = 0; numpadKey <= 9; numpadKey++) {
|
||||
keybindManager.registerKeybinding(
|
||||
"control",
|
||||
domain,
|
||||
"generic:numpad-" + numpadKey.toString(),
|
||||
(waveEvent) => {
|
||||
let currentPart = part;
|
||||
const maxLength = currentPart === "YYYY" ? 4 : 2;
|
||||
const newValue = event.target.value.length < maxLength ? event.target.value + numpadKey : numpadKey;
|
||||
let selectionTimeoutId = null;
|
||||
handleDatePartChange(currentPart, newValue);
|
||||
keybindManager.registerKeybinding("control", domain, "generic:numpad-" + numpadKey.toString(), (_) => {
|
||||
const currentPart = part;
|
||||
const maxLength = currentPart === "YYYY" ? 4 : 2;
|
||||
const newValue = event.target.value.length < maxLength ? event.target.value + numpadKey : numpadKey;
|
||||
let selectionTimeoutId = null;
|
||||
handleDatePartChange(currentPart, newValue);
|
||||
|
||||
// Clear any existing timeout
|
||||
if (selectionTimeoutId !== null) {
|
||||
clearTimeout(selectionTimeoutId);
|
||||
}
|
||||
|
||||
// Re-focus and select the input after state update
|
||||
selectionTimeoutId = setTimeout(() => {
|
||||
event.target.focus();
|
||||
event.target.select();
|
||||
}, 0);
|
||||
return true;
|
||||
// Clear any existing timeout
|
||||
if (selectionTimeoutId !== null) {
|
||||
clearTimeout(selectionTimeoutId);
|
||||
}
|
||||
);
|
||||
|
||||
// Re-focus and select the input after state update
|
||||
selectionTimeoutId = setTimeout(() => {
|
||||
event.target.focus();
|
||||
event.target.select();
|
||||
}, 0);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlur = (event, part) => {
|
||||
const handleBlur = (event, part: string) => {
|
||||
unregisterKeybindings(part);
|
||||
};
|
||||
|
||||
const unregisterKeybindings = (part) => {
|
||||
const unregisterKeybindings = (part: string) => {
|
||||
mobx.action(() => {
|
||||
keybindsRegistered.set(false);
|
||||
})();
|
||||
let domain = "datepicker-" + curUuid + "-" + part;
|
||||
const domain = "datepicker-" + curUuid + "-" + part;
|
||||
GlobalModel.keybindManager.unregisterDomain(domain);
|
||||
};
|
||||
|
||||
// Prevent use from selecting text in the input
|
||||
const handleMouseDown = (event, part) => {
|
||||
const handleMouseDown = (event, part: string) => {
|
||||
event.preventDefault();
|
||||
|
||||
handleFocus(event, part);
|
||||
@@ -456,14 +451,14 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
const inputRef = inputRefs.current[part];
|
||||
|
||||
return (
|
||||
<React.Fragment key={part}>
|
||||
<Fragment key={part}>
|
||||
{index > 0 && <span>{delimiter}</span>}
|
||||
<input
|
||||
readOnly
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={dateParts[part]}
|
||||
onChange={(e) => handleDatePartChange(part, e.target.value)}
|
||||
onChange={(e) => handleDatePartChange(part, (e.target as HTMLInputElement).value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, part)}
|
||||
onMouseDown={(e) => handleMouseDown(e, part)}
|
||||
onFocus={(e) => handleFocus(e, part)}
|
||||
@@ -472,7 +467,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
className="date-input"
|
||||
placeholder={part}
|
||||
/>
|
||||
</React.Fragment>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
<i
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
// Copyright 2023, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import { RefObject, createRef } from "preact";
|
||||
import React, { PureComponent, ReactNode, TargetedEvent, CSSProperties } from "preact/compat";
|
||||
import * as mobxReact from "mobx-preact";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
@@ -13,8 +14,8 @@ import { GlobalModel } from "@/models";
|
||||
import "./dropdown.less";
|
||||
|
||||
interface DropdownDecorationProps {
|
||||
startDecoration?: React.ReactNode;
|
||||
endDecoration?: React.ReactNode;
|
||||
startDecoration?: ReactNode;
|
||||
endDecoration?: ReactNode;
|
||||
}
|
||||
|
||||
interface DropdownProps {
|
||||
@@ -37,9 +38,9 @@ interface DropdownState {
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
wrapperRef: React.RefObject<HTMLDivElement>;
|
||||
menuRef: React.RefObject<HTMLDivElement>;
|
||||
class Dropdown extends PureComponent<DropdownProps, DropdownState> {
|
||||
wrapperRef: RefObject<HTMLDivElement>;
|
||||
menuRef: RefObject<HTMLDivElement>;
|
||||
timeoutId: any;
|
||||
curUuid: string;
|
||||
|
||||
@@ -51,9 +52,9 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
highlightedIndex: -1,
|
||||
isTouched: false,
|
||||
};
|
||||
this.wrapperRef = React.createRef();
|
||||
this.menuRef = React.createRef();
|
||||
this.curUuid == uuidv4();
|
||||
this.wrapperRef = createRef();
|
||||
this.menuRef = createRef();
|
||||
this.curUuid = uuidv4();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -100,6 +101,9 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
|
||||
@boundMethod
|
||||
handleClick() {
|
||||
if (!this.state.isOpen || !this.state.isTouched) {
|
||||
this.registerKeybindings();
|
||||
}
|
||||
this.toggleDropdown();
|
||||
}
|
||||
|
||||
@@ -109,6 +113,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
this.registerKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
registerKeybindings() {
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
let domain = "dropdown-" + this.curUuid;
|
||||
@@ -122,6 +127,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
|
||||
this.setState({ isOpen: false });
|
||||
this.unregisterKeybindings();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectAbove", (waveEvent) => {
|
||||
@@ -165,20 +171,22 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleBlur() {
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
unregisterKeybindings() {
|
||||
let domain = "dropdown-" + this.curUuid;
|
||||
GlobalModel.keybindManager.unregisterDomain(domain);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleKeyDown(event: React.KeyboardEvent) {}
|
||||
handleKeyDown(event) {}
|
||||
|
||||
@boundMethod
|
||||
handleSelect(value: string, event?: React.MouseEvent | React.KeyboardEvent) {
|
||||
handleSelect(value: string, event?: TargetedEvent) {
|
||||
const { onChange } = this.props;
|
||||
if (event) {
|
||||
event.stopPropagation(); // This stops the event from bubbling up to the wrapper
|
||||
@@ -189,6 +197,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
}
|
||||
onChange(value);
|
||||
this.setState({ isOpen: false, isTouched: true });
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -197,7 +206,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
calculatePosition(): React.CSSProperties {
|
||||
calculatePosition(): CSSProperties {
|
||||
if (this.wrapperRef.current) {
|
||||
const rect = this.wrapperRef.current.getBoundingClientRect();
|
||||
return {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user