Sort imports (#6101)

* add package.json

Signed-off-by: Jess Frazelle <github@jessfraz.com>

initial run;

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

more fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

clientsidescne

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

paths

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fix styles

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

combine

Signed-off-by: Jess Frazelle <github@jessfraz.com>

eslint rule

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

my ocd

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

constants file

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

no more import sceneInfra

Signed-off-by: Jess Frazelle <github@jessfraz.com>

updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

try fix circular import

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2025-04-01 23:54:26 -07:00
committed by GitHub
parent 29f8b05f56
commit d168ef94e9
401 changed files with 5427 additions and 4716 deletions

111
.eslintrc
View File

@ -1,111 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"react-perf",
"css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw",
"testing-library",
"@typescript-eslint"
],
"extends": [
"plugin:css-modules/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-array-delete": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-redundant-type-constituents": "error",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-unused-vars": ["error", {
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"vars": "all",
"args": "none"
}],
"@typescript-eslint/no-unsafe-unary-minus": "error",
"@typescript-eslint/no-wrapper-object-types": "error",
"no-throw-literal": "off", // Use @typescript-eslint/only-throw-error instead.
"@typescript-eslint/only-throw-error": "error",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"no-restricted-globals": [
"error",
{
"name": "isNaN",
"message": "Use Number.isNaN() instead."
}
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='stringify']",
"message": "Do not use TOML.stringify directly. Use the wrappers in test-utils instead like settingsToToml."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='parse']",
"message": "Do not use TOML.parse directly. Use the wrappers in test-utils instead like tomlToSettings."
}
],
"semi": [
"error",
"never"
],
"react-hooks/exhaustive-deps": "off",
"suggest-no-throw/suggest-no-throw": "error"
},
"overrides": [
{
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
"extends": [
"plugin:testing-library/react"
],
"rules": {
"suggest-no-throw/suggest-no-throw": "off",
"testing-library/prefer-screen-queries": "off",
"jest/valid-expect": "off"
}
},
{
"files": ["src/**/*.test.ts"],
"extends": [
"plugin:testing-library/react"
],
"rules": {
"suggest-no-throw/suggest-no-throw": "off"
}
}
]
}

127
.eslintrc.json Normal file
View File

@ -0,0 +1,127 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"react-perf",
"css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw",
"testing-library",
"@typescript-eslint"
],
"extends": [
"plugin:css-modules/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"no-array-constructor": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-array-delete": "error",
"@typescript-eslint/no-duplicate-enum-values": "error",
"@typescript-eslint/no-duplicate-type-constituents": "error",
"@typescript-eslint/no-empty-object-type": "error",
"@typescript-eslint/no-extra-non-null-assertion": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error",
"no-implied-eval": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-implied-eval": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-asserted-optional-chain": "error",
"@typescript-eslint/no-redundant-type-constituents": "error",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-unnecessary-type-constraint": "error",
"no-unused-vars": "off", // This is wrong; use the @typescript-eslint one instead.
"@typescript-eslint/no-unused-vars": [
"error",
{
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_",
"ignoreRestSiblings": true,
"vars": "all",
"args": "none"
}
],
"@typescript-eslint/no-unsafe-unary-minus": "error",
"@typescript-eslint/no-wrapper-object-types": "error",
"no-throw-literal": "off", // Use @typescript-eslint/only-throw-error instead.
"@typescript-eslint/only-throw-error": "error",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/prefer-namespace-keyword": "error",
"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-autofocus": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"no-restricted-globals": [
"error",
{
"name": "isNaN",
"message": "Use Number.isNaN() instead."
}
],
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.object.name='Array'][callee.property.name='isArray']",
"message": "Use isArray() in lib/utils.ts instead of Array.isArray()."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='stringify']",
"message": "Do not use TOML.stringify directly. Use the wrappers in test-utils instead like settingsToToml."
},
{
"selector": "CallExpression[callee.object.name='TOML'][callee.property.name='parse']",
"message": "Do not use TOML.parse directly. Use the wrappers in test-utils instead like tomlToSettings."
}
],
"no-restricted-imports": [
"error",
{
"patterns": [
// Restrict all relative imports except for .css files.
{
"group": ["./*", "../*", "!./*.css", "!../*.css"],
"message": "Use absolute imports instead."
}
]
}
],
"semi": ["error", "never"],
"react-hooks/exhaustive-deps": "off",
"suggest-no-throw/suggest-no-throw": "error"
},
"overrides": [
{
"files": ["e2e/**/*.ts"], // Update the pattern based on your file structure
"extends": ["plugin:testing-library/react"],
"rules": {
"suggest-no-throw/suggest-no-throw": "off",
"testing-library/prefer-screen-queries": "off",
"jest/valid-expect": "off"
}
},
{
"files": ["src/**/*.test.ts"],
"extends": ["plugin:testing-library/react"],
"rules": {
"suggest-no-throw/suggest-no-throw": "off"
}
},
{
"files": ["packages/**/*.ts", "rust/**/*.ts"],
"extends": [],
"rules": {
"no-restricted-imports": "off"
}
}
]
}

View File

