Compare commits

..

23 Commits

Author SHA1 Message Date
147268eaa1 Clean up 2025-06-18 10:33:13 -04:00
7f1552b667 back to reg width 2025-06-18 09:53:03 -04:00
e6c9a0f03c WIP: footer buttons 2025-06-18 09:19:41 -04:00
3a9ce876ac Add typecheck 2025-06-17 17:07:14 -04:00
a0edee7393 Fix nodeToEdit not having hidden: true on Shell 2025-06-17 16:41:11 -04:00
9ab00a449a Fixed up more tests related to sweep behavior change 2025-06-17 15:43:29 -04:00
2042339c99 More fixes 2025-06-17 15:19:53 -04:00
92bd8a9f61 Upgrade e2e tests to cmdBar fixtures with fixes 2025-06-17 15:04:14 -04:00
50fb46185e Fix labels for tests 2025-06-17 14:49:15 -04:00
edc4b75077 Remove options bool icon 2025-06-17 14:46:52 -04:00
9c554b4179 More UI polish 2025-06-17 11:56:55 -04:00
78a47ab3e1 Clean up extrude specific changes 2025-06-17 10:48:47 -04:00
fc6a9e33e4 Labels in progress button and option arg section heading 2025-06-17 10:46:07 -04:00
a4c00d0d2c Proper optional args line in review 2025-06-17 10:01:50 -04:00
164df4e864 Merge branch 'main' into pierremtb/issue7495-add-bidirectional-args-to-point-and-click-extrude 2025-06-17 09:15:13 -04:00
d8c168e7f8 Add twistAng 2025-06-16 15:50:56 -04:00
8706767b9f Merge branch 'main' into pierremtb/issue7495-add-bidirectional-args-to-point-and-click-extrude 2025-06-16 14:25:56 -04:00
8138f74cbd WIP 2025-06-16 14:25:22 -04:00
7e578f6d57 Make currentArg always part of header 2025-06-16 13:06:13 -04:00
e8ab2ccbe3 Add bidirectionalLength 2025-06-16 12:57:38 -04:00
4f3742c826 Show skip true args in header in review phase 2025-06-16 12:03:15 -04:00
3339da96b5 Wire up edit flow for symmetric 2025-06-16 11:32:35 -04:00
1a1a152fbf WIP: Add bidirectional args to point-and-click Extrude
Will eventually close #7495
2025-06-16 11:20:57 -04:00
951 changed files with 4285 additions and 88508 deletions

View File

@ -3,17 +3,17 @@
NODE_ENV=development
DEV=true
# App
VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
VITE_KITTYCAD_API_BASE_URL=https://api.dev.zoo.dev
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev
VITE_KC_SITE_APP_URL=https://app.dev.zoo.dev
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=5000
#VITE_WASM_URL="optional override of Wasm URL if not on default port 3000"
#VITE_KITTYCAD_API_TOKEN="required for testing, optional to skip auth in the app"
FAIL_ON_CONSOLE_ERRORS=true
#VITE_KC_DEV_TOKEN="optional token to skip auth in the app"
#token="required token for playwright. TODO: clean up env vars in #3973"
# KCL
RUST_BACKTRACE=1
PYO3_PYTHON=/usr/local/bin/python3
#KITTYCAD_API_TOKEN=$VITE_KITTYCAD_API_TOKEN
#KITTYCAD_API_TOKEN="required token for engine testing"
FAIL_ON_CONSOLE_ERRORS=true

View File

@ -1,8 +1,7 @@
NODE_ENV=production
# App
VITE_KC_API_WS_MODELING_URL=wss://api.zoo.dev/ws/modeling/commands
VITE_KITTYCAD_API_BASE_URL=https://api.zoo.dev
VITE_KC_API_BASE_URL=https://api.zoo.dev
VITE_KC_SITE_BASE_URL=https://zoo.dev
VITE_KC_SITE_APP_URL=https://app.zoo.dev
VITE_KC_SKIP_AUTH=false
VITE_KC_CONNECTION_TIMEOUT_MS=15000

View File

@ -2,7 +2,7 @@
name: Release
about: Create a new release for the Zoo Design Studio
title: "Cut release v1.?.?"
labels: [meta/release]
labels: [release]
---
> Instructions: https://github.com/KittyCAD/modeling-app/blob/main/CONTRIBUTING.md#shipping-releases
@ -19,8 +19,7 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release
* [ ] Open the application again and confirm the updater can downgrade
## macOS via ???
@ -28,8 +27,7 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release
* [ ] Open the application again and confirm the updater can downgrade
## Linux via ???
@ -37,5 +35,4 @@ Release builds URL: ???
* [ ] Confirm the application opens (dismiss the updater)
* [ ] Create a project with a basic Text-to-CAD prompt
* [ ] Confirm the result is viewable in an engine stream
* [ ] Use 'Check for updates' to bring back the updater toast
* [ ] Confirm the app can update to the previous release
* [ ] Open the application again and confirm the updater can downgrade

View File

@ -43,7 +43,7 @@ jobs:
- name: Download Wasm Cache
id: download-wasm
if: ${{ github.event_name == 'pull_request' && steps.filter.outputs.rust == 'false' }}
uses: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@v7
continue-on-error: true
with:
github_token: ${{secrets.GITHUB_TOKEN}}
@ -362,7 +362,7 @@ jobs:
- name: Authenticate to Google Cloud
if: ${{ env.IS_STAGING == 'true' }}
uses: 'google-github-actions/auth@v2.1.10'
uses: 'google-github-actions/auth@v2.1.8'
with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'

View File

@ -31,15 +31,15 @@ jobs:
- name: Use correct Rust toolchain
shell: bash
run: |
cp .github/workflows/nightly-rust-toolchain.toml rust-toolchain.toml
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
- name: Install rust
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache-workspaces: rust
components: rustfmt
- name: Run nightly cargo fmt
- name: Run cargo fmt
run: |
cd rust
cargo +nightly fmt -- --check
cargo fmt -- --check
shell: bash

View File

@ -25,8 +25,8 @@ jobs:
- runner=8cpu-linux-x64
- extras=s3-cache
steps:
- uses: runs-on/action@v2
- uses: actions/create-github-app-token@v2
- uses: runs-on/action@v1
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
@ -149,8 +149,8 @@ jobs:
partitionIndex: [1, 2, 3, 4, 5, 6]
partitionTotal: [6]
steps:
- uses: runs-on/action@v2
- uses: actions/create-github-app-token@v2
- uses: runs-on/action@v1
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
@ -207,8 +207,8 @@ jobs:
- runner=32cpu-linux-x64
- extras=s3-cache
steps:
- uses: runs-on/action@v2
- uses: actions/create-github-app-token@v2
- uses: runs-on/action@v1
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}

View File

@ -46,7 +46,7 @@ jobs:
- name: Download Wasm cache
id: download-wasm
if: ${{ github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
uses: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@v7
continue-on-error: true
with:
github_token: ${{secrets.GITHUB_TOKEN}}
@ -95,8 +95,7 @@ jobs:
shell: bash
run: npm run build:wasm
- name: Upload compiled wasm artifacts
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
with:
name: prepared-wasm
path: |
@ -110,7 +109,7 @@ jobs:
steps:
- uses: actions/create-github-app-token@v2
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
@ -157,7 +156,7 @@ jobs:
timeout_minutes: 5
max_attempts: 5
env:
VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
TAB_API_URL: ${{ secrets.TAB_API_URL }}
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
@ -169,7 +168,7 @@ jobs:
if: always()
run: npm run test:snapshots -- --last-failed --update-snapshots
env:
VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
TAB_API_URL: ${{ secrets.TAB_API_URL }}
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
@ -177,8 +176,7 @@ jobs:
CI_SUITE: e2e:snapshots
TARGET: web
- name: Upload playwright report
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report-snapshot-${{ github.sha }}
@ -230,7 +228,7 @@ jobs:
steps:
- uses: actions/create-github-app-token@v2
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
@ -284,7 +282,7 @@ jobs:
timeout_minutes: 5
max_attempts: 5
env:
VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
TAB_API_URL: ${{ secrets.TAB_API_URL }}
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
@ -292,8 +290,7 @@ jobs:
CI_SUITE: e2e:web
TARGET: web
- name: Upload playwright report
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() && (success() || failure()) }}
with:
name: playwright-report-web-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
@ -410,7 +407,7 @@ jobs:
max_attempts: 9
env:
FAIL_ON_CONSOLE_ERRORS: true
VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
TAB_API_URL: ${{ secrets.TAB_API_URL }}
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
@ -418,8 +415,7 @@ jobs:
CI_SUITE: e2e:desktop
TARGET: desktop
- name: Upload test report
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-desktop-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
@ -428,8 +424,7 @@ jobs:
retention-days: 30
overwrite: true
- name: Upload playwright report
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report-desktop-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/create-github-app-token@v2
- uses: actions/create-github-app-token@v1
id: app-token
with:
# required

View File

@ -328,7 +328,7 @@ jobs:
mkdir -p releases/language-server/${{ env.TAG }}
cp -r build/* releases/language-server/${{ env.TAG }}
- name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v2.1.10"
uses: "google-github-actions/auth@v2.1.8"
with:
credentials_json: "${{ secrets.GOOGLE_CLOUD_DL_SA }}"
- name: Set up Cloud SDK

View File

@ -113,7 +113,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v5
- uses: actions-rust-lang/setup-rust-toolchain@v1
- uses: taiki-e/install-action@just
- name: Run tests
@ -130,7 +130,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v5
- name: Install codespell
run: |
uv venv .venv
@ -161,7 +161,7 @@ jobs:
with:
path: rust/kcl-python-bindings
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v6
uses: astral-sh/setup-uv@v5
- name: do uv things
run: |
cd rust/kcl-python-bindings

View File

@ -1,3 +0,0 @@
[toolchain]
channel = "nightly"
components = ["rustfmt"]

View File

@ -108,7 +108,7 @@ jobs:
run: npm run files:set-notes
- name: Authenticate to Google Cloud
uses: 'google-github-actions/auth@v2.1.10'
uses: 'google-github-actions/auth@v2.1.8'
with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'

View File

@ -120,36 +120,6 @@ jobs:
- run: npm run circular-deps:diff
npm-url-checker:
runs-on: ubuntu-latest
needs: npm-build-wasm
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- run: npm install
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Copy prepared wasm
run: |
ls -R prepared-wasm
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
mkdir rust/kcl-wasm-lib/pkg
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
- name: Copy prepared ts-rs bindings
run: |
ls -R prepared-ts-rs-bindings
mkdir rust/kcl-lib/bindings
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
- run: npm run url-checker:diff
python-codespell:
runs-on: ubuntu-22.04
steps:

View File

@ -62,7 +62,7 @@ jobs:
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: xvfb-run -a npm run test:unit
env:
VITE_KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- name: Check for changes
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}

2
.gitignore vendored
View File

@ -87,4 +87,4 @@ venv
.vscode-test
.biome/
.million
.million

View File

@ -65,7 +65,7 @@ If you're not a Zoo employee you won't be able to access the dev environment, yo
### Development environment variables
The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `zoo.dev`). There is an optional environment variable called `VITE_KITTYCAD_API_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service.
The Copilot LSP plugin in the editor requires a Zoo API token to run. In production, we authenticate this with a token via cookie in the browser and device auth token in the desktop environment, but this token is inaccessible in the dev browser version because the cookie is considered "cross-site" (from `localhost` to `zoo.dev`). There is an optional environment variable called `VITE_KC_DEV_TOKEN` that you can populate with a dev token in a `.env.development.local` file to not check it into Git, which will use that token instead of other methods for the LSP service.
### Developing in Chrome
@ -96,7 +96,7 @@ To package the app for your platform with electron-builder, run `npm run tronb:p
Prepare these system dependencies:
- Set `$VITE_KITTYCAD_API_TOKEN` from https://zoo.dev/account/api-tokens
- Set $token from https://zoo.dev/account/api-tokens
#### Snapshot tests (Google Chrome on Ubuntu only)
@ -235,47 +235,6 @@ To display logging (to the terminal or console) set `ZOO_LOG=1`. This will log s
To enable memory metrics, build with `--features dhat-heap`.
## Running scripts
There are multiple scripts under the folder path `./scripts` which can be used in various settings.
### Pattern for a static file, npm run commands, and CI-CD checks
If you want to implement a static checker follow this pattern. Two static checkers we have are circular dependency checks in our typescript code and url checker to see if any hard coded URL is the typescript application 404s. We have a set of known files in `./scripts/known/*.txt` which is the baseline.
If you improve the baseline, run the overwrite command and commit the new smaller baseline. Try not to make the baseline bigger, the CI CD will complain.
These baselines are to hold us to higher standards and help implement automated testing against the repository
#### Output result to stdout
- `npm run circular-deps`
- `npm run url-checker`
- create a `<name>.sh` file that will run the static checker then output the result to `stdout`
#### Overwrite result to known .txt file on disk
If the application needs to overwrite the known file on disk use this pattern. This known .txt file will be source controlled as the baseline
- `npm run circular-deps:overwrite`
- `npm run url-checker:overwrite`
#### Diff baseline and current
These commands will write a /tmp/ file on disk and compare it to the known file in the repository. This command will also be used in the CI CD pipeline for automated checks
- create a `diff-<name>.sh` file that is the script to diff your tmp file to the baseline
e.g. `diff-url-checker.sh`
```bash
#!/bin/bash
set -euo pipefail
npm run url-checker > /tmp/urls.txt
diff --ignore-blank-lines -w /tmp/urls.txt ./scripts/known/urls.txt
```
- `npm run circular-deps:diff`
- `npm run url-checker:diff`
## Proposing changes
Before you submit a contribution PR to this repo, please ensure that:
@ -321,9 +280,6 @@ Assign someone to each section of the manual checklist generated by the issue te
Follow the instructions [here](./rust/README.md) to publish new crates.
This ensures that the KCL accepted by the app is also accepted by the CLI.
If there are documentation changes, merge the corresponding Dependabot PRs [here](https://github.com/KittyCAD/website/pulls/app%2Fdependabot) for the website.
You can trigger Dependabot to check for updates [here](https://github.com/KittyCAD/website/network/updates/17261214/jobs).
#### 5. Publish the release
Head over to https://github.com/KittyCAD/modeling-app/releases/new, pick the newly created tag and type it in the **Release title** field as well.

View File

@ -49,7 +49,7 @@ RUST_SOURCES := $(wildcard rust/**/*.rs)
REACT_SOURCES := $(wildcard src/*.tsx) $(wildcard src/**/*.tsx)
TYPESCRIPT_SOURCES := tsconfig.* $(wildcard src/*.ts) $(wildcard src/**/*.ts)
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx) .env*
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
.PHONY: build
build: install public/kcl_wasm_lib_bg.wasm public/kcl-samples/manifest.json .vite/build/main.js
@ -62,10 +62,7 @@ else
endif
public/kcl-samples/manifest.json: $(KCL_SOURCES)
ifndef WINDOWS
cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
@ touch $@
endif
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
npm run tronb:vite:dev