@ -1,4 +1,4 @@
import { test, expect } from './zoo-test'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Electron app header tests', () => {
test(

View File

@ -1,13 +1,14 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import type { Page } from '@playwright/test'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import {
getUtils,
PERSIST_MODELING_CONTEXT,
TEST_COLORS,
commonPoints,
PERSIST_MODELING_CONTEXT,
getUtils,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { HomePageFixture } from './fixtures/homePageFixture'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.setTimeout(120000)

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import fs from 'node:fs/promises'
import path from 'node:path'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Point and click for boolean workflows', () => {
// Boolean operations to test
const booleanOperations = [

View File

@ -1,10 +1,11 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import { HomePageFixture } from './fixtures/homePageFixture'
import { getUtils } from './test-utils'
import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils'
import { SceneFixture } from './fixtures/sceneFixture'
import type { Page } from '@playwright/test'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { uuidv4 } from '@src/lib/utils'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe(
'Can create sketches on all planes and their back sides',

View File

@ -1,13 +1,14 @@
import { test, expect } from './zoo-test'
import {
orRunWhenFullSuiteEnabled,
getUtils,
executorInputPath,
} from './test-utils'
import { join } from 'path'
import { bracket } from 'lib/exampleKcl'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from './storageStates'
import { bracket } from '@src/lib/exampleKcl'
import fsp from 'fs/promises'
import { join } from 'path'
import { TEST_CODE_LONG_WITH_ERROR_OUT_OF_VIEW } from '@e2e/playwright/storageStates'
import {
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
test('Typing KCL errors induces a badge on the code pane button', async ({

View File

@ -1,12 +1,13 @@
import { test, expect } from './zoo-test'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import * as fsp from 'fs/promises'
import path, { join } from 'path'
import {
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import path, { join } from 'path'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
test('Extrude from command bar selects extrude line after', async ({

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Copilot ghost text', () => {
// eslint-disable-next-line jest/valid-title

View File

@ -1,6 +1,5 @@
import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
function countNewlines(input: string): number {
let count = 0

View File

@ -1,11 +1,12 @@
import { test, expect } from './zoo-test'
import fsp from 'fs/promises'
import path from 'path'
import {
getUtils,
executorInputPath,
getPlaywrightDownloadDir,
} from './test-utils'
import fsp from 'fs/promises'
getUtils,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test(
'export works on the first try',

View File

@ -1,14 +1,14 @@
import { test, expect } from './zoo-test'
import { uuidv4 } from '@src/lib/utils'
import fsp from 'fs/promises'
import { uuidv4 } from 'lib/utils'
import { join } from 'path'
import {
TEST_COLORS,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
TEST_COLORS,
} from './test-utils'
import { join } from 'path'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Editor tests', { tag: ['@skipWin'] }, () => {
test('can comment out code with ctrl+/', async ({ page, homePage }) => {

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import * as fsp from 'fs/promises'
import { join } from 'path'
import { expect, test } from '@e2e/playwright/zoo-test'
const FEATURE_TREE_EXAMPLE_CODE = `export fn timesFive(x) {
return 5 * x
}

View File

@ -1,15 +1,16 @@
import { test, expect } from './zoo-test'
import * as fsp from 'fs/promises'
import { FILE_EXT } from '@src/lib/constants'
import * as fs from 'fs'
import * as fsp from 'fs/promises'
import { join } from 'path'
import {
createProject,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
runningOnWindows,
} from './test-utils'
import { join } from 'path'
import { FILE_EXT } from 'lib/constants'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('integrations tests', () => {
test(

View File

@ -1,5 +1,5 @@
import type { Page, Locator, Route, Request } from '@playwright/test'
import { expect, TestInfo } from '@playwright/test'
import type { Locator, Page, Request, Route, TestInfo } from '@playwright/test'
import { expect } from '@playwright/test'
import * as fs from 'fs'
import * as path from 'path'

View File

@ -1,11 +1,12 @@
import type { Page, Locator } from '@playwright/test'
import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
import {
closePane,
checkIfPaneIsOpen,
closePane,
openPane,
sansWhitespace,
} from '../test-utils'
} from '@e2e/playwright/test-utils'
interface EditorState {
activeLines: Array<string>

View File

@ -2,25 +2,27 @@
import type {
BrowserContext,
ElectronApplication,
TestInfo,
Page,
TestInfo,
} from '@playwright/test'
import { _electron as electron } from '@playwright/test'
import { TEST_SETTINGS } from '../storageStates'
import { SETTINGS_FILE_NAME } from 'lib/constants'
import { getUtils, setup, settingsToToml } from '../test-utils'
import { SETTINGS_FILE_NAME } from '@src/lib/constants'
import type { DeepPartial } from '@src/lib/types'
import fsp from 'fs/promises'
import fs from 'node:fs'
import path from 'path'
import { CmdBarFixture } from './cmdBarFixture'
import { EditorFixture } from './editorFixture'
import { ToolbarFixture } from './toolbarFixture'
import { SceneFixture } from './sceneFixture'
import { HomePageFixture } from './homePageFixture'
import { DeepPartial } from 'lib/types'
import { Settings } from '@rust/kcl-lib/bindings/Settings'
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
import { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { TEST_SETTINGS } from '@e2e/playwright/storageStates'
import { getUtils, settingsToToml, setup } from '@e2e/playwright/test-utils'
export class AuthenticatedApp {
public readonly page: Page

View File

@ -1,4 +1,4 @@
import type { Page, Locator } from '@playwright/test'
import type { Locator, Page } from '@playwright/test'
import { expect } from '@playwright/test'
interface ProjectCardState {

View File

@ -1,15 +1,17 @@
import type { Page, Locator } from '@playwright/test'
import { expect } from '../zoo-test'
import { isArray, uuidv4 } from 'lib/utils'
import { CmdBarFixture } from './cmdBarFixture'
import type { Locator, Page } from '@playwright/test'
import { isArray, uuidv4 } from '@src/lib/utils'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import {
closeDebugPanel,
doAndWaitForImageDiff,
getPixelRGBs,
getUtils,
openAndClearDebugPanel,
sendCustomCmd,
getUtils,
} from '../test-utils'
} from '@e2e/playwright/test-utils'
import { expect } from '@e2e/playwright/zoo-test'
type MouseParams = {
pixelDiff?: number

View File

@ -1,14 +1,15 @@
import { type Page, type Locator, test } from '@playwright/test'
import { expect } from '../zoo-test'
import { type Locator, type Page, test } from '@playwright/test'
import type { SidebarType } from '@src/components/ModelingSidebar/ModelingPanes'
import { SIDEBAR_BUTTON_SUFFIX } from '@src/lib/constants'
import type { ToolbarModeName } from '@src/lib/toolbar'
import {
checkIfPaneIsOpen,
closePane,
doAndWaitForImageDiff,
openPane,
} from '../test-utils'
import { SidebarType } from 'components/ModelingSidebar/ModelingPanes'
import { SIDEBAR_BUTTON_SUFFIX } from 'lib/constants'
import { ToolbarModeName } from 'lib/toolbar'
} from '@e2e/playwright/test-utils'
import { expect } from '@e2e/playwright/zoo-test'
export class ToolbarFixture {
public page: Page

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import { executorInputPath } from './test-utils'
import { join } from 'path'
import fsp from 'fs/promises'
import { join } from 'path'
import { executorInputPath } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test(
'When machine-api server not found butt is disabled and shows the reason',

View File

@ -1,13 +1,15 @@
import { test, expect } from './zoo-test'
import { PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import { PROJECT_SETTINGS_FILE_NAME } from '@src/lib/constants'
import * as fsp from 'fs/promises'
import { join } from 'path'
import type { NamedView } from '@rust/kcl-lib/bindings/NamedView'
import {
createProject,
tomlToPerProjectSettings,
perProjectsettingsToToml,
} from './test-utils'
import { NamedView } from '@rust/kcl-lib/bindings/NamedView'
tomlToPerProjectSettings,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// Helper function to determine if the file path on disk exists
// Specifically this is used to check if project.toml exists on disk

View File

@ -1,4 +1,4 @@
import { test, expect } from './zoo-test'
import { expect, test } from '@e2e/playwright/zoo-test'
/**
* Not all menu actions are tested. Some are default electron menu actions.

View File

@ -2,8 +2,7 @@
// application, check it can make it to the project pane, and nothing more.
// It also tests our test wrappers are working.
// Additionally this serves as a nice minimal example.
import { test, expect } from './zoo-test'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Open the application', () => {
test('see the project view', async ({ page, context }) => {

View File

@ -1,22 +1,23 @@
import { test, expect } from './zoo-test'
import { join } from 'path'
import { bracket } from '@src/lib/exampleKcl'
import { onboardingPaths } from '@src/routes/Onboarding/paths'
import fsp from 'fs/promises'
import {
getUtils,
executorInputPath,
createProject,
settingsToToml,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { bracket } from 'lib/exampleKcl'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { join } from 'path'
import { expectPixelColor } from '@e2e/playwright/fixtures/sceneFixture'
import {
TEST_SETTINGS_KEY,
TEST_SETTINGS_ONBOARDING_START,
TEST_SETTINGS_ONBOARDING_EXPORT,
TEST_SETTINGS_ONBOARDING_START,
TEST_SETTINGS_ONBOARDING_USER_MENU,
} from './storageStates'
import { expectPixelColor } from './fixtures/sceneFixture'
} from '@e2e/playwright/storageStates'
import {
createProject,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
settingsToToml,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// Because our default test settings have the onboardingStatus set to 'dismissed',
// we must set it to empty for the tests where we want to see the onboarding immediately.

View File

@ -1,4 +1,4 @@
import { test, expect } from '@playwright/test'
import { expect, test } from '@playwright/test'
/** @deprecated, import from ./fixtureSetup.ts instead */
export const _test = test

View File

@ -1,12 +1,12 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import { EditorFixture } from './fixtures/editorFixture'
import { SceneFixture } from './fixtures/sceneFixture'
import { ToolbarFixture } from './fixtures/toolbarFixture'
import type { Locator, Page } from '@playwright/test'
import fs from 'node:fs/promises'
import path from 'node:path'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import { Locator } from '@playwright/test'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// test file is for testing point an click code gen functionality that's not sketch mode related

View File

@ -1,19 +1,20 @@
import { test, expect } from './zoo-test'
import { DEFAULT_PROJECT_KCL_FILE } from '@src/lib/constants'
import fs from 'fs'
import fsp from 'fs/promises'
import path from 'path'
import type { Paths } from '@e2e/playwright/test-utils'
import {
createProject,
doExport,
executorInputPath,
getPlaywrightDownloadDir,
getUtils,
isOutOfViewInScrollContainer,
Paths,
createProject,
getPlaywrightDownloadDir,
orRunWhenFullSuiteEnabled,
runningOnWindows,
} from './test-utils'
import fsp from 'fs/promises'
import fs from 'fs'
import path from 'path'
import { DEFAULT_PROJECT_KCL_FILE } from 'lib/constants'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test(
'projects reload if a new one is created, deleted, or renamed externally',

View File

@ -1,4 +1,5 @@
import { test, expect } from './zoo-test'
import { expect, test } from '@e2e/playwright/zoo-test'
/* eslint-disable jest/no-conditional-expect */
/**

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test'
import { orRunWhenFullSuiteEnabled } from './test-utils'
import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
/* eslint-disable jest/no-conditional-expect */

View File

@ -1,17 +1,18 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import path from 'path'
import type { Page } from '@playwright/test'
import { bracket } from '@src/lib/exampleKcl'
import { reportRejection } from '@src/lib/trap'
import * as fsp from 'fs/promises'
import path from 'path'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from '@e2e/playwright/storageStates'
import type { TestColor } from '@e2e/playwright/test-utils'
import {
getUtils,
TEST_COLORS,
TestColor,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
import { bracket } from 'lib/exampleKcl'
import { reportRejection } from 'lib/trap'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Regression tests', { tag: ['@skipWin'] }, () => {
// bugs we found that don't fit neatly into other categories

View File

@ -1,20 +1,20 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import type { Page } from '@playwright/test'
import { roundOff, uuidv4 } from '@src/lib/utils'
import fs from 'node:fs/promises'
import path from 'node:path'
import { HomePageFixture } from './fixtures/homePageFixture'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import {
getMovementUtils,
getUtils,
PERSIST_MODELING_CONTEXT,
TEST_COLORS,
getMovementUtils,
getUtils,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { uuidv4, roundOff } from 'lib/utils'
import { SceneFixture } from './fixtures/sceneFixture'
import { ToolbarFixture } from './fixtures/toolbarFixture'
import { CmdBarFixture } from './fixtures/cmdBarFixture'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
test('multi-sketch file shows multiple Edit Sketch buttons', async ({

View File

@ -1,21 +1,22 @@
import { test, expect } from './zoo-test'
import { secrets } from './secrets'
import {
Paths,
doExport,
getUtils,
settingsToToml,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { Models } from '@kittycad/lib'
import fsp from 'fs/promises'
import type { Models } from '@kittycad/lib'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import { spawn } from 'child_process'
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import fsp from 'fs/promises'
import JSZip from 'jszip'
import path from 'path'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
import { SceneFixture } from './fixtures/sceneFixture'
import { CmdBarFixture } from './fixtures/cmdBarFixture'
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import { secrets } from '@e2e/playwright/secrets'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
import type { Paths } from '@e2e/playwright/test-utils'
import {
doExport,
getUtils,
orRunWhenFullSuiteEnabled,
settingsToToml,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.beforeEach(async ({ page, context }) => {
// Make the user avatar image always 404

View File

@ -1,8 +1,9 @@
import { Settings } from '@rust/kcl-lib/bindings/Settings'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
import { Themes } from 'lib/theme'
import { DeepPartial } from 'lib/types'
import { onboardingPaths } from 'routes/Onboarding/paths'
import type { SaveSettingsPayload } from '@src/lib/settings/settingsTypes'
import { Themes } from '@src/lib/theme'
import type { DeepPartial } from '@src/lib/types'
import { onboardingPaths } from '@src/routes/Onboarding/paths'
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
export const IS_PLAYWRIGHT_KEY = 'playwright'

View File

@ -1,7 +1,12 @@
import { test, expect } from './zoo-test'
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { uuidv4 } from '@src/lib/utils'
import {
commonPoints,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test network and connection issues', () => {
test(

View File

@ -1,9 +1,9 @@
import {
orRunWhenFullSuiteEnabled,
runningOnLinux,
runningOnMac,
runningOnWindows,
orRunWhenFullSuiteEnabled,
} from './test-utils'
} from '@e2e/playwright/test-utils'
describe('platform detection utilities', () => {
const originalPlatform = process.platform

View File

@ -1,32 +1,29 @@
import {
expect,
BrowserContext,
TestInfo,
Locator,
Page,
} from '@playwright/test'
import { test } from './zoo-test'
import { EngineCommand } from 'lang/std/artifactGraph'
import * as TOML from '@iarna/toml'
import type { Models } from '@kittycad/lib'
import type { BrowserContext, Locator, Page, TestInfo } from '@playwright/test'
import { expect } from '@playwright/test'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import type { Configuration } from '@src/lang/wasm'
import { COOKIE_NAME } from '@src/lib/constants'
import { reportRejection } from '@src/lib/trap'
import type { DeepPartial } from '@src/lib/types'
import { isArray } from '@src/lib/utils'
import fsp from 'fs/promises'
import path from 'path'
import pixelMatch from 'pixelmatch'
import type { Protocol } from 'playwright-core/types/protocol'
import { PNG } from 'pngjs'
import { Protocol } from 'playwright-core/types/protocol'
import type { Models } from '@kittycad/lib'
import { COOKIE_NAME } from 'lib/constants'
import { secrets } from './secrets'
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
import { isErrorWhitelisted } from '@e2e/playwright/lib/console-error-whitelist'
import { secrets } from '@e2e/playwright/secrets'
import {
TEST_SETTINGS_KEY,
TEST_SETTINGS,
IS_PLAYWRIGHT_KEY,
} from './storageStates'
import * as TOML from '@iarna/toml'
import { isErrorWhitelisted } from './lib/console-error-whitelist'
import { isArray } from 'lib/utils'
import { reportRejection } from 'lib/trap'
import { DeepPartial } from 'lib/types'
import { Configuration } from 'lang/wasm'
import { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
TEST_SETTINGS,
TEST_SETTINGS_KEY,
} from '@e2e/playwright/storageStates'
import { test } from '@e2e/playwright/zoo-test'
const toNormalizedCode = (text: string) => {
return text.replace(/\s+/g, '')

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import { EngineCommand } from 'lang/std/artifactGraph'
import { uuidv4 } from 'lib/utils'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import { uuidv4 } from '@src/lib/utils'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
test('Can move camera reliably', async ({ page, context, homePage }) => {

View File

@ -1,14 +1,15 @@
import { test, expect } from './zoo-test'
import { XOR } from '@src/lib/utils'
import * as fsp from 'fs/promises'
import {
getUtils,
TEST_COLORS,
pollEditorLinesSelectedLength,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { XOR } from 'lib/utils'
import path from 'node:path'
import {
TEST_COLORS,
getUtils,
orRunWhenFullSuiteEnabled,
pollEditorLinesSelectedLength,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
test('Can constrain line length', async ({ page, homePage }) => {
await page.addInitScript(async () => {

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
import { uuidv4 } from 'lib/utils'
import { TEST_CODE_GIZMO } from './storageStates'
import { uuidv4 } from '@src/lib/utils'
import { TEST_CODE_GIZMO } from '@e2e/playwright/storageStates'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Gizmo', { tag: ['@skipWin'] }, () => {
const cases = [

View File

@ -1,5 +1,5 @@
import { test, expect } from './zoo-test'
import { getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({ page, homePage }) => {

View File

@ -1,9 +1,10 @@
import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
import { bracket } from 'lib/exampleKcl'
import { FILE_EXT } from '@src/lib/constants'
import { bracket } from '@src/lib/exampleKcl'
import * as fsp from 'fs/promises'
import { join } from 'path'
import { FILE_EXT } from 'lib/constants'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing in-app sample loading', () => {
/**

View File

@ -1,15 +1,15 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import type { Page } from '@playwright/test'
import type { LineInputsType } from '@src/lang/std/sketchcombos'
import { uuidv4 } from '@src/lib/utils'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import {
deg,
getUtils,
wiggleMove,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { LineInputsType } from 'lang/std/sketchcombos'
import { uuidv4 } from 'lib/utils'
import { EditorFixture } from './fixtures/editorFixture'
wiggleMove,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing segment overlays', { tag: ['@skipWin'] }, () => {
test('Hover over a segment should show its overlay, hovering over the input overlays should show its popover, clicking the input overlay should constrain/unconstrain it:\nfor the following segments', () => {

View File

@ -1,9 +1,13 @@
import { test, expect } from './zoo-test'
import type { Coords2d } from '@src/lang/std/sketch'
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
import { uuidv4 } from '@src/lib/utils'
import { commonPoints, getUtils, orRunWhenFullSuiteEnabled } from './test-utils'
import { Coords2d } from 'lang/std/sketch'
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import { uuidv4 } from 'lib/utils'
import {
commonPoints,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing selections', { tag: ['@skipWin'] }, () => {
test.setTimeout(90_000)

View File

@ -1,24 +1,29 @@
import { test, expect } from './zoo-test'
import {
PROJECT_SETTINGS_FILE_NAME,
SETTINGS_FILE_NAME,
} from '@src/lib/constants'
import type { SettingsLevel } from '@src/lib/settings/settingsTypes'
import type { DeepPartial } from '@src/lib/types'
import * as fsp from 'fs/promises'
import { join } from 'path'
import type { Settings } from '@rust/kcl-lib/bindings/Settings'
import {
getUtils,
executorInputPath,
createProject,
tomlToSettings,
TEST_COLORS,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { SettingsLevel } from 'lib/settings/settingsTypes'
import { SETTINGS_FILE_NAME, PROJECT_SETTINGS_FILE_NAME } from 'lib/constants'
import {
TEST_SETTINGS_KEY,
TEST_SETTINGS_CORRUPTED,
TEST_SETTINGS,
TEST_SETTINGS_CORRUPTED,
TEST_SETTINGS_DEFAULT_THEME,
} from './storageStates'
import { DeepPartial } from 'lib/types'
import { Settings } from '@rust/kcl-lib/bindings/Settings'
TEST_SETTINGS_KEY,
} from '@e2e/playwright/storageStates'
import {
TEST_COLORS,
createProject,
executorInputPath,
getUtils,
orRunWhenFullSuiteEnabled,
tomlToSettings,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing settings', () => {
test('Stored settings are validated and fall back to defaults', async ({

View File

@ -1,12 +1,13 @@
import { Page } from '@playwright/test'
import { test, expect } from './zoo-test'
import {
getUtils,
createProject,
orRunWhenFullSuiteEnabled,
} from './test-utils'
import { join } from 'path'
import type { Page } from '@playwright/test'
import fs from 'fs'
import { join } from 'path'
import {
createProject,
getUtils,
orRunWhenFullSuiteEnabled,
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Text-to-CAD tests', { tag: ['@skipWin'] }, () => {
test('basic lego happy case', async ({ page, homePage }) => {

View File

@ -1,11 +1,10 @@
import { test, expect } from './zoo-test'
import {
doExport,
getUtils,
makeTemplate,
orRunWhenFullSuiteEnabled,
} from './test-utils'
} from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test('Units menu', async ({ page, homePage }) => {
test.fixme(orRunWhenFullSuiteEnabled())

View File

@ -1,12 +1,11 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { test as playwrightTestFn } from '@playwright/test'
import type { Fixtures } from '@e2e/playwright/fixtures/fixtureSetup'
import {
fixturesBasedOnProcessEnvPlatform,
Fixtures,
ElectronZoo,
} from './fixtures/fixtureSetup'
fixturesBasedOnProcessEnvPlatform,
} from '@e2e/playwright/fixtures/fixtureSetup'
export { expect } from '@playwright/test'

View File

@ -1,6 +1,6 @@
import type { ForgeConfig } from '@electron-forge/shared-types'
import { VitePlugin } from '@electron-forge/plugin-vite'
import { FusesPlugin } from '@electron-forge/plugin-fuses'
import { VitePlugin } from '@electron-forge/plugin-vite'
import type { ForgeConfig } from '@electron-forge/shared-types'
import { FuseV1Options, FuseVersion } from '@electron/fuses'
import path from 'path'

2
forge.env.d.ts vendored
View File

@ -26,7 +26,7 @@ declare global {
declare module 'vite' {
interface ConfigEnv<
K extends keyof VitePluginConfig = keyof VitePluginConfig
K extends keyof VitePluginConfig = keyof VitePluginConfig,
> {
root: string
forgeConfig: VitePluginConfig

13
interface.d.ts vendored
View File

@ -1,13 +1,10 @@
import fs from 'node:fs/promises'
import fsSync from 'node:fs'
import path from 'path'
import { dialog, shell } from 'electron'
import { MachinesListing } from 'components/MachineManagerProvider'
import type { Channel } from 'src/menu/channels'
import { Menu, WebContents } from 'electron'
import { ZooLabel, ZooMenuEvents } from 'menu/roles'
import type { MenuActionIPC } from 'menu/rules'
import 'electron'
import { dialog, shell } from 'electron'
import type { WebContentSendPayload } from 'menu/channels'
import { ZooLabel } from 'menu/roles'
import fs from 'node:fs/promises'
import path from 'path'
// Extend the interface with additional custom properties
declare module 'electron' {

View File

@ -88,9 +88,9 @@
"simpleserver:ci": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver:bg": "yarn pretest && http-server ./public --cors -p 3000 &",
"simpleserver:stop": "kill-port 3000",
"fmt": "prettier --write ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt:generated": "prettier --write *.ts *.json *.js ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt-check": "prettier --check ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server",
"fmt": "prettier --write .eslintrc.json ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt:generated": "prettier --write .eslintrc.json *.ts *.json *.js ./rust/kcl-lib/bindings ./rust/kcl-wasm-lib/pkg",
"fmt-check": "prettier --check .eslintrc.json ./src *.ts *.json *.js ./e2e ./packages ./rust/kcl-language-server",
"fetch:wasm": "./scripts/get-latest-wasm-bundle.sh",
"fetch:wasm:windows": "./scripts/get-latest-wasm-bundle.ps1",
"fetch:samples": "rm -rf public/kcl-samples* && curl -L -o public/kcl-samples.zip https://github.com/KittyCAD/kcl-samples/archive/refs/heads/achalmers/kw-args-xylineto.zip && unzip -o public/kcl-samples.zip -d public && mv public/kcl-samples-* public/kcl-samples",
@ -102,6 +102,7 @@
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./rust/kcl-wasm-lib/pkg/kcl_wasm_lib.js\" || echo \"sed for both mac and linux\"",
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src rust/kcl-language-server/client/src",
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
"files:set-notes": "./scripts/set-files-notes.sh",
"files:flip-to-nightly": "./scripts/flip-files-to-nightly.sh",
@ -139,7 +140,20 @@
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true
"singleQuote": true,
"importOrder": [
"<THIRD_PARTY_MODULES>",
"^@rust/(.*)$",
"^@e2e/(.*)$",
"^@src/(.*)$",
"^[./]"
],
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"plugins": [
"@trivago/prettier-plugin-sort-imports",
"prettier-plugin-organize-imports"
]
},
"browserslist": {
"production": [
@ -167,6 +181,7 @@
"@playwright/test": "^1.51.1",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^15.0.2",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/diff": "^7.0.2",
"@types/electron": "^1.6.10",
"@types/isomorphic-fetch": "^0.0.39",
@ -187,6 +202,7 @@
"@vitest/web-worker": "^1.5.0",
"@xstate/cli": "^0.5.17",
"autoprefixer": "^10.4.21",
"dpdm": "^3.14.0",
"electron": "^34.1.1",
"electron-builder": "^26.0.12",
"eslint": "^8.0.1",
@ -208,7 +224,8 @@
"pngjs": "^7.0.0",
"postcss": "^8.4.43",
"postinstall-postinstall": "^2.1.0",
"prettier": "^2.8.8",
"prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"setimmediate": "^1.0.5",
"tailwindcss": "^3.4.17",
"ts-node": "^10.0.0",

View File

@ -1,6 +1,6 @@
import dts from 'rollup-plugin-dts'
import { lezer } from '@lezer/generator/rollup'
import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'
export default [
{

View File

@ -1,14 +1,14 @@
// Base CodeMirror language support for kcl.
import {
LRLanguage,
LanguageSupport,
indentNodeProp,
continuedIndent,
delimitedIndent,
foldNodeProp,
foldInside,
foldNodeProp,
indentNodeProp,
} from '@codemirror/language'
// @ts-ignore: No types available
import { parser } from './kcl.grammar'

View File

@ -1,9 +1,9 @@
import { KclLanguage } from '../src/index'
import { fileTests } from '@lezer/generator/dist/test'
import * as fs from 'fs'
import * as path from 'path'
import { KclLanguage } from '../src/index'
let caseDir = path.dirname(__filename)
for (let file of fs.readdirSync(caseDir)) {

View File

@ -1,9 +1,8 @@
// Overrides the test options from the modeling-app config.
import viteTsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig, configDefaults } from 'vitest/config'
// @ts-ignore: No types available
import { lezer } from '@lezer/generator/rollup'
import viteTsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vitest/config'
const config = defineConfig({
test: {

View File

@ -1,4 +1,4 @@
import { encoder, decoder } from '../codec'
import { decoder, encoder } from './encode-decode'
export default class Bytes {
static encode(input: string): Uint8Array {
@ -10,7 +10,7 @@ export default class Bytes {
}
static append<
T extends { length: number; set(arr: T, offset: number): void }
T extends { length: number; set(arr: T, offset: number): void },
>(constructor: { new (length: number): T }, ...arrays: T[]) {
let totalLength = 0
for (const arr of arrays) {

View File

@ -1,10 +1,10 @@
import * as vsrpc from 'vscode-jsonrpc'
import { Codec } from '.'
import Bytes from './bytes'
import PromiseMap from './map'
import Queue from './queue'
import Tracer from './tracer'
import PromiseMap from './map'
import { Codec } from './utils'
export default class StreamDemuxer extends Queue<Uint8Array> {
readonly responses: PromiseMap<number | string, vsrpc.ResponseMessage> =

View File

@ -0,0 +1,2 @@
export const encoder = new TextEncoder()
export const decoder = new TextDecoder()

View File

@ -1,8 +1,7 @@
import * as jsrpc from 'json-rpc-2.0'
import * as vsrpc from 'vscode-jsonrpc'
import type * as vsrpc from 'vscode-jsonrpc'
import Bytes from './bytes'
import StreamDemuxer from './demuxer'
import { decoder } from './encode-decode'
import Headers from './headers'
import Queue from './queue'
import Tracer from './tracer'
@ -12,25 +11,6 @@ export enum LspWorkerEventType {
Call = 'call',
}
export const encoder = new TextEncoder()
export const decoder = new TextDecoder()
export class Codec {
static encode(
json: jsrpc.JSONRPCRequest | jsrpc.JSONRPCResponse
): Uint8Array {
const message = JSON.stringify(json)
const delimited = Headers.add(message)
return Bytes.encode(delimited)
}
static decode<T>(data: Uint8Array): T {
const delimited = Bytes.decode(data)
const message = Headers.remove(delimited)
return JSON.parse(message) as T
}
}
// FIXME: tracing efficiency
export class IntoServer
extends Queue<Uint8Array>

View File

@ -1,4 +1,4 @@
import { Message } from 'vscode-languageserver-protocol'
import type { Message } from 'vscode-languageserver-protocol'
export default class Tracer {
static client(message: string): void {

View File

@ -0,0 +1,20 @@
import type * as jsrpc from 'json-rpc-2.0'
import Bytes from './bytes'
import Headers from './headers'
export class Codec {
static encode(
json: jsrpc.JSONRPCRequest | jsrpc.JSONRPCResponse
): Uint8Array {
const message = JSON.stringify(json)
const delimited = Headers.add(message)
return Bytes.encode(delimited)
}
static decode<T>(data: Uint8Array): T {
const delimited = Bytes.decode(data)
const message = Headers.remove(delimited)
return JSON.parse(message) as T
}
}

View File

@ -1,8 +1,8 @@
import type * as LSP from 'vscode-languageserver-protocol'
import { FromServer, IntoServer } from './codec'
import type { LanguageServerPlugin } from '../plugin/lsp'
import type { FromServer, IntoServer } from './codec'
import Client from './jsonrpc'
import { LanguageServerPlugin } from '../plugin/lsp'
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/
@ -12,15 +12,15 @@ interface LSPRequestMap {
'textDocument/hover': [LSP.HoverParams, LSP.Hover]
'textDocument/completion': [
LSP.CompletionParams,
LSP.CompletionItem[] | LSP.CompletionList | null
LSP.CompletionItem[] | LSP.CompletionList | null,
]
'textDocument/semanticTokens/full': [
LSP.SemanticTokensParams,
LSP.SemanticTokens
LSP.SemanticTokens,
]
'textDocument/formatting': [
LSP.DocumentFormattingParams,
LSP.TextEdit[] | null
LSP.TextEdit[] | null,
]
'textDocument/foldingRange': [LSP.FoldingRangeParams, LSP.FoldingRange[]]
}

View File

@ -1,11 +1,12 @@
import * as jsrpc from 'json-rpc-2.0'
import * as LSP from 'vscode-languageserver-protocol'
import type { FromServer, IntoServer } from './codec'
import { Codec } from './codec/utils'
import {
registerServerCapability,
unregisterServerCapability,
} from './server-capability-registration'
import { Codec, FromServer, IntoServer } from './codec'
const client_capabilities: LSP.ClientCapabilities = {
textDocument: {

View File

@ -1,4 +1,4 @@
import {
import type {
Registration,
ServerCapabilities,
Unregistration,

View File

@ -1,36 +1,34 @@
import { foldService } from '@codemirror/language'
import { Extension, EditorState } from '@codemirror/state'
import type { EditorState, Extension } from '@codemirror/state'
import { ViewPlugin } from '@codemirror/view'
import type { LanguageServerOptions } from './plugin/lsp'
import {
docPathFacet,
LanguageServerPlugin,
LanguageServerPluginSpec,
docPathFacet,
languageId,
workspaceFolders,
LanguageServerOptions,
} from './plugin/lsp'
export type { LanguageServerClientOptions } from './client'
export { LanguageServerClient } from './client'
export type { LanguageServerClientOptions } from './client'
export { FromServer, IntoServer, LspWorkerEventType } from './client/codec'
export { Codec } from './client/codec/utils'
export {
Codec,
FromServer,
IntoServer,
LspWorkerEventType,
} from './client/codec'
export type { LanguageServerOptions } from './plugin/lsp'
lspDiagnosticsEvent,
lspFormatCodeEvent,
lspSemanticTokensEvent,
} from './plugin/annotation'
export {
LanguageServerPlugin,
LanguageServerPluginSpec,
docPathFacet,
languageId,
workspaceFolders,
lspSemanticTokensEvent,
lspDiagnosticsEvent,
lspFormatCodeEvent,
} from './plugin/lsp'
export { posToOffset, offsetToPos } from './plugin/util'
export type { LanguageServerOptions } from './plugin/lsp'
export { offsetToPos, posToOffset } from './plugin/util'
export function lspPlugin(options: LanguageServerOptions): Extension {
let plugin: LanguageServerPlugin | null = null

View File

@ -0,0 +1,12 @@
import { Annotation } from '@codemirror/state'
export enum LspAnnotation {
SemanticTokens = 'semantic-tokens',
FormatCode = 'format-code',
Diagnostics = 'diagnostics',
}
const lspEvent = Annotation.define<LspAnnotation>()
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)

View File

@ -9,17 +9,18 @@ import {
prevSnippetField,
startCompletion,
} from '@codemirror/autocomplete'
import { Prec, Extension } from '@codemirror/state'
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view'
import { syntaxTree } from '@codemirror/language'
import type { Extension } from '@codemirror/state'
import { Prec } from '@codemirror/state'
import type { EditorView, KeyBinding, ViewPlugin } from '@codemirror/view'
import { keymap } from '@codemirror/view'
import {
CompletionItemKind,
CompletionTriggerKind,
} from 'vscode-languageserver-protocol'
import { LanguageServerPlugin } from './lsp'
import type { LanguageServerPlugin } from './lsp'
import { offsetToPos } from './util'
import { syntaxTree } from '@codemirror/language'
export const CompletionItemKindMap = Object.fromEntries(
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])

View File

@ -1,7 +1,9 @@
import { Extension, Prec } from '@codemirror/state'
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view'
import type { Extension } from '@codemirror/state'
import { Prec } from '@codemirror/state'
import type { EditorView, KeyBinding, ViewPlugin } from '@codemirror/view'
import { keymap } from '@codemirror/view'
import { LanguageServerPlugin } from './lsp'
import type { LanguageServerPlugin } from './lsp'
export default function lspFormatExt(
plugin: ViewPlugin<LanguageServerPlugin>

View File

@ -1,12 +1,8 @@
import { Extension } from '@codemirror/state'
import {
hoverTooltip,
tooltips,
ViewPlugin,
EditorView,
} from '@codemirror/view'
import type { Extension } from '@codemirror/state'
import type { ViewPlugin } from '@codemirror/view'
import { EditorView, hoverTooltip, tooltips } from '@codemirror/view'
import { LanguageServerPlugin } from './lsp'
import type { LanguageServerPlugin } from './lsp'
import { offsetToPos } from './util'
export default function lspHoverExt(

View File

@ -1,5 +1,5 @@
import { indentService } from '@codemirror/language'
import { Extension } from '@codemirror/state'
import type { Extension } from '@codemirror/state'
export default function lspIndentExt(): Extension {
// Match the indentation of the previous line (if present).

View File

@ -4,39 +4,34 @@ import type {
CompletionResult,
} from '@codemirror/autocomplete'
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
import {
Facet,
StateEffect,
Extension,
Transaction,
Annotation,
} from '@codemirror/state'
import type {
ViewUpdate,
PluginValue,
PluginSpec,
ViewPlugin,
} from '@codemirror/view'
import { EditorView, Tooltip } from '@codemirror/view'
import { linter } from '@codemirror/lint'
import type { PublishDiagnosticsParams } from 'vscode-languageserver-protocol'
import type { Extension, StateEffect } from '@codemirror/state'
import { Facet, Transaction } from '@codemirror/state'
import type {
EditorView,
PluginSpec,
PluginValue,
Tooltip,
ViewPlugin,
ViewUpdate,
} from '@codemirror/view'
import type * as LSP from 'vscode-languageserver-protocol'
import {
DiagnosticSeverity,
import type {
CompletionTriggerKind,
PublishDiagnosticsParams,
} from 'vscode-languageserver-protocol'
import { DiagnosticSeverity } from 'vscode-languageserver-protocol'
import { URI } from 'vscode-uri'
import { LanguageServerClient } from '../client'
import { CompletionItemKindMap } from './autocomplete'
import { addToken, SemanticToken } from './semantic-tokens'
import { posToOffset, formatMarkdownContents } from './util'
import lspAutocompleteExt from './autocomplete'
import lspHoverExt from './hover'
import type { LanguageServerClient } from '../client'
import { lspFormatCodeEvent, lspSemanticTokensEvent } from './annotation'
import lspAutocompleteExt, { CompletionItemKindMap } from './autocomplete'
import lspFormatExt from './format'
import lspHoverExt from './hover'
import lspIndentExt from './indent'
import lspSemanticTokensExt from './semantic-tokens'
import type { SemanticToken } from './semantic-tokens'
import lspSemanticTokensExt, { addToken } from './semantic-tokens'
import { formatMarkdownContents, posToOffset } from './util'
const useLast = (values: readonly any[]) => values.reduce((_, v) => v, '')
export const docPathFacet = Facet.define<string, string>({
@ -48,17 +43,6 @@ export const workspaceFolders = Facet.define<
LSP.WorkspaceFolder[]
>({ combine: useLast })
export enum LspAnnotation {
SemanticTokens = 'semantic-tokens',
FormatCode = 'format-code',
Diagnostics = 'diagnostics',
}
const lspEvent = Annotation.define<LspAnnotation>()
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
export interface LanguageServerOptions {
// We assume this is the main project directory, we are currently working in.
workspaceFolders: LSP.WorkspaceFolder[]
@ -98,7 +82,10 @@ export class LanguageServerPlugin implements PluginValue {
// document.
private sendScheduled: number | null = null
constructor(options: LanguageServerOptions, private view: EditorView) {
constructor(
options: LanguageServerOptions,
private view: EditorView
) {
this.client = options.client
this.documentVersion = 0

View File

@ -1,10 +1,12 @@
import { highlightingFor } from '@codemirror/language'
import { StateEffect, StateField, Extension } from '@codemirror/state'
import { EditorView, Decoration, DecorationSet } from '@codemirror/view'
import type { Extension } from '@codemirror/state'
import { StateEffect, StateField } from '@codemirror/state'
import type { DecorationSet } from '@codemirror/view'
import { Decoration, EditorView } from '@codemirror/view'
import type { Tag } from '@lezer/highlight'
import { tags } from '@lezer/highlight'
import { Tag, tags } from '@lezer/highlight'
import { lspSemanticTokensEvent } from './lsp'
import { lspSemanticTokensEvent } from './annotation'
export interface SemanticToken {
from: number

View File

@ -1,7 +1,8 @@
import { Text } from '@codemirror/state'
import { Marked, MarkedOptions } from '@ts-stack/markdown'
import type { Text } from '@codemirror/state'
import type { MarkedOptions } from '@ts-stack/markdown'
import { Marked } from '@ts-stack/markdown'
import type * as LSP from 'vscode-languageserver-protocol'
import { isArray } from '../lib/utils'
// takes a function and executes it after the wait time, if the function is called again before the wait time is up, the timer is reset

View File

@ -1,10 +1,11 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode'
import * as os from 'os'
import type { Config } from './config'
import { log, isValidExecutable } from './util'
import type { PersistentState } from './persistent_state'
import { exec } from 'child_process'
import * as os from 'os'
import * as vscode from 'vscode'
import type { Config } from './config'
import type { PersistentState } from './persistent_state'
import { isValidExecutable, log } from './util'
export async function bootstrap(
context: vscode.ExtensionContext,

View File

@ -1,6 +1,6 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as lc from 'vscode-languageclient/node'
import type * as vscode from 'vscode'
import * as lc from 'vscode-languageclient/node'
export async function createClient(
traceOutputChannel: vscode.OutputChannel,

View File

@ -1,8 +1,8 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import { spawnSync } from 'child_process'
import * as vscode from 'vscode'
import type { Cmd, CtxInit } from './ctx'
import { spawnSync } from 'child_process'
export function serverVersion(ctx: CtxInit): Cmd {
return async () => {

View File

@ -1,10 +1,11 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as Is from 'vscode-languageclient/lib/common/utils/is'
import * as os from 'os'
import * as path from 'path'
import * as vscode from 'vscode'
import { log, type Env } from './util'
import * as Is from 'vscode-languageclient/lib/common/utils/is'
import { expectNotUndefined, unwrapUndefinable } from './undefinable'
import { type Env, log } from './util'
export type RunnableEnvCfgItem = {
mask?: string

View File

@ -1,20 +1,20 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode'
import type * as lc from 'vscode-languageclient/node'
import { TransportKind } from 'vscode-languageclient/node'
import { Config, prepareVSCodeConfig } from './config'
import { bootstrap } from './bootstrap'
import { createClient } from './client'
import {
isKclDocument,
isKclEditor,
LazyOutputChannel,
log,
type KclEditor,
} from './util'
import { Config, prepareVSCodeConfig } from './config'
import type { ServerStatusParams } from './lsp_ext'
import { PersistentState } from './persistent_state'
import { bootstrap } from './bootstrap'
import { TransportKind } from 'vscode-languageclient/node'
import {
type KclEditor,
LazyOutputChannel,
isKclDocument,
isKclEditor,
log,
} from './util'
// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
// only those are in use. We use "Empty" to represent these scenarios

View File

@ -1,5 +1,6 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import type * as vscode from 'vscode'
import { log } from './util'
export class PersistentState {

View File

@ -1,6 +1,5 @@
import * as path from 'path'
import { runTests } from '@vscode/test-electron'
import * as path from 'path'
async function main() {
try {

View File

@ -1,8 +1,8 @@
import * as assert from 'assert'
// You can import and use all API from the 'vscode' module
// as well as import your extension to test it
import * as vscode from 'vscode'
// import * as myExtension from '../../extension';
suite('Extension Test Suite', () => {

View File

@ -1,4 +1,5 @@
import * as path from 'path'
const Mocha = require('mocha')
const { glob } = require('glob')

View File

@ -1,8 +1,8 @@
/* eslint suggest-no-throw/suggest-no-throw: 0 */
import * as vscode from 'vscode'
import { strict as nativeAssert } from 'assert'
import { exec, type ExecOptions, spawnSync } from 'child_process'
import { type ExecOptions, exec, spawnSync } from 'child_process'
import { inspect } from 'util'
import * as vscode from 'vscode'
export interface Env {
[name: string]: string

View File

@ -1,36 +1,43 @@
import { useEffect, useMemo, useRef } from 'react'
import { useHotKeyListener } from './hooks/useHotKeyListener'
import { Stream } from './components/Stream'
import { AppHeader } from './components/AppHeader'
import { useHotkeys } from 'react-hotkeys-hook'
import { useLoaderData, useNavigate } from 'react-router-dom'
import { type IndexLoaderData } from 'lib/types'
import { PATHS } from 'lib/paths'
import { onboardingPaths } from 'routes/Onboarding/paths'
import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubscriptions'
import { codeManager, engineCommandManager } from 'lib/singletons'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import { isDesktop } from 'lib/isDesktop'
import { useLspContext } from 'components/LspProvider'
import { ModelingSidebar } from 'components/ModelingSidebar/ModelingSidebar'
import { LowerRightControls } from 'components/LowerRightControls'
import ModalContainer from 'react-modal-promise'
import useHotkeyWrapper from 'lib/hotkeyWrapper'
import Gizmo from 'components/Gizmo'
import { CoreDumpManager } from 'lib/coredump'
import { UnitsMenu } from 'components/UnitsMenu'
import { CameraProjectionToggle } from 'components/CameraProjectionToggle'
import { useCreateFileLinkQuery } from 'hooks/useCreateFileLinkQueryWatcher'
import { maybeWriteToDisk } from 'lib/telemetry'
import { takeScreenshotOfVideoStreamCanvas } from 'lib/screenshot'
import { writeProjectThumbnailFile } from 'lib/desktop'
import { useRouteLoaderData } from 'react-router-dom'
import { useEngineCommands } from 'components/EngineCommands'
import { commandBarActor } from 'machines/commandBarMachine'
import { useToken } from 'machines/appMachine'
import { useSettings } from 'machines/appMachine'
import { rustContext } from 'lib/singletons'
import toast from 'react-hot-toast'
import { useHotkeys } from 'react-hotkeys-hook'
import ModalContainer from 'react-modal-promise'
import {
useLoaderData,
useNavigate,
useRouteLoaderData,
} from 'react-router-dom'
import { AppHeader } from '@src/components/AppHeader'
import { CameraProjectionToggle } from '@src/components/CameraProjectionToggle'
import { useEngineCommands } from '@src/components/EngineCommands'
import Gizmo from '@src/components/Gizmo'
import { LowerRightControls } from '@src/components/LowerRightControls'
import { useLspContext } from '@src/components/LspProvider'
import { ModelingSidebar } from '@src/components/ModelingSidebar/ModelingSidebar'
import { Stream } from '@src/components/Stream'
import { UnitsMenu } from '@src/components/UnitsMenu'
import { useAbsoluteFilePath } from '@src/hooks/useAbsoluteFilePath'
import { useCreateFileLinkQuery } from '@src/hooks/useCreateFileLinkQueryWatcher'
import { useEngineConnectionSubscriptions } from '@src/hooks/useEngineConnectionSubscriptions'
import { useHotKeyListener } from '@src/hooks/useHotKeyListener'
import { CoreDumpManager } from '@src/lib/coredump'
import { writeProjectThumbnailFile } from '@src/lib/desktop'
import useHotkeyWrapper from '@src/lib/hotkeyWrapper'
import { isDesktop } from '@src/lib/isDesktop'
import { PATHS } from '@src/lib/paths'
import { takeScreenshotOfVideoStreamCanvas } from '@src/lib/screenshot'
import {
codeManager,
engineCommandManager,
rustContext,
} from '@src/lib/singletons'
import { maybeWriteToDisk } from '@src/lib/telemetry'
import { type IndexLoaderData } from '@src/lib/types'
import { useSettings, useToken } from '@src/machines/appMachine'
import { commandBarActor } from '@src/machines/commandBarMachine'
import { onboardingPaths } from '@src/routes/Onboarding/paths'
maybeWriteToDisk()
.then(() => {})
.catch(() => {})

View File

@ -1,4 +1,5 @@
import { createContext, useContext, useState, ReactNode } from 'react'
import type { ReactNode } from 'react'
import { createContext, useContext, useState } from 'react'
/*

View File

@ -1,5 +1,5 @@
import { useAuthState } from 'machines/appMachine'
import Loading from './components/Loading'
import Loading from '@src/components/Loading'
import { useAuthState } from '@src/machines/appMachine'
// Wrapper around protected routes, used in src/Router.tsx
export const Auth = ({ children }: React.PropsWithChildren) => {

View File

@ -1,46 +1,53 @@
import { App } from './App'
import { useMemo } from 'react'
import toast from 'react-hot-toast'
import {
Outlet,
RouterProvider,
createBrowserRouter,
createHashRouter,
Outlet,
redirect,
RouterProvider,
} from 'react-router-dom'
import { ErrorPage } from './components/ErrorPage'
import { Settings } from './routes/Settings'
import { Telemetry } from './routes/Telemetry'
import Onboarding, { onboardingRoutes } from './routes/Onboarding'
import SignIn from './routes/SignIn'
import { Auth } from './Auth'
import { isDesktop } from './lib/isDesktop'
import Home from './routes/Home'
import { NetworkContext } from './hooks/useNetworkContext'
import { useNetworkStatus } from './hooks/useNetworkStatus'
import makeUrlPathRelative from './lib/makeUrlPathRelative'
import DownloadAppBanner from 'components/DownloadAppBanner'
import { WasmErrBanner } from 'components/WasmErrBanner'
import { CommandBar } from 'components/CommandBar/CommandBar'
import ModelingMachineProvider from 'components/ModelingMachineProvider'
import FileMachineProvider from 'components/FileMachineProvider'
import { MachineManagerProvider } from 'components/MachineManagerProvider'
import { PATHS } from 'lib/paths'
import { fileLoader, homeLoader, telemetryLoader } from 'lib/routeLoaders'
import LspProvider from 'components/LspProvider'
import { KclContextProvider } from 'lang/KclProvider'
import { ASK_TO_OPEN_QUERY_PARAM, BROWSER_PROJECT_NAME } from 'lib/constants'
import { CoreDumpManager } from 'lib/coredump'
import { codeManager, engineCommandManager } from 'lib/singletons'
import useHotkeyWrapper from 'lib/hotkeyWrapper'
import toast from 'react-hot-toast'
import { coreDump } from 'lang/wasm'
import { useMemo } from 'react'
import { AppStateProvider } from 'AppState'
import { reportRejection } from 'lib/trap'
import { RouteProvider } from 'components/RouteProvider'
import { ProjectsContextProvider } from 'components/ProjectsContextProvider'
import { useToken } from 'machines/appMachine'
import { OpenInDesktopAppHandler } from 'components/OpenInDesktopAppHandler'
import { rustContext } from 'lib/singletons'
import { App } from '@src/App'
import { AppStateProvider } from '@src/AppState'
import { Auth } from '@src/Auth'
import { CommandBar } from '@src/components/CommandBar/CommandBar'
import DownloadAppBanner from '@src/components/DownloadAppBanner'
import { ErrorPage } from '@src/components/ErrorPage'
import FileMachineProvider from '@src/components/FileMachineProvider'
import LspProvider from '@src/components/LspProvider'
import { MachineManagerProvider } from '@src/components/MachineManagerProvider'
import ModelingMachineProvider from '@src/components/ModelingMachineProvider'
import { OpenInDesktopAppHandler } from '@src/components/OpenInDesktopAppHandler'
import { ProjectsContextProvider } from '@src/components/ProjectsContextProvider'
import { RouteProvider } from '@src/components/RouteProvider'
import { WasmErrBanner } from '@src/components/WasmErrBanner'
import { NetworkContext } from '@src/hooks/useNetworkContext'
import { useNetworkStatus } from '@src/hooks/useNetworkStatus'
import { KclContextProvider } from '@src/lang/KclProvider'
import { coreDump } from '@src/lang/wasm'
import {
ASK_TO_OPEN_QUERY_PARAM,
BROWSER_PROJECT_NAME,
} from '@src/lib/constants'
import { CoreDumpManager } from '@src/lib/coredump'
import useHotkeyWrapper from '@src/lib/hotkeyWrapper'
import { isDesktop } from '@src/lib/isDesktop'
import makeUrlPathRelative from '@src/lib/makeUrlPathRelative'
import { PATHS } from '@src/lib/paths'
import { fileLoader, homeLoader, telemetryLoader } from '@src/lib/routeLoaders'
import {
codeManager,
engineCommandManager,
rustContext,
} from '@src/lib/singletons'
import { reportRejection } from '@src/lib/trap'
import { useToken } from '@src/machines/appMachine'
import Home from '@src/routes/Home'
import Onboarding, { onboardingRoutes } from '@src/routes/Onboarding'
import { Settings } from '@src/routes/Settings'
import SignIn from '@src/routes/SignIn'
import { Telemetry } from '@src/routes/Telemetry'
const createRouter = isDesktop() ? createHashRouter : createBrowserRouter

View File

@ -1,28 +1,29 @@
import { useRef, useMemo, memo, useCallback, useState } from 'react'
import { isCursorInSketchCommandRange } from 'lang/util'
import { editorManager, kclManager } from 'lib/singletons'
import { useModelingContext } from 'hooks/useModelingContext'
import { useNetworkContext } from 'hooks/useNetworkContext'
import { NetworkHealthState } from 'hooks/useNetworkStatus'
import { ActionButton } from 'components/ActionButton'
import { useKclContext } from 'lang/KclProvider'
import { ActionButtonDropdown } from 'components/ActionButtonDropdown'
import { memo, useCallback, useMemo, useRef, useState } from 'react'
import { useHotkeys } from 'react-hotkeys-hook'
import Tooltip from 'components/Tooltip'
import { useAppState } from 'AppState'
import { CustomIcon } from 'components/CustomIcon'
import {
toolbarConfig,
import { useAppState } from '@src/AppState'
import { ActionButton } from '@src/components/ActionButton'
import { ActionButtonDropdown } from '@src/components/ActionButtonDropdown'
import { CustomIcon } from '@src/components/CustomIcon'
import Tooltip from '@src/components/Tooltip'
import { useModelingContext } from '@src/hooks/useModelingContext'
import { useNetworkContext } from '@src/hooks/useNetworkContext'
import { NetworkHealthState } from '@src/hooks/useNetworkStatus'
import { useKclContext } from '@src/lang/KclProvider'
import { isCursorInFunctionDefinition } from '@src/lang/queryAst'
import { isCursorInSketchCommandRange } from '@src/lang/util'
import { isDesktop } from '@src/lib/isDesktop'
import { openExternalBrowserIfDesktop } from '@src/lib/openWindow'
import { editorManager, kclManager } from '@src/lib/singletons'
import type {
ToolbarItem,
ToolbarItemCallbackProps,
ToolbarItemResolved,
ToolbarModeName,
} from 'lib/toolbar'
import { isDesktop } from 'lib/isDesktop'
import { openExternalBrowserIfDesktop } from 'lib/openWindow'
import { isCursorInFunctionDefinition } from 'lang/queryAst'
import { commandBarActor } from 'machines/commandBarMachine'
import { isArray } from 'lib/utils'
} from '@src/lib/toolbar'
import { toolbarConfig } from '@src/lib/toolbar'
import { isArray } from '@src/lib/utils'
import { commandBarActor } from '@src/machines/commandBarMachine'
export function Toolbar({
className = '',

View File

@ -1,4 +1,5 @@
import { cameraMouseDragGuards, MouseGuard } from 'lib/cameraControls'
import type { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
import * as TWEEN from '@tweenjs/tween.js'
import {
Euler,
MathUtils,
@ -10,26 +11,34 @@ import {
Vector2,
Vector3,
} from 'three'
import type { CameraProjectionType } from '@rust/kcl-lib/bindings/CameraProjectionType'
import { isQuaternionVertical } from '@src/clientSideScene/helpers'
import {
DEBUG_SHOW_INTERSECTION_PLANE,
INTERSECTION_PLANE_LAYER,
SKETCH_LAYER,
ZOOM_MAGIC_NUMBER,
} from './sceneInfra'
import {
Subscription,
} from '@src/clientSideScene/sceneInfra'
import type { EngineCommand } from '@src/lang/std/artifactGraph'
import type {
EngineCommandManager,
Subscription,
UnreliableSubscription,
} from 'lang/std/engineConnection'
import { EngineCommand } from 'lang/std/artifactGraph'
import { toSync, uuidv4, getNormalisedCoordinates } from 'lib/utils'
import { deg2Rad } from 'lib/utils2d'
import { isReducedMotion, roundOff, throttle } from 'lib/utils'
import * as TWEEN from '@tweenjs/tween.js'
import { isQuaternionVertical } from './helpers'
import { reportRejection } from 'lib/trap'
import { CameraProjectionType } from '@rust/kcl-lib/bindings/CameraProjectionType'
import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/models'
} from '@src/lang/std/engineConnection'
import type { MouseGuard } from '@src/lib/cameraControls'
import { cameraMouseDragGuards } from '@src/lib/cameraControls'
import { reportRejection } from '@src/lib/trap'
import {
getNormalisedCoordinates,
isReducedMotion,
roundOff,
throttle,
toSync,
uuidv4,
} from '@src/lib/utils'
import { deg2Rad } from '@src/lib/utils2d'
const ORTHOGRAPHIC_CAMERA_SIZE = 20
const FRAMES_TO_ANIMATE_IN = 30

View File

@ -1,54 +1,60 @@
import { useRef, useEffect, useState, useMemo, Fragment } from 'react'
import { useModelingContext } from 'hooks/useModelingContext'
import { Dialog, Popover, Transition } from '@headlessui/react'
import { Fragment, useEffect, useMemo, useRef, useState } from 'react'
import toast from 'react-hot-toast'
import type { InstanceProps } from 'react-modal-promise'
import { create } from 'react-modal-promise'
import { cameraMouseDragGuards } from 'lib/cameraControls'
import { ARROWHEAD, DEBUG_SHOW_BOTH_SCENES } from './sceneInfra'
import { ReactCameraProperties } from './CameraControls'
import { throttle, toSync } from 'lib/utils'
import {
sceneInfra,
kclManager,
codeManager,
editorManager,
sceneEntitiesManager,
engineCommandManager,
rustContext,
} from 'lib/singletons'
import type { Node } from '@rust/kcl-lib/bindings/Node'
import type { ReactCameraProperties } from '@src/clientSideScene/CameraControls'
import {
EXTRA_SEGMENT_HANDLE,
PROFILE_START,
getParentGroup,
} from './sceneEntities'
import { SegmentOverlay, SketchDetails } from 'machines/modelingMachine'
import { findUsesOfTagInPipe, getNodeFromPath } from 'lang/queryAst'
} from '@src/clientSideScene/sceneConstants'
import {
CallExpression,
CallExpressionKw,
PathToNode,
Program,
Expr,
parse,
recast,
defaultSourceRange,
resultIsOk,
topLevelRange,
} from 'lang/wasm'
import { CustomIcon, CustomIconName } from 'components/CustomIcon'
import { ConstrainInfo } from 'lang/std/stdTypes'
import { getConstraintInfo, getConstraintInfoKw } from 'lang/std/sketch'
import { Dialog, Popover, Transition } from '@headlessui/react'
import toast from 'react-hot-toast'
import { InstanceProps, create } from 'react-modal-promise'
import { executeAstMock } from 'lang/langHelpers'
ARROWHEAD,
DEBUG_SHOW_BOTH_SCENES,
} from '@src/clientSideScene/sceneInfra'
import { ActionButton } from '@src/components/ActionButton'
import type { CustomIconName } from '@src/components/CustomIcon'
import { CustomIcon } from '@src/components/CustomIcon'
import { useModelingContext } from '@src/hooks/useModelingContext'
import { executeAstMock } from '@src/lang/langHelpers'
import {
deleteSegmentFromPipeExpression,
removeSingleConstraintInfo,
} from 'lang/modifyAst'
import { ActionButton } from 'components/ActionButton'
import { err, reportRejection, trap } from 'lib/trap'
import { Node } from '@rust/kcl-lib/bindings/Node'
import { commandBarActor } from 'machines/commandBarMachine'
import { useSettings } from 'machines/appMachine'
} from '@src/lang/modifyAst'
import { findUsesOfTagInPipe, getNodeFromPath } from '@src/lang/queryAst'
import { getConstraintInfo, getConstraintInfoKw } from '@src/lang/std/sketch'
import type { ConstrainInfo } from '@src/lang/std/stdTypes'
import { topLevelRange } from '@src/lang/util'
import type {
CallExpression,
CallExpressionKw,
Expr,
PathToNode,
Program,
} from '@src/lang/wasm'
import { defaultSourceRange, parse, recast, resultIsOk } from '@src/lang/wasm'
import { cameraMouseDragGuards } from '@src/lib/cameraControls'
import {
codeManager,
editorManager,
engineCommandManager,
kclManager,
rustContext,
sceneEntitiesManager,
sceneInfra,
} from '@src/lib/singletons'
import { err, reportRejection, trap } from '@src/lib/trap'
import { throttle, toSync } from '@src/lib/utils'
import type { useSettings } from '@src/machines/appMachine'
import { commandBarActor } from '@src/machines/commandBarMachine'
import type {
SegmentOverlay,
SketchDetails,
} from '@src/machines/modelingMachine'
function useShouldHideScene(): { hideClient: boolean; hideServer: boolean } {
const [isCamMoving, setIsCamMoving] = useState(false)

View File

@ -1,5 +1,6 @@
import { Quaternion } from 'three'
import { isQuaternionVertical } from './helpers'
import { isQuaternionVertical } from '@src/clientSideScene/helpers'
describe('isQuaternionVertical', () => {
it('should identify vertical quaternions', () => {

View File

@ -1,15 +1,13 @@
import { compareVec2Epsilon2 } from 'lang/std/sketch'
import type { Group, Mesh, OrthographicCamera, Quaternion } from 'three'
import {
GridHelper,
LineBasicMaterial,
OrthographicCamera,
PerspectiveCamera,
Group,
Mesh,
Quaternion,
Vector3,
} from 'three'
import { compareVec2Epsilon2 } from '@src/lang/std/sketch'
export function createGridHelper({
size,
divisions,

View File

@ -0,0 +1,76 @@
// Constants shared between sceneEntities.ts and segments.ts
// This file helps break circular dependencies
import type { Group } from 'three'
// Segment types
export const ARC_SEGMENT = 'arc-segment'
export const ARC_SEGMENT_BODY = 'arc-segment-body'
export const ARC_SEGMENT_DASH = 'arc-segment-dash'
export const STRAIGHT_SEGMENT = 'straight-segment'
export const STRAIGHT_SEGMENT_BODY = 'straight-segment-body'
export const STRAIGHT_SEGMENT_DASH = 'straight-segment-body-dashed'
export const CIRCLE_SEGMENT = 'circle-segment'
export const CIRCLE_SEGMENT_BODY = 'circle-segment-body'
export const CIRCLE_SEGMENT_DASH = 'circle-segment-body-dashed'
export const TANGENTIAL_ARC_TO_SEGMENT = 'tangential-arc-to-segment'
export const TANGENTIAL_ARC_TO_SEGMENT_BODY = 'tangential-arc-to-segment-body'
export const TANGENTIAL_ARC_TO__SEGMENT_DASH =
'tangential-arc-to-segment-body-dashed'
export const THREE_POINT_ARC_SEGMENT = 'three-point-arc-segment'
export const THREE_POINT_ARC_SEGMENT_BODY = 'three-point-arc-segment-body'
export const THREE_POINT_ARC_SEGMENT_DASH = 'three-point-arc-segment-dash'
export const CIRCLE_THREE_POINT_SEGMENT = 'circle-three-point-segment'
export const CIRCLE_THREE_POINT_SEGMENT_BODY = 'circle-segment-body'
export const CIRCLE_THREE_POINT_SEGMENT_DASH =
'circle-three-point-segment-body-dashed'
// Handle names
export const ARC_ANGLE_END = 'arc-angle-end'
export const ARC_ANGLE_REFERENCE_LINE = 'arc-angle-reference-line'
export const ARC_CENTER_TO_FROM = 'arc-center-to-from'
export const ARC_CENTER_TO_TO = 'arc-center-to-to'
export const CIRCLE_CENTER_HANDLE = 'circle-center-handle'
export const CIRCLE_THREE_POINT_HANDLE1 = 'circle-three-point-handle1'
export const CIRCLE_THREE_POINT_HANDLE2 = 'circle-three-point-handle2'
export const CIRCLE_THREE_POINT_HANDLE3 = 'circle-three-point-handle3'
export const THREE_POINT_ARC_HANDLE2 = 'three-point-arc-handle2'
export const THREE_POINT_ARC_HANDLE3 = 'three-point-arc-handle3'
export const EXTRA_SEGMENT_HANDLE = 'extraSegmentHandle'
export const PROFILE_START = 'profile-start'
// Additional types
export const DRAFT_DASHED_LINE = 'draft-dashed-line'
// Measurements
export const EXTRA_SEGMENT_OFFSET_PX = 8
export const SEGMENT_WIDTH_PX = 1.6
export const HIDE_SEGMENT_LENGTH = 75
export const HIDE_HOVER_SEGMENT_LENGTH = 60
// Segment groups
export const SEGMENT_BODIES = [
STRAIGHT_SEGMENT,
TANGENTIAL_ARC_TO_SEGMENT,
CIRCLE_SEGMENT,
CIRCLE_THREE_POINT_SEGMENT,
ARC_SEGMENT,
THREE_POINT_ARC_SEGMENT,
]
export const SEGMENT_BODIES_PLUS_PROFILE_START = [
...SEGMENT_BODIES,
PROFILE_START,
]
// Helper functions
export function getParentGroup(
object: any,
stopAt: string[] = SEGMENT_BODIES
): Group | null {
if (stopAt.includes(object?.userData?.type)) {
return object
} else if (object?.parent) {
return getParentGroup(object.parent, stopAt)
}
return null
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,13 @@
import * as TWEEN from '@tweenjs/tween.js'
import type {
Group,
Intersection,
Mesh,
MeshBasicMaterial,
Object3D,
Object3DEventMap,
Texture,
} from 'three'
import {
AmbientLight,
Color,
@ -5,32 +15,29 @@ import {
LineBasicMaterial,
OrthographicCamera,
PerspectiveCamera,
Raycaster,
Scene,
TextureLoader,
Vector2,
Vector3,
WebGLRenderer,
Raycaster,
Vector2,
Group,
MeshBasicMaterial,
Mesh,
Intersection,
Object3D,
Object3DEventMap,
TextureLoader,
Texture,
} from 'three'
import { Coords2d, compareVec2Epsilon2 } from 'lang/std/sketch'
import { useModelingContext } from 'hooks/useModelingContext'
import * as TWEEN from '@tweenjs/tween.js'
import { Axis, NonCodeSelection } from 'lib/selections'
import { type BaseUnit } from 'lib/settings/settingsTypes'
import { CameraControls } from './CameraControls'
import { EngineCommandManager } from 'lang/std/engineConnection'
import { MouseState, SegmentOverlayPayload } from 'machines/modelingMachine'
import { getAngle, throttle } from 'lib/utils'
import { Themes } from 'lib/theme'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { orthoScale, perspScale } from './helpers'
import { CameraControls } from '@src/clientSideScene/CameraControls'
import { orthoScale, perspScale } from '@src/clientSideScene/helpers'
import type { useModelingContext } from '@src/hooks/useModelingContext'
import type { EngineCommandManager } from '@src/lang/std/engineConnection'
import type { Coords2d } from '@src/lang/std/sketch'
import { compareVec2Epsilon2 } from '@src/lang/std/sketch'
import type { Axis, NonCodeSelection } from '@src/lib/selections'
import { type BaseUnit } from '@src/lib/settings/settingsTypes'
import { Themes } from '@src/lib/theme'
import { getAngle, throttle } from '@src/lib/utils'
import type {
MouseState,
SegmentOverlayPayload,
} from '@src/machines/modelingMachine'
type SendType = ReturnType<typeof useModelingContext>['send']

View File

View File

@ -1,4 +1,4 @@
import { Coords2d } from 'lang/std/sketch'
import type { NormalBufferAttributes, Texture } from 'three'
import {
BoxGeometry,
BufferGeometry,
@ -8,25 +8,33 @@ import {
EllipseCurve,
ExtrudeGeometry,
Group,
LineCurve3,
LineBasicMaterial,
LineDashedMaterial,
Line,
LineBasicMaterial,
LineCurve3,
LineDashedMaterial,
Mesh,
MeshBasicMaterial,
NormalBufferAttributes,
Points,
PointsMaterial,
Shape,
SphereGeometry,
Texture,
Vector2,
Vector3,
} from 'three'
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { PathToNode, Sketch, getTangentialArcToInfo } from 'lang/wasm'
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js'
import { calculate_circle_from_3_points } from '@rust/kcl-wasm-lib/pkg/kcl_wasm_lib'
import type { Sketch } from '@rust/kcl-lib/bindings/Sketch'
import {
ARC_ANGLE_END,
ARC_ANGLE_REFERENCE_LINE,
ARC_CENTER_TO_FROM,
ARC_CENTER_TO_TO,
ARC_SEGMENT,
ARC_SEGMENT_BODY,
ARC_SEGMENT_DASH,
CIRCLE_CENTER_HANDLE,
CIRCLE_SEGMENT,
CIRCLE_SEGMENT_BODY,
@ -49,42 +57,37 @@ import {
TANGENTIAL_ARC_TO_SEGMENT,
TANGENTIAL_ARC_TO_SEGMENT_BODY,
TANGENTIAL_ARC_TO__SEGMENT_DASH,
ARC_SEGMENT,
ARC_SEGMENT_BODY,
ARC_SEGMENT_DASH,
ARC_ANGLE_END,
getParentGroup,
ARC_CENTER_TO_FROM,
ARC_CENTER_TO_TO,
ARC_ANGLE_REFERENCE_LINE,
THREE_POINT_ARC_HANDLE2,
THREE_POINT_ARC_HANDLE3,
THREE_POINT_ARC_SEGMENT,
THREE_POINT_ARC_SEGMENT_BODY,
THREE_POINT_ARC_SEGMENT_DASH,
THREE_POINT_ARC_HANDLE2,
THREE_POINT_ARC_HANDLE3,
} from './sceneEntities'
import { getTangentPointFromPreviousArc } from 'lib/utils2d'
getParentGroup,
} from '@src/clientSideScene/sceneConstants'
import type { SceneInfra } from '@src/clientSideScene/sceneInfra'
import {
ARROWHEAD,
DRAFT_POINT,
SceneInfra,
SEGMENT_LENGTH_LABEL,
SEGMENT_LENGTH_LABEL_OFFSET_PX,
SEGMENT_LENGTH_LABEL_TEXT,
} from './sceneInfra'
import { Themes, getThemeColorForThreeJs } from 'lib/theme'
import { isClockwise, normaliseAngle, roundOff } from 'lib/utils'
import {
} from '@src/clientSideScene/sceneInfra'
import type { Coords2d } from '@src/lang/std/sketch'
import type { SegmentInputs } from '@src/lang/std/stdTypes'
import type { PathToNode } from '@src/lang/wasm'
import { getTangentialArcToInfo } from '@src/lang/wasm'
import type { Selections } from '@src/lib/selections'
import type { Themes } from '@src/lib/theme'
import { getThemeColorForThreeJs } from '@src/lib/theme'
import { err } from '@src/lib/trap'
import { isClockwise, normaliseAngle, roundOff } from '@src/lib/utils'
import { getTangentPointFromPreviousArc } from '@src/lib/utils2d'
import { commandBarActor } from '@src/machines/commandBarMachine'
import type {
SegmentOverlay,
SegmentOverlayPayload,
SegmentOverlays,
} from 'machines/modelingMachine'
import { SegmentInputs } from 'lang/std/stdTypes'
import { err } from 'lib/trap'
import { sceneInfra } from 'lib/singletons'
import { Selections } from 'lib/selections'
import { calculate_circle_from_3_points } from '@rust/kcl-wasm-lib/pkg/kcl_wasm_lib'
import { commandBarActor } from 'machines/commandBarMachine'
} from '@src/machines/modelingMachine'
const ANGLE_INDICATOR_RADIUS = 30 // in px
interface CreateSegmentArgs {
@ -205,6 +208,7 @@ class StraightSegment implements SegmentUtils {
from,
to,
scale,
sceneInfra,
})
segmentGroup.add(arrowGroup)
segmentGroup.add(lengthIndicatorGroup)
@ -572,6 +576,7 @@ class CircleSegment implements SegmentUtils {
from: center,
to: [center[0] + radius, center[1]],
scale,
sceneInfra,
})
arcMesh.userData.type = meshType
@ -1002,6 +1007,7 @@ class ArcSegment implements SegmentUtils {
from: center,
to: from,
scale,
sceneInfra,
})
const grey = 0xaaaaaa
@ -1059,6 +1065,7 @@ class ArcSegment implements SegmentUtils {
center[1] + Math.sin(endAngle) * radius,
],
scale,
sceneInfra,
})
endAngleLengthIndicator.name = 'endAngleLengthIndicator'
@ -1679,11 +1686,13 @@ function createLengthIndicator({
to,
scale,
length = 0.1,
sceneInfra,
}: {
from: Coords2d
to: Coords2d
scale: number
length?: number
sceneInfra: SceneInfra
}) {
const lengthIndicatorGroup = new Group()
lengthIndicatorGroup.name = SEGMENT_LENGTH_LABEL

View File

@ -1,4 +1,4 @@
import { getPathOrUrlFromArgs, parseCLIArgs } from 'commandLineArgs'
import { getPathOrUrlFromArgs, parseCLIArgs } from '@src/commandLineArgs'
const linuxDeepLinkArgv = [
'/tmp/.mount_Zoo Movq3t0x/zoo-modeling-app',

View File

@ -1,6 +1,7 @@
import { render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import { ActionButton } from './ActionButton'
import { ActionButton } from '@src/components/ActionButton'
describe('ActionButton tests', () => {
it('ActionButton with no iconStart or iconEnd should have even left and right padding', () => {

Some files were not shown because too many files have changed in this diff Show More