View File

@ -83,13 +83,6 @@ Allow orbiting in sketch mode.
Whether to show the debug panel, which lets you see various states of the app to aid in development.
**Default:** None
##### fixed_size_grid
If true, the grid cells will be fixed-size, where the width is your default length unit. If false, the grid will get larger as you zoom out, and smaller as you zoom in.
**Default:** None

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,11 +10,9 @@ Extend the current sketch with a new involute circular curve.
```kcl
involuteCircular(
@sketch: Sketch,
startRadius: number(Length),
endRadius: number(Length),
angle: number(Angle),
startRadius?: number(Length),
endRadius?: number(Length),
startDiameter?: number(Length),
endDiameter?: number(Length),
reverse?: bool,
tag?: TagDecl,
): Sketch
@ -27,11 +25,9 @@ involuteCircular(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `sketch` | [`Sketch`](/docs/kcl-std/types/std-types-Sketch) | Which sketch should this path be added to? | Yes |
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, start_radius is the radius of the inner circle. | Yes |
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, end_radius is the radius of the outer circle. | Yes |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | The angle to rotate the involute by. A value of zero will produce a curve with a tangent along the x-axis at the start point of the curve. | Yes |
| `startRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startRadius is the radius of the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
| `endRadius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endRadius is the radius of the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
| `startDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, startDiameter describes the inner circle. Either `startRadius` or `startDiameter` must be given (but not both). | No |
| `endDiameter` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The involute is described between two circles, endDiameter describes the outer circle. Either `endRadius` or `endDiameter` must be given (but not both). | No |
| `reverse` | [`bool`](/docs/kcl-std/types/std-types-bool) | If reverse is true, the segment will start from the end of the involute, otherwise it will start from that start. | No |
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this line. | No |

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,7 @@ revolved around the same axis.
| `sketches` | [`[Sketch; 1+]`](/docs/kcl-std/types/std-types-Sketch) | The sketch or set of sketches that should be revolved | Yes |
| `axis` | [`Axis2d`](/docs/kcl-std/types/std-types-Axis2d) or [`Edge`](/docs/kcl-std/types/std-types-Edge) | Axis of revolution. | Yes |
| `angle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | Angle to revolve (in degrees). Default is 360. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Tolerance for the revolve operation. | No |
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
| `bidirectionalAngle` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | If specified, will also revolve in the opposite direction to 'angle' to the specified angle. If 'symmetric' is true, this value is ignored. | No |
| `tagStart` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | A named tag for the face at the start of the revolve, i.e. the original sketch. | No |

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -28,7 +28,7 @@ will smoothly blend the transition.
| `solid` | [`Solid`](/docs/kcl-std/types/std-types-Solid) | The solid whose edges should be filletted | Yes |
| `radius` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The radius of the fillet | Yes |
| `tags` | [`[Edge; 1+]`](/docs/kcl-std/types/std-types-Edge) | The paths you want to fillet | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance for this fillet | No |
| `tag` | [`TagDecl`](/docs/kcl-std/types/std-types-TagDecl) | Create a new tag which refers to this fillet | No |
### Returns

File diff suppressed because one or more lines are too long

View File

@ -24,7 +24,7 @@ verifying fit, and analyzing overlapping geometries in assemblies.
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `solids` | `[Solid; 2+]` | The solids to intersect. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the intersection operation. | No |
### Returns

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -27,7 +27,7 @@ and complex multi-body part modeling.
|----------|------|-------------|----------|
| `solids` | [`[Solid; 1+]`](/docs/kcl-std/types/std-types-Solid) | The solids to use as the base to subtract from. | Yes |
| `tools` | [`[Solid]`](/docs/kcl-std/types/std-types-Solid) | The solids to subtract. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the subtraction operation. | No |
### Returns

View File

@ -21,7 +21,7 @@ union(
| Name | Type | Description | Required |
|----------|------|-------------|----------|
| `solids` | `[Solid; 2+]` | The solids to union. | Yes |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | Defines the smallest distance below which two entities are considered coincident, intersecting, coplanar, or similar. For most use cases, it should not be changed from its default value of 10^-7 millimeters. | No |
| `tolerance` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The tolerance to use for the union operation. | No |
### Returns

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -67,12 +67,10 @@ layout: manual
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`planeOf`](/docs/kcl-std/functions/std-sketch-planeOf)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
* [`rectangle`](/docs/kcl-std/functions/std-sketch-rectangle)
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)

View File

@ -32,12 +32,10 @@ This module contains functions for creating and manipulating sketches, and makin
* [`patternCircular2d`](/docs/kcl-std/functions/std-sketch-patternCircular2d)
* [`patternLinear2d`](/docs/kcl-std/functions/std-sketch-patternLinear2d)
* [`patternTransform2d`](/docs/kcl-std/functions/std-sketch-patternTransform2d)
* [`planeOf`](/docs/kcl-std/functions/std-sketch-planeOf)
* [`polygon`](/docs/kcl-std/functions/std-sketch-polygon)
* [`profileStart`](/docs/kcl-std/functions/std-sketch-profileStart)
* [`profileStartX`](/docs/kcl-std/functions/std-sketch-profileStartX)
* [`profileStartY`](/docs/kcl-std/functions/std-sketch-profileStartY)
* [`rectangle`](/docs/kcl-std/functions/std-sketch-rectangle)
* [`revolve`](/docs/kcl-std/functions/std-sketch-revolve)
* [`segAng`](/docs/kcl-std/functions/std-sketch-segAng)
* [`segEnd`](/docs/kcl-std/functions/std-sketch-segEnd)

View File

@ -1,5 +1,6 @@
import { expect, test } from '@e2e/playwright/zoo-test'
// test file is for testing auth functionality
test.describe('Authentication tests', () => {
test(
`The user can sign out and back in`,
@ -12,12 +13,22 @@ test.describe('Authentication tests', () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.projectSection.waitFor()
// This is only needed as an override to test-utils' setup() for this test
await page.addInitScript(() => {
localStorage.setItem('TOKEN_PERSIST_KEY', '')
})
await test.step('Click on sign out and expect sign in page', async () => {
await toolbar.userSidebarButton.click()
await toolbar.signOutButton.click()
await expect(signInPage.signInButton).toBeVisible()
})
await test.step("Refresh doesn't log the user back in", async () => {
await page.reload()
await expect(signInPage.signInButton).toBeVisible()
})
await test.step('Click on sign in and cancel, click again and expect different code', async () => {
await signInPage.signInButton.click()
await expect(signInPage.userCode).toBeVisible()

View File

@ -12,7 +12,7 @@ test.describe('Point and click for boolean workflows', () => {
},
{
name: 'subtract',
code: 'subtract(extrude001, tools = extrude006)',
code: 'subtract([extrude001], tools = [extrude006])',
},
{
name: 'intersect',
@ -81,8 +81,6 @@ test.describe('Point and click for boolean workflows', () => {
if (operationName !== 'subtract') {
// should down shift key to select multiple objects
await page.keyboard.down('Shift')
} else {
await cmdBar.progressCmdBar()
}
// Select second object
@ -105,8 +103,8 @@ test.describe('Point and click for boolean workflows', () => {
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Solids: '1 path',
Tools: '1 path',
Tool: '1 path',
Target: '1 path',
},
commandName,
})

View File

@ -5,7 +5,6 @@ import { uuidv4 } from '@src/lib/utils'
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 type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -15,18 +14,13 @@ test.describe('Can create sketches on all planes and their back sides', () => {
homePage: HomePageFixture,
scene: SceneFixture,
toolbar: ToolbarFixture,
cmdBar: CmdBarFixture,
plane: string,
clickCoords: { x: number; y: number }
) => {
const u = await getUtils(page)
// await page.addInitScript(() => {
// localStorage.setItem('persistCode', '@settings(defaultLengthUnit = in)')
// })
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
// await scene.settled(cmdBar)
const XYPlanRed: [number, number, number] = [98, 50, 51]
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
@ -125,166 +119,12 @@ test.describe('Can create sketches on all planes and their back sides', () => {
]
for (const config of planeConfigs) {
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
await sketchOnPlaneAndBackSideTest(
page,
homePage,
scene,
toolbar,
cmdBar,
config.plane,
config.coords
)
})
}
})
test.describe('Can create sketches on offset planes and their back sides', () => {
const sketchOnPlaneAndBackSideTest = async (
page: Page,
homePage: HomePageFixture,
scene: SceneFixture,
toolbar: ToolbarFixture,
cmdbar: CmdBarFixture,
plane: string,
clickCoords: { x: number; y: number }
) => {
const u = await getUtils(page)
await page.addInitScript(() => {
localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit = in)
xyPlane = offsetPlane(XY, offset = 0.05)
xzPlane = offsetPlane(XZ, offset = 0.05)
yzPlane = offsetPlane(YZ, offset = 0.05)
`
)
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
// await scene.settled(cmdbar)
const XYPlanRed: [number, number, number] = [74, 74, 74]
await scene.expectPixelColor(XYPlanRed, { x: 700, y: 300 }, 15)
await u.openDebugPanel()
const coord =
plane === '-XY' || plane === '-YZ' || plane === 'XZ' ? -100 : 100
const camCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_look_at',
center: { x: 0, y: 0, z: 0 },
vantage: { x: coord, y: coord, z: coord },
up: { x: 0, y: 0, z: 1 },
},
}
const updateCamCommand: EngineCommand = {
type: 'modeling_cmd_req',
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_get_settings',
},
}
const prefix = plane.length === 3 ? '-' : ''
const planeName = plane
.slice(plane.length === 3 ? 1 : 0)
.toLocaleLowerCase()
const codeLine1 = `sketch001 = startSketchOn(${prefix}${planeName}Plane)`
const codeLine2 = `profile001 = startProfile(sketch001, at = [${0.91 + (plane[0] === '-' ? 0.01 : 0)}, -${1.21 + (plane[0] === '-' ? 0.01 : 0)}])`
await u.openDebugPanel()
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await u.sendCustomCmd(camCommand)
await page.waitForTimeout(100)
await u.sendCustomCmd(updateCamCommand)
await u.closeDebugPanel()
await toolbar.openFeatureTreePane()
await toolbar.getDefaultPlaneVisibilityButton('XY').click()
await toolbar.getDefaultPlaneVisibilityButton('XZ').click()
await toolbar.getDefaultPlaneVisibilityButton('YZ').click()
await expect(
toolbar
.getDefaultPlaneVisibilityButton('YZ')
.locator('[aria-label="eye crossed out"]')
).toBeVisible()
await page.mouse.click(clickCoords.x, clickCoords.y)
await page.waitForTimeout(600) // wait for animation
await toolbar.waitUntilSketchingReady()
await expect(
page.getByRole('button', { name: 'line Line', exact: true })
).toBeVisible()
await u.closeDebugPanel()
await page.mouse.click(707, 393)
await expect(page.locator('.cm-content')).toContainText(codeLine1)
await expect(page.locator('.cm-content')).toContainText(codeLine2)
await page
.getByRole('button', { name: 'line Line', exact: true })
.first()
.click()
await u.openAndClearDebugPanel()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.clearCommandLogs()
await u.removeCurrentCode()
}
const planeConfigs = [
{
plane: 'XY',
coords: { x: 600, y: 388 },
description: 'red plane',
},
{
plane: 'YZ',
coords: { x: 700, y: 250 },
description: 'green plane',
},
{
plane: 'XZ',
coords: { x: 684, y: 427 },
description: 'blue plane',
},
{
plane: '-XY',
coords: { x: 600, y: 118 },
description: 'back of red plane',
},
{
plane: '-YZ',
coords: { x: 700, y: 219 },
description: 'back of green plane',
},
{
plane: '-XZ',
coords: { x: 700, y: 80 },
description: 'back of blue plane',
},
]
for (const config of planeConfigs) {
test(config.plane, async ({ page, homePage, scene, toolbar, cmdBar }) => {
await sketchOnPlaneAndBackSideTest(
page,
homePage,
scene,
toolbar,
cmdBar,
config.plane,
config.coords
)

View File

@ -265,8 +265,6 @@ middle(0)
})
await expect(
page.getByText(`assert failed: Expected 0 to be greater than 0 but it wasn't
Backtrace:
assert()
check()
middle()`)

View File

@ -525,9 +525,7 @@ test.describe('Command bar tests', () => {
const projectName = 'test'
const beforeKclCode = `a = 5
b = a * a
c = 3 + a
theta = 45deg
`
c = 3 + a`
await context.folderSetupFn(async (dir) => {
const testProject = join(dir, projectName)
await fsp.mkdir(testProject, { recursive: true })
@ -617,45 +615,9 @@ theta = 45deg
stage: 'commandBarClosed',
})
})
await test.step(`Edit a parameter with explicit units via command bar`, async () => {
await cmdBar.cmdBarOpenBtn.click()
await cmdBar.chooseCommand('edit parameter')
await cmdBar
.selectOption({
name: 'theta',
})
.click()
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Edit parameter',
currentArgKey: 'value',
currentArgValue: '45deg',
headerArguments: {
Name: 'theta',
Value: '',
},
highlightedHeaderArg: 'value',
})
await cmdBar.argumentInput
.locator('[contenteditable]')
.fill('45deg + 1deg')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
commandName: 'Edit parameter',
headerArguments: {
Name: 'theta',
Value: '46deg',
},
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'commandBarClosed',
})
})
await editor.expectEditor.toContain(
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + atheta = 45deg + 1deg`
`a = 5b = a * amyParameter001 = ${newValue}c = 3 + a`
)
})

View File

@ -288,7 +288,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
// error text on hover
await page.hover('.cm-lint-marker-info')
await expect(
page.getByText('Identifiers should be lowerCamelCase').first()
page.getByText('Identifiers must be lowerCamelCase').first()
).toBeVisible()
await page.locator('#code-pane button:first-child').click()
@ -314,7 +314,7 @@ sketch_001 = startSketchOn(XY)
// error text on hover
await page.hover('.cm-lint-marker-info')
await expect(
page.getByText('Identifiers should be lowerCamelCase').first()
page.getByText('Identifiers must be lowerCamelCase').first()
).toBeVisible()
})
@ -511,7 +511,7 @@ sketch_001 = startSketchOn(XY)
// error text on hover
await page.hover('.cm-lint-marker-info')
await expect(
page.getByText('Identifiers should be lowerCamelCase').first()
page.getByText('Identifiers must be lowerCamelCase').first()
).toBeVisible()
// focus the editor
@ -539,7 +539,7 @@ sketch_001 = startSketchOn(XY)
// error text on hover
await page.hover('.cm-lint-marker-info')
await expect(
page.getByText('Identifiers should be lowerCamelCase').first()
page.getByText('Identifiers must be lowerCamelCase').first()
).toBeVisible()
})
@ -681,7 +681,7 @@ a1 = startSketchOn(offsetPlane(XY, offset = 10))
// error text on hover
await page.hover('.cm-lint-marker-info')
await expect(
page.getByText('Identifiers should be lowerCamelCase').first()
page.getByText('Identifiers must be lowerCamelCase').first()
).toBeVisible()
// select the line that's causing the error and delete it
@ -1617,33 +1617,4 @@ sketch001 = startSketchOn(XZ)
// Verify error is still visible
await expect(page.locator('.cm-lint-marker-error')).toHaveCount(1)
})
test('Core dump hotkey', async ({ page, scene, cmdBar, homePage }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
`
)
})
const viewportSize = { width: 1200, height: 800 }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
const modifier = process.platform === 'darwin' ? 'Meta' : 'Control'
await page.keyboard.press(`${modifier}+Shift+.`)
const toast1 = page.getByText('Starting core dump...')
await expect(toast1).toBeVisible()
const toast2 = page.getByText('Core dump completed')
await expect(toast2).toBeVisible()
})
})

View File

@ -229,12 +229,11 @@ test.describe('Feature Tree pane', () => {
const initialCode = `sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 5)
renamedExtrude = extrude(sketch001, length = ${initialInput})`
const newParameterName = 'length001'
const expectedCode = `${newParameterName} = 23
const newConstantName = 'length001'
const expectedCode = `${newConstantName} = 23
sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 5)
renamedExtrude = extrude(sketch001, length = ${newParameterName})`
const editedParameterValue = '23 * 2'
renamedExtrude = extrude(sketch001, length = ${newConstantName})`
await context.folderSetupFn(async (dir) => {
const testDir = join(dir, 'test-sample')
@ -280,7 +279,7 @@ test.describe('Feature Tree pane', () => {
})
})
await test.step('Add a parameter for distance argument and submit', async () => {
await test.step('Add a named constant for distance argument and submit', async () => {
await expect(cmdBar.currentArgumentInput).toBeVisible()
await cmdBar.variableCheckbox.click()
await cmdBar.progressCmdBar()
@ -297,43 +296,13 @@ test.describe('Feature Tree pane', () => {
highlightedCode: '',
diagnostics: [],
activeLines: [
`renamedExtrude = extrude(sketch001, length = ${newParameterName})`,
`renamedExtrude = extrude(sketch001, length = ${newConstantName})`,
],
})
await editor.expectEditor.toContain(expectedCode, {
shouldNormalise: true,
})
})
await test.step('Edit the parameter via the feature tree', async () => {
const parameter = await toolbar.getFeatureTreeOperation('Parameter', 0)
await parameter.dblclick()
await cmdBar.expectState({
commandName: 'Edit parameter',
currentArgKey: 'value',
currentArgValue: '23',
headerArguments: {
Name: newParameterName,
Value: '23',
},
stage: 'arguments',
highlightedHeaderArg: 'value',
})
await cmdBar.argumentInput
.locator('[contenteditable]')
.fill(editedParameterValue)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
commandName: 'Edit parameter',
headerArguments: {
Name: newParameterName,
Value: '46', // Shows calculated result
},
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(editedParameterValue)
})
})
test(`User can edit an offset plane operation from the feature tree`, async ({
context,

View File

@ -187,13 +187,6 @@ export class CmdBarFixture {
return this.page.getByRole('option', options)
}
/**
* Select an optional argument from the command bar during review
*/
clickOptionalArgument = async (argName: string) => {
await this.page.getByTestId(`cmd-bar-add-optional-arg-${argName}`).click()
}
/**
* Clicks the Create new variable button for kcl input
*/

View File

@ -183,15 +183,14 @@ export class EditorFixture {
scrollToText(text: string, placeCursor?: boolean) {
return this.page.evaluate(
(args: { text: string; placeCursor?: boolean }) => {
const editorView = window.editorManager.getEditorView()
// error TS2339: Property 'docView' does not exist on type 'EditorView'.
// Except it does so :shrug:
// @ts-ignore
const index = editorView?.docView.view.state.doc
let index = window.editorManager._editorView?.docView.view.state.doc
.toString()
.indexOf(args.text)
editorView?.focus()
editorView?.dispatch({
window.editorManager._editorView?.focus()
window.editorManager._editorView?.dispatch({
selection: window.EditorSelection.create([
window.EditorSelection.cursor(index),
]),

View File

@ -274,13 +274,6 @@ export class ToolbarFixture {
.nth(operationIndex)
}
getDefaultPlaneVisibilityButton(plane: 'XY' | 'XZ' | 'YZ' = 'XY') {
const index = plane === 'XZ' ? 0 : plane === 'XY' ? 1 : 2
return this.featureTreePane
.getByTestId('feature-tree-visibility-toggle')
.nth(index)
}
/**
* View source on a specific operation in the Feature Tree pane.
* @param operationName The name of the operation type

View File

@ -5,7 +5,7 @@ import type {
FullResult,
} from '@playwright/test/reporter'
class APIReporter implements Reporter {
class MyAPIReporter implements Reporter {
private pendingRequests: Promise<void>[] = []
private allResults: Record<string, any>[] = []
private blockingResults: Record<string, any>[] = []
@ -32,7 +32,7 @@ class APIReporter implements Reporter {
'X-API-Key': process.env.TAB_API_KEY || '',
}),
body: JSON.stringify({
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
project: 'https://github.com/KittyCAD/modeling-app',
branch:
process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
@ -60,7 +60,7 @@ class APIReporter implements Reporter {
const payload = {
// Required information
project: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}`,
project: 'https://github.com/KittyCAD/modeling-app',
suite: process.env.CI_SUITE || 'e2e',
branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || '',
commit: process.env.CI_COMMIT_SHA || process.env.GITHUB_SHA || '',
@ -124,4 +124,4 @@ class APIReporter implements Reporter {
}
}
export default APIReporter
export default MyAPIReporter

File diff suppressed because it is too large Load Diff

View File

@ -573,7 +573,7 @@ extrude002 = extrude(profile002, length = 150)
name: 'Projects',
})
const projectLink = page.getByRole('link', { name: 'bracket' })
const networkHealthIndicator = page.getByTestId(/network-toggle/)
const networkHealthIndicator = page.getByTestId('network-toggle')
await test.step('Check the home page', async () => {
await expect(projectsHeading).toBeVisible()

View File

@ -187,68 +187,6 @@ sketch001 = startProfile(sketch002, at = [12.34, -12.34])
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
})
test('Can select planes in Feature Tree after Start Sketch', async ({
page,
homePage,
toolbar,
editor,
}) => {
// Load the app with empty code
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`plane001 = offsetPlane(XZ, offset = 5)`
)
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await test.step('Click Start Sketch button', async () => {
await page.getByRole('button', { name: 'Start Sketch' }).click()
await expect(
page.getByRole('button', { name: 'Exit Sketch' })
).toBeVisible()
await expect(page.getByText('select a plane or face')).toBeVisible()
})
await test.step('Open feature tree and select Front plane (XZ)', async () => {
await toolbar.openFeatureTreePane()
await page.getByRole('button', { name: 'Front plane' }).click()
await page.waitForTimeout(600)
await expect(toolbar.lineBtn).toBeEnabled()
await editor.expectEditor.toContain('startSketchOn(XZ)')
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
})
await test.step('Click Start Sketch button again', async () => {
await page.getByRole('button', { name: 'Start Sketch' }).click()
await expect(
page.getByRole('button', { name: 'Exit Sketch' })
).toBeVisible()
})
await test.step('Select the offset plane', async () => {
await toolbar.openFeatureTreePane()
await page.getByRole('button', { name: 'Offset plane' }).click()
await page.waitForTimeout(600)
await expect(toolbar.lineBtn).toBeEnabled()
await editor.expectEditor.toContain('startSketchOn(plane001)')
})
})
test('Can edit segments by dragging their handles', () => {
const doEditSegmentsByDraggingHandle = async (
page: Page,
@ -1540,7 +1478,6 @@ sketch001 = startSketchOn(XZ)
await page.mouse.move(1200, 139)
await page.mouse.down()
await page.mouse.move(870, 250)
await page.mouse.up()
await page.waitForTimeout(200)
@ -1550,60 +1487,6 @@ sketch001 = startSketchOn(XZ)
)
})
test('Can undo with closed code pane', async ({
page,
homePage,
editor,
toolbar,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const viewportSize = { width: 1500, height: 750 }
await page.setBodyDimensions(viewportSize)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`@settings(defaultLengthUnit=in)
sketch001 = startSketchOn(XZ)
|> startProfile(at = [-10, -10])
|> line(end = [20.0, 10.0])
|> tangentialArc(end = [5.49, 8.37])`
)
})
await homePage.goToModelingScene()
await toolbar.waitForFeatureTreeToBeBuilt()
await scene.settled(cmdBar)
await (await toolbar.getFeatureTreeOperation('Sketch', 0)).dblclick()
await page.waitForTimeout(1000)
await page.mouse.move(1200, 139)
await page.mouse.down()
await page.mouse.move(870, 250)
await page.mouse.up()
await editor.expectEditor.toContain(`tangentialArc(end=[-5.85,4.32])`, {
shouldNormalise: true,
})
await u.closeKclCodePanel()
// Undo the last change
await page.keyboard.down('Control')
await page.keyboard.press('KeyZ')
await page.keyboard.up('Control')
await u.openKclCodePanel()
await editor.expectEditor.toContain(`tangentialArc(end = [5.49, 8.37])`, {
shouldNormalise: true,
})
})
test('Can delete a single segment line with keyboard', async ({
page,
scene,

View File

@ -798,7 +798,7 @@ test('theme persists', async ({ page, context, homePage }) => {
await page.getByTestId('settings-close-button').click()
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggle = page.getByTestId('network-toggle')
// simulate network down
await u.emulateNetworkConditions({

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -12,7 +12,6 @@ export const TEST_SETTINGS: DeepPartial<Settings> = {
},
onboarding_status: 'dismissed',
show_debug_panel: true,
fixed_size_grid: false,
},
modeling: {
enable_ssao: false,

View File

@ -24,15 +24,16 @@ test.describe('Test network related behaviors', () => {
await homePage.goToModelingScene()
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggle = page.getByTestId('network-toggle')
// This is how we wait until the stream is online
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled({ timeout: 15000 })
await expect(networkToggle).toBeVisible()
await networkToggle.hover()
const networkWidget = page.locator('[data-testid="network-toggle"]')
await expect(networkWidget).toBeVisible()
await networkWidget.hover()
const networkPopover = page.locator('[data-testid="network-popover"]')
await expect(networkPopover).not.toBeVisible()
@ -43,7 +44,7 @@ test.describe('Test network related behaviors', () => {
).toBeVisible()
// Click the network widget
await networkToggle.click()
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
@ -64,8 +65,8 @@ test.describe('Test network related behaviors', () => {
// Expect the network to be down
await expect(networkToggle).toContainText('Network health (Offline)')
// Click the network toggle
await networkToggle.click()
// Click the network widget
await networkWidget.click()
// Check the modal opened.
await expect(networkPopover).toBeVisible()
@ -98,7 +99,7 @@ test.describe('Test network related behaviors', () => {
'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar, scene, cmdBar }) => {
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggle = page.getByTestId('network-toggle')
const networkToggleConnectedText = page.getByText(
'Network health (Strong)'
)
@ -285,7 +286,7 @@ profile001 = startProfile(sketch001, at = [12.34, -12.34])
'Paused stream freezes view frame, unpause reconnect is seamless to user',
{ tag: ['@desktop', '@skipLocalEngine'] },
async ({ page, homePage, scene, cmdBar, toolbar, tronApp }) => {
const networkToggle = page.getByTestId(/network-toggle/)
const networkToggle = page.getByTestId('network-toggle')
const networkToggleConnectedText = page.getByText(
'Network health (Strong)'
)

View File

@ -17,7 +17,7 @@ import dotenv from 'dotenv'
const NODE_ENV = process.env.NODE_ENV || 'development'
dotenv.config({ path: [`.env.${NODE_ENV}.local`, `.env.${NODE_ENV}`] })
export const token = process.env.VITE_KITTYCAD_API_TOKEN || ''
export const token = process.env.token || ''
import type { ProjectConfiguration } from '@rust/kcl-lib/bindings/ProjectConfiguration'
@ -38,7 +38,7 @@ export const headerMasks = (page: Page) => [
]
export const lowerRightMasks = (page: Page) => [
page.getByTestId(/network-toggle/),
page.getByTestId('network-toggle'),
page.getByTestId('billing-remaining-bar'),
]
@ -159,10 +159,10 @@ async function openKclCodePanel(page: Page) {
await page.evaluate(() => {
// editorManager is available on the window object.
//@ts-ignore this is in an entirely different context that tsc can't see.
editorManager.getEditorView().dispatch({
editorManager._editorView.dispatch({
selection: {
//@ts-ignore this is in an entirely different context that tsc can't see.
anchor: editorManager.getEditorView().docView.length,
anchor: editorManager._editorView.docView.length,
},
scrollIntoView: true,
})
@ -880,10 +880,6 @@ export async function setup(
},
...TEST_SETTINGS.project,
onboarding_status: 'dismissed',
// Tests were written before this setting existed.
// It's true by default because it's a good user experience, but
// these tests require it to be false.
fixed_size_grid: false,
},
project: {
...TEST_SETTINGS.project,

View File

@ -8,37 +8,37 @@ test.describe('Testing Gizmo', () => {
const cases = [
{
testDescription: 'top view',
clickPosition: { x: 951, y: 402 },
clickPosition: { x: 951, y: 385 },
expectedCameraPosition: { x: 800, y: -152, z: 4886.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'bottom view',
clickPosition: { x: 951, y: 449 },
clickPosition: { x: 951, y: 429 },
expectedCameraPosition: { x: 800, y: -152, z: -4834.02 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'right view',
clickPosition: { x: 929, y: 435 },
clickPosition: { x: 929, y: 417 },
expectedCameraPosition: { x: 5660.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'left view',
clickPosition: { x: 974, y: 417 },
clickPosition: { x: 974, y: 397 },
expectedCameraPosition: { x: -4060.02, y: -152, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'back view',
clickPosition: { x: 967, y: 441 },
clickPosition: { x: 967, y: 421 },
expectedCameraPosition: { x: 800, y: 4708.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},
{
testDescription: 'front view',
clickPosition: { x: 935, y: 413 },
clickPosition: { x: 935, y: 393 },
expectedCameraPosition: { x: 800, y: -5012.02, z: 26 },
expectedCameraTarget: { x: 800, y: -152, z: 26 },
},

18
flake.lock generated
View File

@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1750865895,
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
"lastModified": 1745998881,
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
"type": "github"
},
"original": {
@ -36,11 +36,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1750865895,
"narHash": "sha256-p2dWAQcLVzquy9LxYCZPwyUdugw78Qv3ChvnX755qHA=",
"lastModified": 1745998881,
"narHash": "sha256-vonyYAKJSlsX4n9GCsS0pHxR6yCrfqBIuGvANlkwG6U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
"rev": "423d2df5b04b4ee7688c3d71396e872afa236a89",
"type": "github"
},
"original": {
@ -78,11 +78,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1750964660,
"narHash": "sha256-YQ6EyFetjH1uy5JhdhRdPe6cuNXlYpMAQePFfZj4W7M=",
"lastModified": 1745980514,
"narHash": "sha256-CITAeiuXGjDvT5iZBXr6vKVWQwsUQLJUMFO91bfJFC4=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "04f0fcfb1a50c63529805a798b4b5c21610ff390",
"rev": "7fbdae44b0f40ea432e46fd152ad8be0f8f41ad6",
"type": "github"
},
"original": {

7
interface.d.ts vendored
View File

@ -72,13 +72,16 @@ export interface IElectronAPI {
}
process: {
env: {
BASE_URL: string
IS_PLAYWRIGHT: string
VITE_KITTYCAD_API_TOKEN: string
VITE_KC_DEV_TOKEN: string
VITE_KC_API_WS_MODELING_URL: string
VITE_KITTYCAD_API_BASE_URL: string
VITE_KC_API_BASE_URL: string
VITE_KC_SITE_BASE_URL: string
VITE_KC_SITE_APP_URL: string
VITE_KC_SKIP_AUTH: string
VITE_KC_CONNECTION_TIMEOUT_MS: string
VITE_KC_DEV_TOKEN: string
NODE_ENV: string
PROD: string
DEV: string

View File

@ -125,57 +125,18 @@ test('Shows a loading spinner when uninitialized credit count', async () => {
await expect(queryByTestId('spinner')).toBeVisible()
})
const unKnownTierData = {
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 25,
},
subscriptions: {
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "unknown",
}
}
const freeTierData = {
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "free",
}
}
const proTierData = {
// These are all ignored
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
// This should be ignored because it's Pro tier.
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "pro",
}
}
const enterpriseTierData = {
// These are all ignored, user is part of an org.
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
// This should be ignored because it's Pro tier.
monthlyPayAsYouGoApiCreditsTotal: 20,
// This should be ignored because the user is part of an Org.
name: "free",
}
}
test('Shows the total credits for Unknown subscription', async () => {
const data = unKnownTierData
const data = {
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 25,
},
subscriptions: {
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "unknown",
}
}
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
@ -205,7 +166,17 @@ test('Shows the total credits for Unknown subscription', async () => {
})
test('Progress bar reflects ratio left of Free subscription', async () => {
const data = freeTierData
const data = {
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "free",
}
}
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
@ -241,7 +212,19 @@ test('Progress bar reflects ratio left of Free subscription', async () => {
})
})
test('Shows infinite credits for Pro subscription', async () => {
const data = proTierData
const data = {
// These are all ignored
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
// This should be ignored because it's Pro tier.
monthlyPayAsYouGoApiCreditsTotal: 20,
name: "pro",
}
}
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
@ -272,7 +255,19 @@ test('Shows infinite credits for Pro subscription', async () => {
await expect(queryByTestId('billing-remaining-progress-bar-inline')).toBe(null)
})
test('Shows infinite credits for Enterprise subscription', async () => {
const data = enterpriseTierData
const data = {
// These are all ignored, user is part of an org.
balance: {
monthlyApiCreditsRemaining: 10,
stableApiCreditsRemaining: 0,
},
subscriptions: {
// This should be ignored because it's Pro tier.
monthlyPayAsYouGoApiCreditsTotal: 20,
// This should be ignored because the user is part of an Org.
name: "free",
}
}
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
@ -302,58 +297,3 @@ test('Shows infinite credits for Enterprise subscription', async () => {
await expect(queryByTestId('infinity')).toBeVisible()
await expect(queryByTestId('billing-remaining-progress-bar-inline')).toBe(null)
})
test('Show upgrade button if credits are not infinite', async () => {
const data = freeTierData
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
}),
http.get('*/user/payment/subscriptions', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentSubscriptionsResponse(data.subscriptions))
}),
http.get('*/org', (req, res, ctx) => {
return new HttpResponse(403)
}),
)
const billingActor = createActor(billingMachine, { input: BILLING_CONTEXT_DEFAULTS }).start()
const { queryByTestId } = render(<BillingDialog
billingActor={billingActor}
/>)
await act(() => {
billingActor.send({ type: BillingTransition.Update, apiToken: "it doesn't matter wtf this is :)" })
})
await expect(queryByTestId('billing-upgrade-button')).toBeVisible()
})
test('Hide upgrade button if credits are infinite', async () => {
const data = enterpriseTierData
server.use(
http.get('*/user/payment/balance', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentBalanceResponse(data.balance))
}),
http.get('*/user/payment/subscriptions', (req, res, ctx) => {
return HttpResponse.json(createUserPaymentSubscriptionsResponse(data.subscriptions))
}),
// Ok finally the first use of an org lol
http.get('*/org', (req, res, ctx) => {
return HttpResponse.json(createOrgResponse())
}),
)
const billingActor = createActor(billingMachine, { input: BILLING_CONTEXT_DEFAULTS }).start()
const { queryByTestId } = render(<BillingDialog
billingActor={billingActor}
/>)
await act(() => {
billingActor.send({ type: BillingTransition.Update, apiToken: "it doesn't matter wtf this is :)" })
})
await expect(queryByTestId('billing-upgrade-button')).toBe(null)
})

1144
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -110,11 +110,8 @@
"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",
"url-checker":"./scripts/url-checker.sh",
"url-checker:overwrite":"npm run url-checker > scripts/known/urls.txt",
"url-checker:diff":"./scripts/diff-url-checker.sh",
"circular-deps": "dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx",
"circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > scripts/known/circular.txt",
"circular-deps:overwrite": "npm run circular-deps | sed '$d' | grep -v '^npm run' > known-circular.txt",
"circular-deps:diff": "./scripts/diff-circular-deps.sh",
"circular-deps:diff:nodejs": "npm run circular-deps:diff || node ./scripts/diff.js",
"files:set-version": "echo \"$(jq --arg v \"$VERSION\" '.version=$v' package.json --indent 2)\" > package.json",
@ -227,7 +224,7 @@
"ts-node": "^10.0.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.30.1",
"vite": "^5.4.19",
"vite": "^5.4.18",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -111,8 +111,7 @@ commaSep1NoTrailingComma<term> { term ("," term)* }
PipeSubstitution { "%" }
// Includes non-whitespace unicode characters.
identifier { $[a-zA-Z_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}] $[a-zA-Z0-9_\u{a1}-\u{167f}\u{1681}-\u{1fff}\u{200e}-\u{2027}\u{202a}-\u{202e}\u{2030}-\u{205e}\u{2061}-\u{2fff}\u{3001}-\u{fefe}\u{ff00}-\u{10ffff}]* }
identifier { (@asciiLetter | "_") (@asciiLetter | @digit | "_")* }
AnnotationName { "@" identifier? }
PropertyName { identifier }
TagDeclarator { "$" identifier }

View File

@ -29,7 +29,7 @@
"vscode-uri": "^3.1.0"
},
"devDependencies": {
"@types/node": "^24.0.7",
"@types/node": "^22.14.1",
"ts-node": "^10.9.2"
}
}

View File

@ -42,15 +42,15 @@ fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) {
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight))
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2))
|> involuteCircular(
startDiameter = baseDiameter,
endDiameter = tipDiameter,
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = helixCalc,
tag = $seg01,
)
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2))
|> involuteCircular(
startDiameter = baseDiameter,
endDiameter = tipDiameter,
startRadius = baseDiameter / 2,
endRadius = tipDiameter / 2,
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)),
reverse = true,
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

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