Compare commits

...

196 Commits

Author SHA1 Message Date
6c78dbd4c8 Force dev from main.ts :sad: 2025-01-22 16:17:19 +01:00
059593372a Attempt at building debug and dev 2025-01-22 15:47:42 +01:00
1ba8c5af00 @pierremtb spinner feedback 2025-01-22 09:35:19 -05:00
410b4e81eb @lf94 nit 2025-01-22 09:32:46 -05:00
30275d86cc Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-22 09:12:59 -05:00
39c40b2cde fmt 2025-01-22 09:12:40 -05:00
10789d9c3c set scene units based on a module's default units (#5127)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-01-22 15:23:55 +13:00
67cc4f5835 Tweaks to clarify tooltips from tool dropdown menus (#5123)
* Separate content from ToolbarItemTooltip, make simple and "rich" versions

* Add support for dropdown-arrow-only tooltip

* Add toolbar-wide hover timeouts and clears to switch between simple and rich tooltips

* Fix the dropdown arrow button hover styling now that they're separate

* Add missing doc links to rich toolbar tooltips

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Re-run CI after snapshots

* fix codespell

* fmt

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-21 18:32:56 -05:00
2692f2b73a Add units to geometry structs (#5075)
* Make all geometry KclValue variants into struct variants

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Add units to geometry types

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-01-21 20:42:09 +00:00
965cb18059 Parse units on numeric literals and keep them in the AST (#5061)
* Code changes

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* test changes

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Frontend changes

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Refactor asNum

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-01-22 08:29:30 +13:00
a022b8ef6c Fix suggestion for updating function decl syntax for anon functions (#5088)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-01-22 07:10:07 +13:00
907102a8fa Update dumb use of site URL instead of prod app URL 2025-01-21 12:46:45 -05:00
4d24bf7c94 Add API Call ID log for debugging (#5107) 2025-01-20 19:49:02 +00:00
9a537da183 Show toolbar tooltips on hover only, hide when dropdowns are open (#5109)
* Show toolbar tooltips on hover only, hide when dropdowns are open

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Re-run CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-18 05:22:22 -05:00
353eca110e Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-17 18:41:44 -05:00
df81b76b8b Bug fix follow-up for create project (#5105)
* fix dumb mistake in command flow for #5083

* Add e2e test for creating projects with the default interpolated name

* Drop that number to 12 ain't got all day

* Why do I have a kcl-samples submodule hanging around?

* Empty commit to remove the submodule
2025-01-17 23:10:28 +00:00
ac3f7ab712 Rust: Remove iai benchmark tests (#5102)
We don't get much value from these, we can always run criterion or valgrind locally.

If we want to measure instruction counts, we should be using codspeed.io instead because
they support visualizing and tracking over time.

If we want to track performance over time we should be using Kevin's perf monitor machine.
2025-01-17 15:42:51 -06:00
dac91d3b79 Add uniqueness check to "Create project" command (#5100)
* Add failing playwright test

* Make create generate a unique name if the given one collides

* Add a new consolidated getUniqueProjectName function with tests

* Use getUniqueProjectName

* Replace "New project" button text with "Create project"
cc @pierremtb

* Extend the e2e test to show the incrementing behavior
cc @lf94
2025-01-17 19:46:52 +00:00
0698432abf Rust artifact graph (#5068)
* Start porting artifact graph creation to Rust

* Add most of artifact graph creation

* Add handling loft command from recent PR

* Refactor artifact merge code so that it errors when a new artifact type is added

* Add sweep subtype

* Finish implementation of build artifact graph

* Fix wasm.ts to use new combined generated ts-rs file

* Fix Rust lints

* Fix lints

* Fix up replacement code

* Add artifact graph to WASM outcome

* Add artifact graph to simulation test output

* Add new artifact graph output snapshots

* Fix wall field and reduce unreachable code

* Change field order for subtype

* Change subtype to be determined from the request, like the TS

* Fix plane sweep_id

* Condense code

* Change ID types to be properly optional

* Change to favor the new ID, the same as TS

* Fix to make error impossible

* Rename artifact type tag values to match TS

* Fix name of field on Cap

* Update outputs

* Change to use Rust source range

* Update output snapshots

* Add conversion to mermaid mind map and add to snapshot tests

* Add new mermaid mind map output

* Add flowchart

* Remove raw artifact graph from tests

* Remove JSON artifact graph output

* Update output file with header

* Update output after adding flowchart

* Fix flowchart to not have duplicate edges, one in each direction

* Fix not not output duplicate edges in flowcharts

* Change flowchart edge style to be more obvious when a direction is missing

* Update output after deduplication of edges

* Fix not not skip sketch-on-face artifacts

* Add docs

* Fix edge iteration order to be stable

* Update output after fixing order

* Port TS artifactGraph.test.ts tests to simulation tests

* Add grouping segments and solid2ds with their path

* Update output flowcharts since grouping paths

* Remove TS artifactGraph tests

* Remove unused d3 dependencies

* Fix to track loft ID on paths

* Add command ID to error messages

* Move artifact graph test code to a separate file since it's a large file

* Reduce function visibility

* Remove TS artifact graph code

* Fix spelling error with serde

* Add TODO for edge cut consumed ID

* Add comment about mermaid edge rank

* Fix mermaid flowchart edge cuts to appear as children of their edges

* Update output since fixing flowchart order

* Fix to always build the artifact graph even when there's a KCL error

* Add artifact graph to error output

* Change optional ID merge to match TS

* Remove redundant SourceRange definition

* Remove Rust-flavored default source range function

* Add helper for source range creation

* Update doc comment for the website

* Update docs after doc comment change

* Fix to save engine responses in execution cache

* Remove unused import

* Fix to not call WASM function before beforeAll callback is run

* Remove more unused imports
2025-01-17 14:34:36 -05:00
fb56820811 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-17 11:25:30 -05:00
fb37bb83a8 Add "Share file" to command palette 2025-01-17 11:24:59 -05:00
f90811695d Refactor: break out copyFileShareLink into standalone function 2025-01-17 11:24:38 -05:00
0592d3b5da Selection dry-run validation for Shell (#4775)
* WIP: mess with shell selection validation
Will eventually fix #4711

* Update from main

* WIP: not working yet

* Working loft dry run validator

* Clean up shell (still not working)

* Bump kittycad-modeling-cmds

* Clean up

* Add logging

* Add proper object_id and face_id mapping, still not working for shell

* Fix faceId

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Working validation after engine merge; Clean up

* Fix codespell

* Add pw test

* More clean up

* Back to basics

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Clean up

* Fix tests

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Remove kcl-samples

---------

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-17 10:16:18 -05:00
max
31e4d60045 Refactor Fillet Playwright Test to the new Fixture-based Approach (#4909)
* add locator

* new test

* remove old test

* separation of setup steps

* improved click reliability

* fix ubuntu

* ubuntu fix 2

* ubuntu fix 3

* flaky cmdbar ubuntu

* ubuntu fix second yellow

* ubuntu update

* enable test for windows

* step(Initial test setup)

* extra await, just in case

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* screenshot

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-17 10:21:55 +01:00
c0817b00e4 Auto retry on yarn install as it sometimes fail on windows (#5077) 2025-01-16 18:03:31 -05:00
4ea1d16fb6 Loft command prompt focus fix (#5080) 2025-01-16 18:03:01 -05:00
d049bf33e8 Return key to go through Onboarding steps (#5086)
Fixes #5049
2025-01-16 17:45:59 -05:00
7b11047d07 Fix helix sweep, you can make springs! (#5089)
* fix dumb mistake

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

* updates for springs!

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

* update docs

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

* update known issues

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-01-16 13:50:13 -08:00
5c1dfe0c8e Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-16 14:12:20 -05:00
412e9568f2 Per-file units (use per-file settings for conversion functions) (#5064)
* Use the project default units for the per-file unit default values

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Use per-file units in conversion functions

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-01-17 07:55:01 +13:00
9be208e5e1 Fix wasm bundle upload (upload-artifact@v4) (#5084) 2025-01-16 13:33:14 -05:00
842ef5ede9 Feature: Allow orbit in sketch mode via setting (#4990)
* feat: enable/disable free camera aka allow orbit in sketch mode mvp

* fix: removing comments

* fix: logic for enabling and disabling in and out of sketch mode

* fix: fmt, linter, tsc fixes

* fix: added comment

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* fix: current,prev check to no op the useeffect if the values are the same

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-16 11:48:13 -06:00
3f855d7bad Make commands disable, not unregister, based on their machineActor (#5070)
* Make "Find and select command" global to commandBarMachine

* Make commands not removed based on their actor state, only disabled

* Sort commands better in CommandComboBox

* Break out sort logic, add a few unit tests

* Fix missed name change

* Needed to make one more change from source branch:
since `optionsFromContext` now only gets fired once, I/O-based options need to use the `options` config instead.

---------

Co-authored-by: 49fl <ircsurfer33@gmail.com>
2025-01-16 12:08:48 -05:00
0a1a6e50cf 3-point circle interactive component (#4982)
* Add dragging behavior to 3 point circle

Uses our talked about technique of calling Rust functions to calculate new
geometry coordinates and parameters. It works very well!

Need to have the modeling app show "edit sketch" still.

* Cargo fmt

* cargo fmt

* Address Jon's comments

* Fix clippy

* Dont use isNaN

* Make points easier to select (enlarge)

* Fix circle button not being activated

* Ensure efficiency of updating editor vs execution

* Make cargo clippy happy
2025-01-16 11:10:36 -05:00
f06873a0e2 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-16 09:52:26 -05:00
d4e955289c Add helix icon and start of toolbar/feature tree impl (#5062)
* Add icon

* Add to stdLibMap

* Add to toolbar as "kcl-only"

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
2025-01-16 14:22:19 +00:00
c147a219f4 Minor bits and pieces (#5066)
* Use std deprecation for int rather than a hack in the parser

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Don't allow an epsilon when converting floats to ints for property access

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Fixup tests

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-01-16 14:00:32 +13:00
09025179f9 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-15 19:34:40 -05:00
38513a1e25 Fix broken golden standard tests caused by changes to kcl-samples (#5065)
* Fix our golden standard tests (broken by new assemblies kcl-samples)

* Finally use the right combination of env vars

* Fix the manifest

* Continue to fix multiple file kcl-samples

* Fix loading in desktop app

* Type narrow for tsc

* fmt

---------

Co-authored-by: Frank Noirot <frank@kittycad.io>
2025-01-15 23:30:20 +00:00
521a593451 Bump typescript from 5.7.2 to 5.7.3 (#5021)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 12:37:22 -05:00
87c4e6c74e custom axis and origin example for helix (#5057)
* custom axis and origin for helix

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

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* empty

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-15 12:37:22 -05:00
82cd106898 Bump @types/node from 20.14.9 to 22.10.6 in /packages/codemirror-lsp-client (#5041) 2025-01-15 12:36:48 -05:00
max
e14cc4ace3 Remove Redundant Fillet Button State Test (#5009)
delete obsolete test
2025-01-15 12:36:48 -05:00
max
2a2a31d0ef Hook up chamfer UI with AST-mod (#4694)
* button

* config

* hook up with ast

* cmd bar test

* button states fix and test

* little naming fix

* xState action to actor

* remove button state test updates

* fixture-based approach

* nightly

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Update src/lib/toolbar.ts

Co-authored-by: Frank Noirot <frank@zoo.dev>

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2025-01-15 12:36:48 -05:00
f2669223c5 Bump xstate from 5.17.4 to 5.19.2 (#5027) 2025-01-15 12:36:48 -05:00
c3bc1fad6d ci: Add yarn test of packages/codemirror-lang-kcl (#5035)
* ci: Add yarn test of packages/codemirror-lang-kcl

* Fix CI error running tests

* Fix postcss config error
2025-01-15 12:36:48 -05:00
96ff1dd55b turns on helix from edge (#5036)
* updates for new lib

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

* autocomplete

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

* bump version

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

* bump all the things

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

* new samples

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

* docs

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-01-15 12:36:48 -05:00
82bd04631a Disable auto-updater on non-versioned builds (#5042) 2025-01-15 12:36:48 -05:00
abec2d6d66 Upgrade all wasm-bindgen dependencies together (#5037) 2025-01-15 12:36:48 -05:00
6089b1932a Fix Cargo.lock to not have changes (#5034) 2025-01-15 12:36:48 -05:00
074fd2b5c7 Fix artifact types to be more accurate (#5022) 2025-01-15 12:36:48 -05:00
b2485b804c Bump syn from 2.0.95 to 2.0.96 in /src/wasm-lib (#5015)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.95 to 2.0.96.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.95...2.0.96)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 12:36:48 -05:00
e753082653 Bump handlebars from 6.2.0 to 6.3.0 in /src/wasm-lib (#5012)
Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/sunng87/handlebars-rust/releases)
- [Changelog](https://github.com/sunng87/handlebars-rust/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sunng87/handlebars-rust/compare/v6.2.0...v6.3.0)

---
updated-dependencies:
- dependency-name: handlebars
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 12:36:48 -05:00
634745bb81 Bump @lezer/generator from 1.7.1 to 1.7.2 (#5018)
Bumps [@lezer/generator](https://github.com/lezer-parser/generator) from 1.7.1 to 1.7.2.
- [Changelog](https://github.com/lezer-parser/generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lezer-parser/generator/compare/1.7.1...1.7.2)

---
updated-dependencies:
- dependency-name: "@lezer/generator"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-15 12:36:48 -05:00
e3660c75fc Add packages to Dependabot updates (#5024) 2025-01-15 12:36:48 -05:00
ef61d10615 Change Dependabot PRs to always be made on Mondays (#5025) 2025-01-15 12:36:48 -05:00
c208e16c76 Developer workflow: added auto generated workspace file from vitest extension in vscode (#4997)
* chore: added auto generated workspace file from vitest extension in vscode

* fix: auto fmt fixes
2025-01-15 12:36:48 -05:00
585ca7e80f Fix lost lints and add new ones (#5011)
* Add eslint-plugin-jsx-a11y dependency

* Add jsx-a11y lint

* Add eslint-plugin-react-hooks dependency

* Add react hooks lints

* Ignore new react hooks lint in tests

* Add eslint-plugin-testing-library dependency

* Add testing-library lint

* Fix yarn lint to use all files recursively
2025-01-15 12:36:48 -05:00
f7bae1d221 Upgrade typescript-eslint from 5.62.0 to 8.19.1 and remove eslint-config-react-app (#5006) 2025-01-15 12:36:48 -05:00
339de00e68 Point-and-click Sweep (first PR) (#4989)
* Refactor 'Delete selection' as actor
Will fix #4662

* WIP logging

* WIP: working Solid3dGetExtrusionFaceInfo for loft

* Working wall deletion of loft

* Add offset plane deletion

* Add feature tree deletion of shell

* Clean up

* Revert "Clean up"

This reverts commit 214763cc2b.

* Clean up rust changes, taking the sketch with the most paths

* Working cap selection and deletion

* Clean up

* Add test for loft and offset plane deletion via selection

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Set reenter: false as it was originally

* Passing test

* Add shell deletion via feature tree test

* Revert the migration to promise actor

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Use cmd.id as solid_id after latest engine merge

* Add feature tree deletion of offset plane and fix lint

* Add feature tree deletion of loft

* Clean up

* Better comment

* Lint fix

* Remove sketch sorting

* WIP: sweep point-and-click

* Working sweep

* Add test

* Make sweep a development command

* Fix tsc error

* Clean up for review

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-15 12:36:47 -05:00
4f02e45da3 Add new lint to disallow use of confusing isNaN (#4999) 2025-01-15 12:36:47 -05:00
1908383f0e Fix so that all artifact commands are returned regardless of caching (#5005)
* Fix so that all artifact commands are returned regardless of caching

* Add some more docs and fix up old ones
2025-01-15 12:36:47 -05:00
68204bb23d Make the test executor a bit more patient (#5004) 2025-01-15 12:36:47 -05:00
5438a987ab Fix browser command flow, because we had made the projectMachine desktop-only on main 2025-01-15 11:35:59 -05:00
fa3f934948 Clean up unneeded PROD_TOKEN 2025-01-14 17:23:39 -05:00
08e714080e Use dev urls everywhere when configured that way
I think we were just using some constants that ended up returning bad
values for dev, it seemed to return a working shortlink when I went
through the flow.
2025-01-14 17:16:16 -05:00
c0c5c790ca Bump typescript from 5.7.2 to 5.7.3 (#5021)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.7.2 to 5.7.3.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-14 16:18:26 -05:00
8b60f75220 custom axis and origin example for helix (#5057)
* custom axis and origin for helix

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

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* empty

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-14 12:05:36 -08:00
f91ad4331f Bump @types/node from 20.14.9 to 22.10.6 in /packages/codemirror-lsp-client (#5041) 2025-01-14 17:36:46 +00:00
max
59103a2118 Remove Redundant Fillet Button State Test (#5009)
delete obsolete test
2025-01-14 12:09:29 -05:00
max
9737c2550a Hook up chamfer UI with AST-mod (#4694)
* button

* config

* hook up with ast

* cmd bar test

* button states fix and test

* little naming fix

* xState action to actor

* remove button state test updates

* fixture-based approach

* nightly

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Update src/lib/toolbar.ts

Co-authored-by: Frank Noirot <frank@zoo.dev>

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2025-01-14 12:08:32 -05:00
bf9d01a8dd Bump xstate from 5.17.4 to 5.19.2 (#5027) 2025-01-14 15:39:05 +00:00
702e322f90 ci: Add yarn test of packages/codemirror-lang-kcl (#5035)
* ci: Add yarn test of packages/codemirror-lang-kcl

* Fix CI error running tests

* Fix postcss config error
2025-01-14 09:30:08 -05:00
e82830754d turns on helix from edge (#5036)
* updates for new lib

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

* autocomplete

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

* bump version

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

* bump all the things

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

* new samples

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

* docs

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-01-13 23:34:43 +00:00
7806377a5a Disable auto-updater on non-versioned builds (#5042) 2025-01-13 17:40:51 -05:00
859afa2fd8 Upgrade all wasm-bindgen dependencies together (#5037) 2025-01-13 13:24:23 -08:00
0a5f3093fc Fix Cargo.lock to not have changes (#5034) 2025-01-13 15:38:24 -05:00
b65f7939f6 Fix artifact types to be more accurate (#5022) 2025-01-13 15:02:55 -05:00
c35dea5e07 Bump syn from 2.0.95 to 2.0.96 in /src/wasm-lib (#5015)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.95 to 2.0.96.
- [Release notes](https://github.com/dtolnay/syn/releases)
- [Commits](https://github.com/dtolnay/syn/compare/2.0.95...2.0.96)

---
updated-dependencies:
- dependency-name: syn
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 10:04:30 -08:00
fc66d4745f Bump handlebars from 6.2.0 to 6.3.0 in /src/wasm-lib (#5012)
Bumps [handlebars](https://github.com/sunng87/handlebars-rust) from 6.2.0 to 6.3.0.
- [Release notes](https://github.com/sunng87/handlebars-rust/releases)
- [Changelog](https://github.com/sunng87/handlebars-rust/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sunng87/handlebars-rust/compare/v6.2.0...v6.3.0)

---
updated-dependencies:
- dependency-name: handlebars
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 13:03:34 -05:00
b313d26c2a Bump @lezer/generator from 1.7.1 to 1.7.2 (#5018)
Bumps [@lezer/generator](https://github.com/lezer-parser/generator) from 1.7.1 to 1.7.2.
- [Changelog](https://github.com/lezer-parser/generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lezer-parser/generator/compare/1.7.1...1.7.2)

---
updated-dependencies:
- dependency-name: "@lezer/generator"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 11:48:13 -05:00
00b94ead62 Add packages to Dependabot updates (#5024) 2025-01-13 11:29:00 -05:00
df01c233e4 Fix unit test, use kebab-case for url query param 2025-01-13 10:42:08 -05:00
b30a37a0b3 Fix broken rename and delete project commands
Something about the `optionsFromContext` config no longer works with file I/O-related commands. I suspect this has to do with our read/write loop patching
2025-01-13 10:34:38 -05:00
0531ea1ce9 Change Dependabot PRs to always be made on Mondays (#5025) 2025-01-13 15:30:33 +00:00
5f9a4887c1 Developer workflow: added auto generated workspace file from vitest extension in vscode (#4997)
* chore: added auto generated workspace file from vitest extension in vscode

* fix: auto fmt fixes
2025-01-13 09:57:12 -05:00
da7dfa16d8 Fix lost lints and add new ones (#5011)
* Add eslint-plugin-jsx-a11y dependency

* Add jsx-a11y lint

* Add eslint-plugin-react-hooks dependency

* Add react hooks lints

* Ignore new react hooks lint in tests

* Add eslint-plugin-testing-library dependency

* Add testing-library lint

* Fix yarn lint to use all files recursively
2025-01-13 09:30:14 -05:00
363ae10658 Upgrade typescript-eslint from 5.62.0 to 8.19.1 and remove eslint-config-react-app (#5006) 2025-01-11 09:59:09 -05:00
ac4a6c84cf Point-and-click Sweep (first PR) (#4989)
* Refactor 'Delete selection' as actor
Will fix #4662

* WIP logging

* WIP: working Solid3dGetExtrusionFaceInfo for loft

* Working wall deletion of loft

* Add offset plane deletion

* Add feature tree deletion of shell

* Clean up

* Revert "Clean up"

This reverts commit 214763cc2b.

* Clean up rust changes, taking the sketch with the most paths

* Working cap selection and deletion

* Clean up

* Add test for loft and offset plane deletion via selection

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Set reenter: false as it was originally

* Passing test

* Add shell deletion via feature tree test

* Revert the migration to promise actor

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Use cmd.id as solid_id after latest engine merge

* Add feature tree deletion of offset plane and fix lint

* Add feature tree deletion of loft

* Clean up

* Better comment

* Lint fix

* Remove sketch sorting

* WIP: sweep point-and-click

* Working sweep

* Add test

* Make sweep a development command

* Fix tsc error

* Clean up for review

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-11 08:20:49 -05:00
c6fad2e2dc Add new lint to disallow use of confusing isNaN (#4999) 2025-01-11 05:28:12 +00:00
013cb10961 Fix so that all artifact commands are returned regardless of caching (#5005)
* Fix so that all artifact commands are returned regardless of caching

* Add some more docs and fix up old ones
2025-01-10 22:33:05 -05:00
6261083cb1 Make the test executor a bit more patient (#5004) 2025-01-10 20:05:27 -05:00
82aefec34d Fix unit test 2025-01-10 18:04:33 -05:00
679b65f643 Lints, fmt, tsc 2025-01-10 17:04:09 -05:00
d64270d494 Undo mistaken or unecessary changes 2025-01-10 17:00:18 -05:00
c06b2b4029 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-10 16:50:12 -05:00
8b8a2bc4e2 Add E2E test for "add to existing project" user flow 2025-01-10 16:22:28 -05:00
af702ae1b2 Fix the "existing project" user flow 2025-01-10 16:11:15 -05:00
83e72dafa3 Add a couple component tests for OpenInDesktopAppHandler 2025-01-10 15:55:43 -05:00
e417e60053 Add E2E test for importing file from URL 2025-01-10 15:08:56 -05:00
2b0ba37ed0 Use Chromium instead of Chrome for Playwright Electron (#5001)
* Use Chromium instead of Chrome for Playwright Electron

* Remove channel
2025-01-10 13:37:26 -05:00
96174f3cf6 Increase playwright retries to 5 (#5000) 2025-01-10 13:34:27 -05:00
aed62ff912 Fix flaky playwright test 'Shell point-and-click sketch on face' (#5002)
Fixes #4998
2025-01-10 13:32:31 -05:00
ebc6b6460d Separate creating createFileUrl and shortlink so it is unit testable 2025-01-10 12:57:16 -05:00
91f0cfe467 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-10 11:32:36 -05:00
9334d64608 Allow under-development commands in Nightly builds (#4995)
* Allow under-development commands in Nightly builds
Fixes #4994

* Fix warning

* Add back status: development to Revolve
2025-01-10 16:24:07 +00:00
a2ff0aeceb Clean up unecessary file 2025-01-10 11:18:14 -05:00
f05acf92cc Styling updates to OpenInDesktopAppHandler 2025-01-10 10:36:05 -05:00
4fa7d2d8c8 Feature: new axis and edge selection workflow for point and click revolve (#4939)
* feat: implemented axis or edge selection workflow in the commandbar

* fix: removing comment

* fix: removing console logs from testing

* fix: fixing lint and tsc errors

* fix: changed copy

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2025-01-10 08:52:04 -06:00
3e615dfdbc Update Katie's name reference and link in onboarding (#4967) 2025-01-09 22:07:40 -05:00
c9860af29f Fix Shell point-and-click picking the wrong face with piped extrudes (#4981)
* [BUG] Shell point and click references the wrong feature
Fixes #4961

* Add test for sketch on face based on extrudes in pipe

* Add no extrude in pipe case

* Lint

* Add scene.waitForExecutionDone()

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Update src/lang/modifyAst/addShell.ts

Co-authored-by: Frank Noirot <frank@zoo.dev>

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
2025-01-10 01:20:07 +00:00
670faac1e8 Rework to open browser app first, then send along to the desktop app if asked 2025-01-09 17:58:12 -05:00
23a42f0195 Bump @kittycad/lib to v2.0.13 (#4988) 2025-01-09 16:02:05 -05:00
a77fa639f3 Point-and-click deletion of lofts, shells, and offset planes (#4898)
* Refactor 'Delete selection' as actor
Will fix #4662

* WIP logging

* WIP: working Solid3dGetExtrusionFaceInfo for loft

* Working wall deletion of loft

* Add offset plane deletion

* Add feature tree deletion of shell

* Clean up

* Revert "Clean up"

This reverts commit 214763cc2b.

* Clean up rust changes, taking the sketch with the most paths

* Working cap selection and deletion

* Clean up

* Add test for loft and offset plane deletion via selection

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Set reenter: false as it was originally

* Passing test

* Add shell deletion via feature tree test

* Revert the migration to promise actor

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* Trigger CI

* Use cmd.id as solid_id after latest engine merge

* Add feature tree deletion of offset plane and fix lint

* Add feature tree deletion of loft

* Clean up

* Better comment

* Lint fix

* Remove sketch sorting

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-09 15:36:50 -05:00
0a5ad7c95b Show deprecated indicator in CodeMirror autocomplete (#4983) 2025-01-09 09:15:00 -05:00
4a654523d2 Prevent toSync from clobbering stack traces (#4980)
* Prevent toSync from clobbering stack traces

* Capture error on the outside of the toSync catch

* fmt

* Actually fix it 🤦
2025-01-09 03:40:42 +00:00
73a7e2bfd6 Return modeling commands from KCL execution (#4912)
* Add Rust side artifacts for startSketchOn face or plane

* Add Rust-generated artifacts to ExecOutcome

* Add output of artifact commands

* Add new output files

* Wire the artifact commands to the artifact graph creation

* Fix to use real PartialEq implemented in modeling commands

* Fix modeling commands with zero fields to work

* Fix missing artifactCommands field in errors

* Change artifact graph to be built from artifact commands

* Wire up ExecState artifacts, but not using them yet

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>

* Remove unneeded local var

* Fix test to fail with a helpful error message when command isn't found

* Rename and deprecate orderedCommands

* Update comment about borrowing

* Move ArtifactCommand tracking to the EngineManager trait

* Update artifact commands since tracking in the engine

* Upgrade kittycad-modeling-cmds from 0.2.85 to 0.2.86

* Remove unneeded JsonSchema derive to speed up build

* Fix to not fail on floating point differences in CI

* Update artifact commands output since truncating floating point numbers

* Fix to ensure artifact commands get cleared after a clear scene

* Update artifact commands snapshot after clearing them on clear scene

* Remove all remnants of OrderedCommands

* Update output for new simulation tests

---------

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
2025-01-09 01:02:30 +00:00
ca09224c92 Get primary user flow working on desktop 2025-01-08 16:56:48 -05:00
5cbd11cec8 Add useCreateFileLinkQuery on Home page 2025-01-08 12:15:59 -05:00
28eb99f655 Merge branch 'main' into franknoirot/4088/create-file-url 2025-01-08 12:00:19 -05:00
eb0850fea9 Make codespell smooth when run locally (#4978)
* Skip the out/ directory produced by yarn tron:package

* Skip all dist/ dirs

Produced when building rollup packages like codemirror-lang-kcl.

* Skip typescript build info

* Fix typo instead of excluding file

---------

Co-authored-by: Matt Mundell <matt@mundell.me>
2025-01-08 10:36:37 -06:00
029f76f273 Nadro/4857/wasm panic catching errors (#4901)
* chore: skeleton code to initialize and detect the global WASM panic

* chore: implementing a reimport method to fix the wasm instance being bricked

* fix: cleaning up tsc/lint

* fix: renaming file to be more accurate

* fix: added toast message

* fix: types...

* fix: typed the functions with arg spreads
2025-01-08 15:58:41 +00:00
max
28b5f7080c Refactor Fillet AST Mod to Async Actor (#4803) 2025-01-08 16:05:24 +01:00
5b1dcfecd6 Open updater toast changelog links externally (#4970)
* fix: Hook into markdown-generated anchors to avoid e.g breaking the desktop app

* add comment

* Disable eslint on copied line from ts-stack

---------

Co-authored-by: marc2332 <mespinsanz@gmail.com>
2025-01-08 09:15:18 -05:00
f89d191425 add a test for foreign characters in project name (#4976)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-01-08 05:34:08 -05:00
2f4e4b62a8 Don't wait for !isExecuting to play the stream (#4971)
* Add failing test for current behavior

* Change stream behavior so that stream is played regardless of `isExecuting`

* Change expected pixel color

* Widen possible pixel color diff because local and CI produce slightly different colors
2025-01-08 04:34:57 -05:00
5ebd5c8dbb Enhance helixes (#4973)
* 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>

* allow a helix to go into a sweep

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

* fix clippy

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

* updates

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

* udpates

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

* updates

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

* snapshots

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

* docs

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

* docs

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

* fix

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>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* updates

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

* updates

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

* docs

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

* updates

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

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* em,pty

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* updates

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>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-08 03:10:53 +00:00
a9ceaf2678 fix: make error for missing a closing bracket clearer (#4974)
* fix: make error for missing a closing bracket clearer

* Fix test for error message

---------

Co-authored-by: Tom Pridham <pridham.tom@gmail.com>
2025-01-08 01:55:07 +00:00
c8afd3399b Dead code clean up (smol PR) (#4653)
* general clean up

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-08 01:46:05 +00:00
5dda4828c6 Bump react-modal from 3.16.1 to 3.16.3 (#4924)
Bumps [react-modal](https://github.com/reactjs/react-modal) from 3.16.1 to 3.16.3.
- [Release notes](https://github.com/reactjs/react-modal/releases)
- [Changelog](https://github.com/reactjs/react-modal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/reactjs/react-modal/compare/v3.16.1...v3.16.3)

---
updated-dependencies:
- dependency-name: react-modal
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 15:24:24 -08:00
72acab752c Bump async-trait from 0.1.83 to 0.1.85 in /src/wasm-lib (#4969)
Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.83 to 0.1.85.
- [Release notes](https://github.com/dtolnay/async-trait/releases)
- [Commits](https://github.com/dtolnay/async-trait/compare/0.1.83...0.1.85)

---
updated-dependencies:
- dependency-name: async-trait
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 12:54:16 -08:00
81df38ad1c Bump happy-dom from 15.11.7 to 16.3.0 (#4925)
* Bump happy-dom from 15.11.7 to 16.3.0

Bumps [happy-dom](https://github.com/capricorn86/happy-dom) from 15.11.7 to 16.3.0.
- [Release notes](https://github.com/capricorn86/happy-dom/releases)
- [Commits](https://github.com/capricorn86/happy-dom/compare/v15.11.7...v16.3.0)

---
updated-dependencies:
- dependency-name: happy-dom
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-07 20:51:15 +00:00
0576a2bef1 Bump react-hotkeys-hook from 4.5.1 to 4.6.1 (#4953)
Bumps [react-hotkeys-hook](https://github.com/JohannesKlauss/react-keymap-hook) from 4.5.1 to 4.6.1.
- [Release notes](https://github.com/JohannesKlauss/react-keymap-hook/releases)
- [Changelog](https://github.com/JohannesKlauss/react-hotkeys-hook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/JohannesKlauss/react-keymap-hook/compare/v4.5.1...v4.6.1)

---
updated-dependencies:
- dependency-name: react-hotkeys-hook
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 20:46:57 +00:00
4b2f6b4647 refactor: Remove unused UpdaterModal component (#4791) 2025-01-07 15:28:33 -05:00
69edaa4183 implementing array pop (#4806)
* implementing naive array pop

* multi-profile follow up. (#4802)

* multi-profile work

* fix enter sketch on cap

* fix coderef problem for walls and caps

* allow sketch mode entry from circle

* clean up

* update snapshot

* Look at this (photo)Graph *in the voice of Nickelback*

* trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* add test

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* fix how expression index is corrected, to make compatible with offset planes

* another test

* tweak test

* more test tweaks

* break up test to fix it hopfully

* fix onboarding test

* remove bad comment

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* get ready to bump (kcl-lib and friends) world (#4794)

get ready to bump world

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

* Revert multi-profile (#4812)

* Revert "multi-profile follow up. (#4802)"

This reverts commit 2b2ed470c1.

* Revert "multi profile (#4532)"

This reverts commit 04e586d07b.

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* Re-run CI after snapshots

* Re-run CI after snapshots

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Re-run CI after snapshots

* Add `fixme` to onboarding test

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Add tracking of operations for the feature tree (#4746)

* Add operations tracking for the timeline

* Change to only track certain stdlib functions as operations

* Update gen files

* Add operations to simulation snapshot tests

* Add tracking of positional function calls

* Fix generated field names to be camel case in TS

* Fix generated TS field names to match and better docs

* Fix order of ops with patternTransform

* Fix sweep to be included

* Add new expected test outputs

* Add tracking for startSketchOn

* Update ops output to include startSketchOn

* Fix serde field name

* Fix output field name

* Add tracking of operations that fail

* Add snapshots of operations even when there's a KCL execution error

* Add ops output for error executions

* Add operations output to executor error

* Update op source ranges

* Remove tracking of circle() and polygon() since they're not needed

* Update output without circle and polygon

* Fix to track patternCircular3d and patternLinear3d

* Remove tracking for mirror2d

* Update ops output

* Fix to track the correct source range of function definitions

---------

Co-authored-by: Frank Noirot <frank@zoo.dev>

* Change KCL completion to use new object/record syntax (#4815)

* Reserve syntax for units of measure (#4783)

* Allow underscores but only for un-referenced names

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Support numeric suffixes for UoM types

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* UoM type arguments

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* warnings -> non-fatal errors

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* type ascription

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Whole module imports (#4767)

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Support completions from import statements (#4768)

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Implements boolean logical and/or in kcl  (#4678)

* redoing bool logic impl on latest main

* adding snapshot tests (removing .new)

* removing accidental change smh:(

* accepting client side scene snapshot

* accepting png snapshot and triggering ci

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* accepting png again?

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* accepting grid visibility snapshot

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* accepting png snapshot

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* accepting png snapshot

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* accepting png snapshot

* rerunning simtest creation to get ops.snap files

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>

* Annotations syntax and per-file default units preparatory work (#4822)

* Parse annotations

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Propagate settings from annotations to exec_state

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* KCL: Unlabeled first param defaults to % (#4817)

Part of #4600

KCL functions can declare one special argument that doesn't require a label on its parameter when called.

This PR will default that arg to % (the current pipeline) if not given.

* Deprecate startSketchAt() stdlib function (#4819)

* Deprecate startSketchAt() stdlib function

* Remove uses of startSketchAt() from the doc tests

* Update docs

* Add dry-run validation for Loft (#4820)

* WIP: mess with shell selection validation
Will eventually fix #4711

* Update from main

* WIP: not working yet

* Working loft dry run validator

* Clean up shell (still not working)

* Bump kittycad-modeling-cmds

* Clean up

* Add logging

* Add proper object_id and face_id mapping, still not working for shell

* Fix faceId

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Add dry-run validation to Loft
Checks one box for #4711

* Add extra check for non solid2ds

---------

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Double click label on sketch to dimension  (#4816)

* feat: double click segment label to dimension length, POC, need to clean up code!

* fix: cleaning up the PR for review

* fix: cleaning for the PR. Adding more comments and moving some logic

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* fix: mergining main, auto linter and tsc fixes. Need to make some more

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* fix: tsc errors are resolved

* chore: added test for constraint

* fix: fixing overlay bug since length labels can now be clicked.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* KCL: Show beautiful Miette errors when a KCL example test fails (#4829)

* KCL: Show beautiful Miette errors when a KCL example test fails

Background: KCL example tests are generated from the stdlib KCL examples in the `#[stdlib]` macro in derive-docs.

Problem: When these tests fail, they output a really unhelpful error message like Kcl(Semantic(KclErrorDetails { source_ranges: [156, 160, 0], message: "Expected a sketch but found array" } )).

Solution: Use miette. Now the errors highlight the KCL code that failed and show exactly what went wrong, on which line, presenting nice diagnostics that look like cargo/rustc output.

* Update helix snapshots

* Move all tests over to electron (#4484)

* Move all tests over to electron

* Pass the correct param to playwright-electron.sh

* Add shebang to script and add macos-14-large as a target

* Get sketch-tests.spec.ts passing in electron

* Try out 4 workers

* Got testing-segment-overlays passing

* Pass testing-selections.spec.ts

* Go back to fix up sketch-tests test

* Pass various.spec.ts, by far the hardest one

* Pass can-sketch-on-all-planes... with ease

* Pass command bar tests

* fmt

* Completely fix code mirror text navigating for tests

* Pass debug pane tests

* Pass desktop export tests

* Pass editor tests

* Pass file tree tests

* Pass onboarding tests

* Corrected a fixme in file-tree.spec!

* Painfully fix hardcoded coordinates in point-click.spec

* Pass machine.spec tests

* Pass projects, fought hard with filechooser

* Pass regresion-tests.spec tests

* Pass network and connection tests

* Pass camera-movement.spec tests

* Extreme time eaten by gizmo test fixes. All passing now.

* Merge main (tests changed x_x) and pass all constraints.spec tests (pain)

* Pass another painful spec suite: testing-settings

* Pass perspective-toggle, interesting note

* Pass samples loading tests

* Pass app header tests

* Pass text-to-cad tests

* Pass segment-overlays (minor ache) and ability to switch to web if needed :)

* Fix a ton of syntax changes and deflake 2 more tests (pain)

* Correct all tsc errors

* Remove to-electron script

* Add an f-ton of shit because playwright doesnt want S P R E A D

* Try CI again

* Stop snapshots of exports (already test in e2e)

* Fix flake in double click editor

* Hopefully help CI flake

* Fixmes, fixmes everywhere

* One more fixme to settings

* Skip another code pane flake

* Port jess's projects.spec tests

* fixup

* Reuse electron window; difficult task

* Rebased and refixed

* Remove duplicate cases

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* Reduce the workers to something CI can handle

* Lower it further, we need to think about the others

* Update package.json

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Update package.json

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Fix the last tests and tsc errors

* Timeout to 120 and windows-2022-16core

* Fix windows runner detection, enable concurrency temporarily

* Hopefully this time fix windows runner detection

* Comment out Vector, add back removed camera test code

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* Fix camera tests again

* Massively deflake a whole class of tests

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* Try new CI and fix small onboarding test

* Derp

* No github tuning

* Try mac

* Add back all the OS

* Lord, hallow be thy name

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* One last try with window-16-cores

* Trigger CI

* Try AWS Windows runner

* Passing on windows locally with a few skips

* Skip more win tests, add back all three oses

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* Add two more fixmes

* 2 more fixmes

* skip segment overlays on win32

* Another fixme

* Trigger CI

* Trigger CI

* Quick clean up

* Move all tests over to electron

* Pass the correct param to playwright-electron.sh

* Add shebang to script and add macos-14-large as a target

* Get sketch-tests.spec.ts passing in electron

* Try out 4 workers

* Got testing-segment-overlays passing

* Pass testing-selections.spec.ts

* Go back to fix up sketch-tests test

* Pass various.spec.ts, by far the hardest one

* Pass can-sketch-on-all-planes... with ease

* Pass command bar tests

* fmt

* Completely fix code mirror text navigating for tests

* Pass debug pane tests

* Pass desktop export tests

* Pass editor tests

* Pass file tree tests

* Pass onboarding tests

* Corrected a fixme in file-tree.spec!

* Painfully fix hardcoded coordinates in point-click.spec

* Pass machine.spec tests

* Pass projects, fought hard with filechooser

* Pass regresion-tests.spec tests

* Pass network and connection tests

* Pass camera-movement.spec tests

* Extreme time eaten by gizmo test fixes. All passing now.

* Merge main (tests changed x_x) and pass all constraints.spec tests (pain)

* Pass another painful spec suite: testing-settings

* Pass perspective-toggle, interesting note

* Pass samples loading tests

* Pass app header tests

* Pass text-to-cad tests

* Pass segment-overlays (minor ache) and ability to switch to web if needed :)

* Fix a ton of syntax changes and deflake 2 more tests (pain)

* Correct all tsc errors

* Remove to-electron script

* Add an f-ton of shit because playwright doesnt want S P R E A D

* Try CI again

* Stop snapshots of exports (already test in e2e)

* Fix flake in double click editor

* Hopefully help CI flake

* Fixmes, fixmes everywhere

* One more fixme to settings

* Skip another code pane flake

* Port jess's projects.spec tests

* fixup

* Reuse electron window; difficult task

* Rebased and refixed

* Remove duplicate cases

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* Reduce the workers to something CI can handle

* Lower it further, we need to think about the others

* Update package.json

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Update package.json

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Fix the last tests and tsc errors

* Timeout to 120 and windows-2022-16core

* Fix windows runner detection, enable concurrency temporarily

* Hopefully this time fix windows runner detection

* Comment out Vector, add back removed camera test code

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* Fix camera tests again

* Massively deflake a whole class of tests

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: macos-14-large)

* Try new CI and fix small onboarding test

* Derp

* No github tuning

* Try mac

* Add back all the OS

* Lord, hallow be thy name

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Try AWS Windows runner

* Passing on windows locally with a few skips

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* fmt, tsc, lint

* Enable two fixmes again

* Fix lint, codespell, fmt

* Fix lint

* Don't run e2e on draft, add back concurrency, clean up

* One last windows skip

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>

* Add blank line to discord bot message (#4814)

* Add blank link to discord bot message

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Implement some basic cache program generation (#4840)

Implement some basic cache program generation

A bit ago, @jessfraz added the ability to control reexecution from the
executor. When we did this, it used the digest to determine if there
was a code change rather than a non-code change (whitespace, comment,
etc).

This allows the creation of a new program to be run without clearing the
scene. This, in conjunction with being able to delete Engine objects by
ID will allow us to do some clever stuff when incrementally executing
a program.

I'm still working on something a bit more advanced, but a good first
step to derisk some of the caching behavior here fully is to implement a
basic "changed program" stub.

This process the ast programs (old and new) if it doesn't exactly match.
This would have been a complete refresh before this commit.

 1) Check all overlapping top-level statements of the body of the new and
    old AST and ensure they all match.
      - If this is true, this means that one of the two AST programs has more
        elements then the other, and they all otherwise match (addition or
        deletion of the end of the program). We continue to #2 in this
        case.
      - If this is false, we have a meaingful difference in a section of
        overlapping code. This will result in a cache miss and rebuild
        the scene. We short-cut here and the scene is rebuilt.

 2) Check the lengths of the two bodies.
   - If they're the same, we shouldn't have even been called. We will
     short-cut with a noop cache return (no clear, no program).
   - if the old ast is longer, we've removed instructions from the
     program. We can't delete things now, so this will result in a cache
     miss and rebuild the scene. We short-cut here and the scene is
     rebuilt.
   - If the new ast is longer, we have an insertion of code at the end.

 3) construct a new program using only the new elements from the new
    ast, and return a `CacheResult` that *does not clear the scene*.
    This means nothing will be rebuilt, and only a new object will polp
    onto the scene. This is the first case where we diverge with
    existing behavior.

Signed-off-by: Paul R. Tagliamonte <paul@zoo.dev>

* Fix mac issue after electron test migration PR (#4842)

Fix mac issue after electron test migration pR

* Remove guards from modeling commands in the toolbar (#4800)

* Remove guards from modeling commands in the toolbar

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Remove the deprecated function, update doc comment for the one still in use

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* Remove more selection check functions that are no longer used

* Update E2E tests that assumed the extrude button could be disabled due to selection

* Update a few fillet tests that expected the button to disable based on selection

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>

* Prompt to edit (#4830)

* initial plumbing for getting the new option into the cmd-bar

* start of prompt edit

* update AI poll

* add spinner

* more prompt engineering

* add success toast, allowing user's to reject code

* select code that changed in prompt to edit

* selection in scene should not disappear when opening prompt cmd

* tweak

* fmt

* add tests

* some clean up

* clean up

* fix tests

* Yeet telemetry to text to cad endpoint (#4847)

yeet telemetry to text to cad endpoint

* Tweak prompt wording (#4846)

tweak prompt wording

* update discord bot (#4837)

* Re-enable test 'code pane closed at start' after electron migration (#4841)

* Re-enable 'code pane closed at start'
Relates to #4838

* Enable test on current branch

* Revert "Enable test on current branch"

This reverts commit 0d970b9ad6.

* Add 3-point circle tool (#4832)

* Add 3-point circle tool

This adds a 1st pass for the 3-point circle tool.

There is disabled code to drag around the 3 points and redraw the circle and
a triangle created by those points. It will be enabled in a follow-up PR
when we have circle3Point in the stdlib.

For now, all it does is after the 3rd click, will insert circle center-radius
KCL code for users to modify.

* PR comments

* First draft of a feature tree pane (#4782)

* Fix e2e default planes tests to use mask on state indicator (#4849)

* Fix e2e default planes tests to use mask on state indicator

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* fix: don't error on failure to fetch privacy settings (#4799)

* fix: dont error on failure to fetch privacy settings

* Add console warning when we ignore it

---------

Co-authored-by: Tom Pridham <pridham.tom@gmail.com>

* Match package license to LICENSE file (#4882)

* Remove the old Loft GitHub issue link in the toolbar (#4848)

Now that it's available, it shouldn't be there anymore.

* Fix fuzz crate lints and update deps (#4873)

* Fix fuzz to use new API

* Fix fuzz Cargo.toml lints and update lock

* Use app foreground color for focus outline button color so there's no hue collision (#4894)

Towards #4851

* Add support for float numbers in rem() arguments (#4858)

* Add support for float numbers in rem() arguments

* Update docs

* Rename to prevent name collision in docs

* Update docs after rename to NumberArg

* Fix parameter types to follow naming convention

* Change doc comment description to not refer to floating point

* Update docs after NumberArg doc change

* Change function to be more condensed

* Change to not try to preserve ints

* Update docs to use f64

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Add auto-retries to macOS build notarization (#4892)

* Add DEBUG=electron-notarize* to build-apps

* Force IS_RELEASE: true

* Temp: Disable version setting based on tag

* Remove deprecated notarize.teamId and add retry logic

* Revert "Remove deprecated notarize.teamId and add retry logic"

This reverts commit 6ff98d784d.

* Retry only on macOS

* Better retry logic for macOS

* Use nick-fields/retry

* Clean up Temp: commits for PR

* Clean up

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* Bump nanoid from 3.3.7 to 3.3.8 (#4731)

Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Enable enter for autocompletions in the command palette KCL input (#4896)

* Enable enter for autocompletions in the command palette KCL input

* Oops I commented out code for the variable name input
Thanks for the catch @pierremtb

---------

Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Bump rollup from 4.21.0 to 4.29.1 (#4888)

* Bump rollup from 4.21.0 to 4.29.1

Bumps [rollup](https://github.com/rollup/rollup) from 4.21.0 to 4.29.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.21.0...v4.29.1)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>

* Louder Windows codesign errors (#4762)

* WIP: Silent failure in signWin.js
Fixes #4582

* Temp: force release build

* Fake throw

* Temp: another test

* Clean up for merge

* Add parsing keyword function calls inside pipelines (#4907)

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>

* Remove draft PR filter on e2e tests (#4908)

* Add three point circle stdlib function (#4893)

* Add parsing keyword function calls inside pipelines

Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>

* Add three point circle stdlib function

* Generate new documentation

* Fix 20:20 for the circle three point test

* Convert to using keyword arguments

* Wtf yo

* Remove unused structure

* Use the new simulation tests

* Regenerate documentation

---------

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>

* Move the base CodeMirror KCL support to a local package (#4897)

* Move CodeMirror LRLanguage to new file

This separates the base language support from the LSP and color picker.

* Move the base CodeMirror KCL support to a local package

* Start CodeMirror grammar tests

* Exclude vitest config in tsconfig

* Add KCL path to tsconfig

* Remove stray import

* Drop extension from import

* Use __filename for commonjs compat

* Check exec return before access

* Build ES and CJS to dist

* Format

* Exclude all.test.ts from codespell

This is to work around "fileTests" imported from Lezer. Future codespell versions look
like they'll allow the code to be annotated, which would be nicer.

---------

Co-authored-by: Matt Mundell <matt@mundell.me>

* Fix typo in README (#3843)

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>

* remove backwards compatibility for snake case in objects (#4920)

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

* CM KCL: Support `=` in record init (#4933)

Support `=` in record init

Co-authored-by: Matt Mundell <matt@mundell.me>

* Bump clap from 4.5.21 to 4.5.23 in /src/wasm-lib (#4928)

Bumps [clap](https://github.com/clap-rs/clap) from 4.5.21 to 4.5.23.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.21...clap_complete-v4.5.23)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump @kittycad/lib from 2.0.7 to 2.0.12 (#4922)

Bumps [@kittycad/lib](https://github.com/KittyCAD/kittycad.ts) from 2.0.7 to 2.0.12.
- [Release notes](https://github.com/KittyCAD/kittycad.ts/releases)
- [Commits](https://github.com/KittyCAD/kittycad.ts/compare/v2.0.7...v2.0.12)

---
updated-dependencies:
- dependency-name: "@kittycad/lib"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump anyhow from 1.0.94 to 1.0.95 in /src/wasm-lib (#4929)

Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.94 to 1.0.95.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.94...1.0.95)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump url from 2.5.3 to 2.5.4 in /src/wasm-lib (#4930)

Bumps [url](https://github.com/servo/rust-url) from 2.5.3 to 2.5.4.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.5.3...v2.5.4)

---
updated-dependencies:
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump wasm-streams from 0.4.1 to 0.4.2 in /src/wasm-lib (#4926)

Bumps [wasm-streams](https://github.com/MattiasBuelens/wasm-streams) from 0.4.1 to 0.4.2.
- [Release notes](https://github.com/MattiasBuelens/wasm-streams/releases)
- [Changelog](https://github.com/MattiasBuelens/wasm-streams/blob/main/CHANGELOG.md)
- [Commits](https://github.com/MattiasBuelens/wasm-streams/compare/v0.4.1...v0.4.2)

---
updated-dependencies:
- dependency-name: wasm-streams
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump @csstools/postcss-oklab-function from 4.0.2 to 4.0.7 (#4923)

Bumps [@csstools/postcss-oklab-function](https://github.com/csstools/postcss-plugins/tree/HEAD/plugins/postcss-oklab-function) from 4.0.2 to 4.0.7.
- [Changelog](https://github.com/csstools/postcss-plugins/blob/main/plugins/postcss-oklab-function/CHANGELOG.md)
- [Commits](https://github.com/csstools/postcss-plugins/commits/HEAD/plugins/postcss-oklab-function)

---
updated-dependencies:
- dependency-name: "@csstools/postcss-oklab-function"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: writes to disk when the user accepts the prompt to edit (#4942)

* fix: writes to disk when the user accepts the prompt to edit

* fix: then catch

* Make circle3Point tool an actor (#4906)

* Reduce the amount of data sent to TS and make new fields opt-in (#4913)

* Reduce the amount of data sent back to JS/TS from WASM

* Remove unneeded derives since we shouldn't expose these types

* Alias type to be clearer

* Bump syn from 2.0.87 to 2.0.95 to be compatible with modeling-cmds 0.… (#4945)

Bump syn from 2.0.87 to 2.0.95 to be compatible with modeling-cmds 0.2.86

* fix out of range error (#4931)

* fix out of range error

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

* updates

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

* remove console logs

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

* add a regression test

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

---------

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

* Run chrome e2e snapshots only on linux (#4947)

* Run chrome e2e snapshots only on linux

* Wtf is this 1-indexed

* Force 1/1 sharding

* Add TODO

* Nadro/3079/screenshot improvements (#3917)

* chore: swapped screenshot to only use the video stream

* feat: video stream screenshot, native electron screenshot

* fix: auto tsc, fmt, xgen, lint

* fix: fixing tsc errors

* fix: removing debug console.log

* fix: renaming ScreenShot to Screenshot

* fix: deleting console log from debugging

* fix: bug with what source was referenced

* fix: using a productName

* fix: improving usage for native screenshots and detecthing support

* fix: fmt

* chore: updated rust test documentation

* fix: typo in readme

* fix: leaving package.json and yarn.lock the same as main??

* bump

* bump

* bump again

* bump again2

* feat: implemented zoom to fit on code change if previous AST was empty (#3925)

* feat: implemented zoom to fit on code change if previous AST was empty

* feat: implementing selectAll text logic to enable select all and copy and paste and zoom to fit will work

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* fix: clarifying comment in _isAstEmpty

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* bump

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* bump again

* fix: fixing new type since this branch is old

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest-8-cores)

* bump

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: 49fl <ircsurfer33@gmail.com>

* Add dependabot group for all serde dependencies (#4944)

* Fix formatting of dependabot.yml

* Add dependabot group for all serde dependencies

* CM KCL: = and => are optional in fn declarations (#4941)

CM KCL: `=` and `=>` are optional in fn declarations

Co-authored-by: Matt Mundell <matt@mundell.me>

* Bump ts-rs from 10.0.0 to 10.1.0 (#4949)

* Add toolbar buttons for text-to-cad and prompt-to-edit (#4938)

* Add toolbar buttons for text-to-cad and prompt-to-edit
Resolves #4890

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-macos-8-cores)

* `preventDefault` on <kbd>Enter</kbd> with textarea input so buttons aren't clicked as well

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-16-cores)

* Trigger CI

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>

* Bump quote from 1.0.37 to 1.0.38 in /src/wasm-lib (#4951)

Bumps [quote](https://github.com/dtolnay/quote) from 1.0.37 to 1.0.38.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.38)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* array pop with unlabled kw arg

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Signed-off-by: Paul R. Tagliamonte <paul@zoo.dev>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Kevin Nadro <nadr0@users.noreply.github.com>
Co-authored-by: 49fl <ircsurfer33@gmail.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
Co-authored-by: Paul Tagliamonte <paul@zoo.dev>
Co-authored-by: Josh Gomez <114548659+jgomez720@users.noreply.github.com>
Co-authored-by: Tom Pridham <pridham.tom@gmail.com>
Co-authored-by: Matt Mundell <32057441+mattmundell@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Matt Mundell <matt@mundell.me>
Co-authored-by: alteous <david@harvey-macaulay.com>
2025-01-07 20:24:24 +00:00
2eb7c382bf Bump @codemirror/lint from 6.8.1 to 6.8.4 (#4955)
Bumps [@codemirror/lint](https://github.com/codemirror/lint) from 6.8.1 to 6.8.4.
- [Changelog](https://github.com/codemirror/lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/lint/compare/6.8.1...6.8.4)

---
updated-dependencies:
- dependency-name: "@codemirror/lint"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 20:23:07 +00:00
38913ecb98 Bump three and @types/three (#4956)
Bumps [three](https://github.com/mrdoob/three.js) and [@types/three](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/three). These dependencies needed to be updated together.

Updates `three` from 0.166.1 to 0.172.0
- [Release notes](https://github.com/mrdoob/three.js/releases)
- [Commits](https://github.com/mrdoob/three.js/commits)

Updates `@types/three` from 0.163.0 to 0.172.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/three)

---
updated-dependencies:
- dependency-name: three
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: "@types/three"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 20:19:58 +00:00
debd06129f CM KCL: numbers must have digits after dot (#4963)
Co-authored-by: Matt Mundell <matt@mundell.me>
2025-01-07 12:19:31 -08:00
d38bd342a0 Bump winnow from 0.6.20 to 0.6.22 in /src/wasm-lib (#4954)
Bumps [winnow](https://github.com/winnow-rs/winnow) from 0.6.20 to 0.6.22.
- [Changelog](https://github.com/winnow-rs/winnow/blob/main/CHANGELOG.md)
- [Commits](https://github.com/winnow-rs/winnow/compare/v0.6.20...v0.6.22)

---
updated-dependencies:
- dependency-name: winnow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 20:16:56 +00:00
f026f10335 Bump zip from 2.2.0 to 2.2.2 in /src/wasm-lib (#4952)
Bumps [zip](https://github.com/zip-rs/zip2) from 2.2.0 to 2.2.2.
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v2.2.0...v2.2.2)

---
updated-dependencies:
- dependency-name: zip
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 18:06:37 +00:00
895d7ebc6d Bump the serde-dependencies group in /src/wasm-lib with 2 updates (#4950)
Bumps the serde-dependencies group in /src/wasm-lib with 2 updates: [serde_json](https://github.com/serde-rs/json) and [serde](https://github.com/serde-rs/serde).


Updates `serde_json` from 1.0.133 to 1.0.135
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.133...v1.0.135)

Updates `serde` from 1.0.216 to 1.0.217
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.216...v1.0.217)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: serde-dependencies
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: serde-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 17:55:33 +00:00
65edf17a44 Bump quote from 1.0.37 to 1.0.38 in /src/wasm-lib (#4951)
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.37 to 1.0.38.
- [Release notes](https://github.com/dtolnay/quote/releases)
- [Commits](https://github.com/dtolnay/quote/compare/1.0.37...1.0.38)

---
updated-dependencies:
- dependency-name: quote
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-07 09:14:32 -08:00
c29be6e341 Everything's pretty much done but url.zoo.dev has been broken and we need to think about how to test reliably 2024-10-19 00:12:58 -04:00
2193d563c5 wip 2024-10-17 19:03:38 -04:00
570d159c29 wip 2024-10-17 18:56:49 -04:00
713886b274 rerun CI 2024-10-17 09:25:44 -07:00
2aa4a01cb7 Merge branch 'franknoirot/4088/decouple-homeMachine' into franknoirot/4088/create-file-url 2024-10-16 18:56:53 -04:00
2048c26b9f Tests always run on localhost, don't expect the prod origin 2024-10-16 15:56:17 -07:00
cbb8df5904 A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) 2024-10-15 20:16:54 +00:00
bb67a9e9cf Merge branch 'franknoirot/4088/decouple-homeMachine' into franknoirot/4088/create-file-url 2024-10-15 13:07:29 -07:00
b84d5951b7 Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-15 13:07:00 -07:00
1e5954e5ed Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-10 20:50:48 -04:00
d58a147b7d Get query-triggered command working in browser too 2024-10-10 18:55:31 -04:00
96b06247a4 Side quest: Only register commands once, power their disabled status while selecting commands via optional actor 2024-10-10 18:54:53 -04:00
36d49b1bcb A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) 2024-10-10 20:23:44 +00:00
4748c2d1e0 Ahhh more flaky toasts, they're everywhere! 2024-10-10 16:19:58 -04:00
698ce671df Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-10 15:48:56 -04:00
a2330a0dbc A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) 2024-10-10 19:38:47 +00:00
c882e34ea9 Merge branch 'franknoirot/4088/decouple-homeMachine' into franknoirot/4088/create-file-url 2024-10-10 15:36:32 -04:00
1ce3d8ccd0 Dumb test error because I was rushing 2024-10-10 15:34:07 -04:00
15bedd56f4 FMT 2024-10-10 15:04:25 -04:00
746ebf80d1 De-flake another text that could be thrown off by toast-based selectors 2024-10-10 14:57:25 -04:00
02b249bd31 Merge branch 'main' into franknoirot/update-download-progress 2024-10-10 12:20:48 -04:00
524fcb03ad Merge branch 'franknoirot/4088/decouple-homeMachine' into franknoirot/4088/create-file-url 2024-10-08 15:32:06 -04:00
3a9e0c72a8 Fix a couple stray tests that still relied on the old way of creating projects 2024-10-08 15:31:49 -04:00
5dc983ad7b Add (broken) event logic and command triggering logic 2024-10-08 14:52:38 -04:00
81411033d7 Forward query params while redirecting to /home or /file 2024-10-08 12:36:48 -04:00
30a24c8ae6 Add menu item to share link to file 2024-10-08 12:32:47 -04:00
403cee5f16 Fix tsc 2024-10-08 10:42:42 -04:00
14eeafb70a Fix lint 2024-10-08 10:38:25 -04:00
f4ecd16ffa Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-08 10:31:13 -04:00
48380be480 A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) 2024-10-08 14:11:34 +00:00
80e32b337f Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-08 10:07:50 -04:00
9378d9862b A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) 2024-10-08 13:27:43 +00:00
1f515b712b A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) 2024-10-08 13:22:12 +00:00
372f2eebcc Add a mask to the state indicator to client-side scale test 2024-10-08 09:18:24 -04:00
e22a9edde8 Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"
This reverts commit 3d2e48732c.
2024-10-08 09:17:45 -04:00
75e3f843eb Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"
This reverts commit 7545b61b49.
2024-10-08 09:17:21 -04:00
f0136a5939 Fix tests that relied on one-click, no-navigation project creation 2024-10-08 09:15:18 -04:00
3d2e48732c A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) 2024-10-07 19:23:02 +00:00
7545b61b49 A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest) 2024-10-07 19:21:28 +00:00
d1be6d7b64 A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest) 2024-10-07 19:18:03 +00:00
8ab24ceee7 @jtran feedback, use the type guard util 2024-10-07 15:13:52 -04:00
f163870b86 Fix tsc 2024-10-07 11:08:36 -04:00
3fc707a2a4 Remove console logs 2024-10-07 11:07:09 -04:00
238163d7db Tests second version: flattened 2024-10-07 11:06:25 -04:00
bfccb79c1c Tests first version: nested loops 2024-10-07 10:56:00 -04:00
fe6d1f8119 Make projects watching code not run in web 2024-10-07 09:13:24 -04:00
f496d94258 Merge branch 'main' into franknoirot/4088/decouple-homeMachine 2024-10-07 09:01:27 -04:00
5d8f3f988a More explicit warning message text 2024-10-04 17:15:54 -04:00
4f06524776 Update "New project" button to use command bar flow
Closes #2585
2024-10-04 17:07:41 -04:00
d7fe827a9e Make it navigate when you create a project 2024-10-04 17:03:23 -04:00
049e487ac4 Show a warning in the command palette for deleting a project 2024-10-04 16:59:09 -04:00
5bd89047b2 Add logic to navigate out from deleted or renamed project 2024-10-04 16:51:06 -04:00
5822321f35 Separate out /home route from projectsMachine 2024-10-04 16:18:16 -04:00
401dcf8152 Rename homeMachine and accessories to projectsMachine 2024-10-04 16:16:09 -04:00
835 changed files with 266557 additions and 72099 deletions

View File

@ -1,3 +1,3 @@
[codespell]
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./src/lib/machine-api.d.ts,./packages/codemirror-lang-kcl/test/all.test.ts
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser
skip: **/target,node_modules,build,dist,./out,**/Cargo.lock,./docs/kcl/*.md,.yarn.lock,**/yarn.lock,./openapi/*.json,./packages/codemirror-lang-kcl/test/all.test.ts,tsconfig.tsbuildinfo

View File

@ -5,16 +5,32 @@
},
"plugins": [
"css-modules",
"jest",
"jsx-a11y",
"react",
"react-hooks",
"suggest-no-throw",
"testing-library",
"@typescript-eslint"
],
"extends": [
"react-app",
"react-app/jest",
"plugin:css-modules/recommended"
"plugin:css-modules/recommended",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended"
],
"rules": {
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "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."
}
],
"semi": [
"error",
"never"
@ -25,6 +41,9 @@
"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",
@ -33,6 +52,9 @@
},
{
"files": ["src/**/*.test.ts"],
"extends": [
"plugin:testing-library/react"
],
"rules": {
"suggest-no-throw/suggest-no-throw": "off",
}

View File

@ -21,7 +21,7 @@ if [[ ! -f "test-results/.last-run.json" ]]; then
fi
retry=1
max_retrys=4
max_retrys=5
# retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues
while [[ $retry -le $max_retrys ]]; do

View File

@ -6,23 +6,29 @@
version: 2
updates:
- package-ecosystem: 'npm' # See documentation for possible values
directory: '/' # Location of package manifests
directories:
- '/'
- '/packages/codemirror-lang-kcl/'
- '/packages/codemirror-lsp-client/'
schedule:
interval: 'weekly'
interval: weekly
day: monday
reviewers:
- franknoirot
- irev-dev
- package-ecosystem: 'github-actions' # See documentation for possible values
directory: '/' # Location of package manifests
schedule:
interval: 'weekly'
interval: weekly
day: monday
reviewers:
- adamchalmers
- jessfraz
- package-ecosystem: 'cargo' # See documentation for possible values
directory: '/src/wasm-lib/' # Location of package manifests
schedule:
interval: 'weekly'
interval: weekly
day: monday
reviewers:
- adamchalmers
- jessfraz
@ -30,3 +36,6 @@ updates:
serde-dependencies:
patterns:
- "serde*"
wasm-bindgen-deps:
patterns:
- "wasm-bindgen*"

View File

@ -27,7 +27,7 @@ jobs:
# Upload the WASM bundle as an artifact
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: wasm-bundle
path: src/wasm-lib/pkg

View File

@ -5,6 +5,7 @@ on:
push:
branches:
- main
- pierremtb/4088/create-file-url
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
schedule:
@ -126,7 +127,13 @@ jobs:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install
- name: yarn install
# Windows is picky sometimes and fails on fetch. Step takes about ~30s
uses: nick-fields/retry@v3.0.0
with:
timeout_minutes: 2
max_attempts: 3
command: yarn install
- run: yarn tronb:vite

View File

@ -1,44 +0,0 @@
on:
push:
branches:
- main
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-bench.yml
pull_request:
paths:
- '**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-bench.yml
workflow_dispatch:
permissions: read-all
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: cargo bench
jobs:
cargo-bench:
name: Benchmark with iai
runs-on: ubuntu-latest-8-cores
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
cargo install cargo-criterion
sudo apt update
sudo apt install -y valgrind
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: Benchmark kcl library
shell: bash
run: |-
cd src/wasm-lib/kcl; cargo bench --all-features -- iai
env:
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN}}

View File

@ -0,0 +1,32 @@
name: CodeMirror Lang KCL
on:
pull_request:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
yarn-unit-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
working-directory: packages/codemirror-lang-kcl
- run: yarn tsc
working-directory: packages/codemirror-lang-kcl
- name: run unit tests
run: yarn test
working-directory: packages/codemirror-lang-kcl

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -48,11 +48,11 @@ layout: manual
* [`getOppositeEdge`](kcl/getOppositeEdge)
* [`getPreviousAdjacentEdge`](kcl/getPreviousAdjacentEdge)
* [`helix`](kcl/helix)
* [`helixRevolutions`](kcl/helixRevolutions)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`import`](kcl/import)
* [`inch`](kcl/inch)
* [`int`](kcl/int)
* [`lastSegX`](kcl/lastSegX)
* [`lastSegY`](kcl/lastSegY)
* [`legAngX`](kcl/legAngX)
@ -81,6 +81,7 @@ layout: manual
* [`pi`](kcl/pi)
* [`polar`](kcl/polar)
* [`polygon`](kcl/polygon)
* [`pop`](kcl/pop)
* [`pow`](kcl/pow)
* [`profileStart`](kcl/profileStart)
* [`profileStartX`](kcl/profileStartX)

View File

@ -4,6 +4,8 @@ excerpt: "Convert a number to an integer."
layout: manual
---
**WARNING:** This function is deprecated.
Convert a number to an integer.
DEPRECATED use floor(), ceil(), or round().

39
docs/kcl/pop.md Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,19 +1,19 @@
---
title: "AxisOrEdgeReference"
excerpt: "Axis or tagged edge."
title: "Axis2dOrEdgeReference"
excerpt: "A 2D axis or tagged edge."
layout: manual
---
Axis or tagged edge.
A 2D axis or tagged edge.
**This schema accepts any of the following:**
Axis and origin.
2D axis and origin.
[`AxisAndOrigin`](/docs/kcl/types/AxisAndOrigin)
[`AxisAndOrigin2d`](/docs/kcl/types/AxisAndOrigin2d)

View File

@ -0,0 +1,42 @@
---
title: "Axis3dOrEdgeReference"
excerpt: "A 3D axis or tagged edge."
layout: manual
---
A 3D axis or tagged edge.
**This schema accepts any of the following:**
3D axis and origin.
[`AxisAndOrigin3d`](/docs/kcl/types/AxisAndOrigin3d)
----
Tagged edge.
[`EdgeReference`](/docs/kcl/types/EdgeReference)
----

View File

@ -1,10 +1,10 @@
---
title: "AxisAndOrigin"
excerpt: "Axis and origin."
title: "AxisAndOrigin2d"
excerpt: "A 2D axis and origin."
layout: manual
---
Axis and origin.
A 2D axis and origin.

View File

@ -0,0 +1,105 @@
---
title: "AxisAndOrigin3d"
excerpt: "A 3D axis and origin."
layout: manual
---
A 3D axis and origin.
**This schema accepts exactly one of the following:**
X-axis.
**enum:** `X`
----
Y-axis.
**enum:** `Y`
----
Z-axis.
**enum:** `Z`
----
Flip the X-axis.
**enum:** `-X`
----
Flip the Y-axis.
**enum:** `-Y`
----
Flip the Z-axis.
**enum:** `-Z`
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `custom` |`object`| | No |
----

28
docs/kcl/types/Face.md Normal file
View File

@ -0,0 +1,28 @@
---
title: "Face"
excerpt: "A face."
layout: manual
---
A face.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `id` |`string`| The id of the face. | No |
| `value` |`string`| The tag of the face. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the faces X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the faces Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A face. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

26
docs/kcl/types/Helix.md Normal file
View File

@ -0,0 +1,26 @@
---
title: "Helix"
excerpt: "A helix."
layout: manual
---
A helix.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `value` |`string`| The id of the helix. | No |
| `revolutions` |`number`| Number of revolutions. | No |
| `angleStart` |`number`| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A helix. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -1,10 +1,10 @@
---
title: "HelixData"
excerpt: "Data for helices."
excerpt: "Data for a helix."
layout: manual
---
Data for helices.
Data for a helix.
**Type:** `object`
@ -19,6 +19,8 @@ Data for helices.
| `revolutions` |`number`| Number of revolutions. | No |
| `angleStart` |`number`| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? The default is `false`. | No |
| `length` |`number`| Length of the helix. If this argument is not provided, the height of the solid is used. | No |
| `length` |`number`| Length of the helix. This is not necessary if the helix is created around an edge. If not given the length of the edge is used. | No |
| `radius` |`number`| Radius of the helix. | No |
| `axis` |[`Axis3dOrEdgeReference`](/docs/kcl/types/Axis3dOrEdgeReference)| Axis to use as mirror. | No |

View File

@ -0,0 +1,24 @@
---
title: "HelixRevolutionsData"
excerpt: "Data for helix revolutions."
layout: manual
---
Data for helix revolutions.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `revolutions` |`number`| Number of revolutions. | No |
| `angleStart` |`number`| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? The default is `false`. | No |
| `length` |`number`| Length of the helix. If this argument is not provided, the height of the solid is used. | No |

View File

@ -0,0 +1,26 @@
---
title: "HelixValue"
excerpt: "A helix."
layout: manual
---
A helix.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `value` |`string`| The id of the helix. | No |
| `revolutions` |`number`| Number of revolutions. | No |
| `angleStart` |`number`| Start angle (in degrees). | No |
| `ccw` |`boolean`| Is the helix rotation counter clockwise? | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A helix. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -168,7 +168,6 @@ Any KCL value.
----
A plane.
**Type:** `object`
@ -181,17 +180,10 @@ A plane.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: [`Plane`](/docs/kcl/types/Plane)| | No |
| `id` |`string`| The id of the plane. | No |
| `value` |[`PlaneType`](/docs/kcl/types/PlaneType)| Any KCL value. | No |
| `origin` |[`Point3d`](/docs/kcl/types/Point3d)| Origin of the plane. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
| `value` |[`Plane`](/docs/kcl/types/Plane)| Any KCL value. | No |
----
A face.
**Type:** `object`
@ -203,14 +195,8 @@ A face.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Face`| | No |
| `id` |`string`| The id of the face. | No |
| `value` |`string`| The tag of the face. | No |
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the faces X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the faces Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
| `type` |enum: [`Face`](/docs/kcl/types/Face)| | No |
| `value` |[`Face`](/docs/kcl/types/Face)| Any KCL value. | No |
----
@ -246,7 +232,6 @@ A face.
----
An solid is a collection of extrude surfaces.
**Type:** `object`
@ -259,14 +244,7 @@ An solid is a collection of extrude surfaces.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: [`Solid`](/docs/kcl/types/Solid)| | No |
| `id` |`string`| The id of the solid. | No |
| `value` |`[` [`ExtrudeSurface`](/docs/kcl/types/ExtrudeSurface) `]`| The extrude surfaces. | No |
| `sketch` |[`Sketch`](/docs/kcl/types/Sketch)| The sketch. | No |
| `height` |`number`| The height of the solid. | No |
| `startCapId` |`string`| The id of the extrusion start cap | No |
| `endCapId` |`string`| The id of the extrusion end cap | No |
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |
| `value` |[`Solid`](/docs/kcl/types/Solid)| Any KCL value. | No |
----
@ -285,6 +263,22 @@ An solid is a collection of extrude surfaces.
| `value` |`[` [`Solid`](/docs/kcl/types/Solid) `]`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: [`Helix`](/docs/kcl/types/Helix)| | No |
| `value` |[`Helix`](/docs/kcl/types/Helix)| Any KCL value. | No |
----
Data for an imported geometry.

View File

@ -16,6 +16,6 @@ Data for a mirror.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `axis` |[`AxisOrEdgeReference`](/docs/kcl/types/AxisOrEdgeReference)| Axis to use as mirror. | No |
| `axis` |[`Axis2dOrEdgeReference`](/docs/kcl/types/Axis2dOrEdgeReference)| Axis to use as mirror. | No |

View File

@ -22,6 +22,7 @@ A plane.
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A plane. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -17,7 +17,7 @@ Data for revolution surfaces.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `angle` |`number` (**maximum:** 360.0) (**minimum:** -360.0)| Angle to revolve (in degrees). Default is 360. | No |
| `axis` |[`AxisOrEdgeReference`](/docs/kcl/types/AxisOrEdgeReference)| Axis of revolution. | No |
| `axis` |[`Axis2dOrEdgeReference`](/docs/kcl/types/Axis2dOrEdgeReference)| Axis of revolution. | No |
| `tolerance` |`number`| Tolerance for the revolve operation. | No |

View File

@ -21,6 +21,7 @@ A sketch is a collection of paths.
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch is a collection of paths. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -30,6 +30,7 @@ A sketch is a collection of paths.
| `on` |[`SketchSurface`](/docs/kcl/types/SketchSurface)| What the sketch is on (can be a plane or a face). | No |
| `start` |[`BasePath`](/docs/kcl/types/BasePath)| The starting path. | No |
| `tags` |`object`| Tag identifiers that have been declared in this sketch. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch or a group of sketches. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -31,6 +31,7 @@ A plane.
| `xAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes X axis be? | No |
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the planes Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch type. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |
@ -54,6 +55,7 @@ A face.
| `yAxis` |[`Point3d`](/docs/kcl/types/Point3d)| What should the faces Y axis be? | No |
| `zAxis` |[`Point3d`](/docs/kcl/types/Point3d)| The z-axis (normal). | No |
| `solid` |[`Solid`](/docs/kcl/types/Solid)| The solid the face is on. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A sketch type. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| | No |

View File

@ -23,6 +23,7 @@ An solid is a collection of extrude surfaces.
| `startCapId` |`string`| The id of the extrusion start cap | No |
| `endCapId` |`string`| The id of the extrusion end cap | No |
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| An solid is a collection of extrude surfaces. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -32,6 +32,7 @@ An solid is a collection of extrude surfaces.
| `startCapId` |`string`| The id of the extrusion start cap | No |
| `endCapId` |`string`| The id of the extrusion end cap | No |
| `edgeCuts` |`[` [`EdgeCut`](/docs/kcl/types/EdgeCut) `]`| Chamfers or fillets on this solid. | No |
| `units` |[`UnitLen`](/docs/kcl/types/UnitLen)| A solid or a group of solids. | No |
| `__meta` |`[` [`Metadata`](/docs/kcl/types/Metadata) `]`| Metadata. | No |

View File

@ -16,7 +16,7 @@ Data for a sweep.
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `path` |[`Sketch`](/docs/kcl/types/Sketch)| The path to sweep along. | No |
| `path` |[`SweepPath`](/docs/kcl/types/SweepPath)| The path to sweep along. | No |
| `sectional` |`boolean`| If true, the sweep will be broken up into sub-sweeps (extrusions, revolves, sweeps) based on the trajectory path components. | No |
| `tolerance` |`number`| Tolerance for the sweep operation. | No |

View File

@ -0,0 +1,42 @@
---
title: "SweepPath"
excerpt: "A path to sweep along."
layout: manual
---
A path to sweep along.
**This schema accepts any of the following:**
A path to sweep along.
[`Sketch`](/docs/kcl/types/Sketch)
----
A path to sweep along.
[`Helix`](/docs/kcl/types/Helix)
----

107
docs/kcl/types/UnitLen.md Normal file
View File

@ -0,0 +1,107 @@
---
title: "UnitLen"
excerpt: ""
layout: manual
---
**This schema accepts exactly one of the following:**
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Mm`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Cm`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `M`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Inches`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Feet`| | No |
----
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `type` |enum: `Yards`| | No |
----

View File

@ -280,7 +280,7 @@ test(
await expect(page.getByRole('link', { name: 'bracket' })).toBeVisible()
await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
await expect(page.getByText('Create project')).toBeVisible()
})
await test.step('Opening the router-template project should load', async () => {

View File

@ -1,7 +1,8 @@
import { test, expect } from './zoo-test'
import { getUtils } from './test-utils'
import * as fsp from 'fs/promises'
import { executorInputPath, getUtils } from './test-utils'
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import path from 'path'
test.describe('Command bar tests', () => {
test('Extrude from command bar selects extrude line after', async ({
@ -45,46 +46,6 @@ test.describe('Command bar tests', () => {
)
})
// TODO: fix this test after the electron migration
test.fixme('Fillet from command bar', async ({ page, homePage }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XY')
|> startProfileAt([-5, -5], %)
|> line([0, 10], %)
|> line([10, 0], %)
|> line([0, -10], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
extrude001 = extrude(-10, sketch001)`
)
})
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
const selectSegment = () => page.getByText(`line([0, -10], %)`).click()
await selectSegment()
await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Fillet' }).click()
await page.waitForTimeout(100)
await page.keyboard.press('Enter') // skip selection
await page.waitForTimeout(100)
await page.keyboard.press('Enter') // accept default radius
await page.waitForTimeout(100)
await page.keyboard.press('Enter') // submit
await page.waitForTimeout(100)
await expect(page.locator('.cm-activeLine')).toContainText(
`fillet({ radius = ${KCL_DEFAULT_LENGTH}, tags = [seg01] }, %)`
)
})
test('Command bar can change a setting, and switch back and forth between arguments', async ({
page,
homePage,
@ -345,4 +306,132 @@ test.describe('Command bar tests', () => {
await arcToolCommand.click()
await expect(arcToolButton).toHaveAttribute('aria-pressed', 'true')
})
test(`Reacts to query param to open "import from URL" command`, async ({
page,
cmdBar,
editor,
homePage,
}) => {
await test.step(`Prepare and navigate to home page with query params`, async () => {
const targetURL = `?create-file&name=test&units=mm&code=ZXh0cnVzaW9uRGlzdGFuY2UgPSAxMg%3D%3D&ask-open-desktop`
await homePage.expectState({
projectCards: [],
sortBy: 'last-modified-desc',
})
await page.goto(page.url() + targetURL)
expect(page.url()).toContain(targetURL)
})
await test.step(`Submit the command`, async () => {
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Import file from URL',
currentArgKey: 'method',
currentArgValue: '',
headerArguments: {
Method: '',
Name: 'test',
Code: '1 line',
},
highlightedHeaderArg: 'method',
})
await cmdBar.selectOption({ name: 'New Project' }).click()
await cmdBar.expectState({
stage: 'review',
commandName: 'Import file from URL',
headerArguments: {
Method: 'New project',
Name: 'test',
Code: '1 line',
},
})
await cmdBar.progressCmdBar()
})
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
await editor.expectEditor.toContain('extrusionDistance = 12')
})
})
test(`"import from URL" can add to existing project`, async ({
page,
cmdBar,
editor,
homePage,
toolbar,
context,
}) => {
await context.folderSetupFn(async (dir) => {
const testProjectDir = path.join(dir, 'testProjectDir')
await Promise.all([fsp.mkdir(testProjectDir, { recursive: true })])
await Promise.all([
fsp.copyFile(
executorInputPath('cylinder.kcl'),
path.join(testProjectDir, 'main.kcl')
),
])
})
await test.step(`Prepare and navigate to home page with query params`, async () => {
const targetURL = `?create-file&name=test&units=mm&code=ZXh0cnVzaW9uRGlzdGFuY2UgPSAxMg%3D%3D&ask-open-desktop`
await homePage.expectState({
projectCards: [
{
fileCount: 1,
title: 'testProjectDir',
},
],
sortBy: 'last-modified-desc',
})
await page.goto(page.url() + targetURL)
expect(page.url()).toContain(targetURL)
})
await test.step(`Submit the command`, async () => {
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Import file from URL',
currentArgKey: 'method',
currentArgValue: '',
headerArguments: {
Method: '',
Name: 'test',
Code: '1 line',
},
highlightedHeaderArg: 'method',
})
await cmdBar.selectOption({ name: 'Existing Project' }).click()
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Import file from URL',
currentArgKey: 'projectName',
currentArgValue: '',
headerArguments: {
Method: 'Existing project',
Name: 'test',
ProjectName: '',
Code: '1 line',
},
highlightedHeaderArg: 'projectName',
})
await cmdBar.selectOption({ name: 'testProjectDir' }).click()
await cmdBar.expectState({
stage: 'review',
commandName: 'Import file from URL',
headerArguments: {
Method: 'Existing project',
ProjectName: 'testProjectDir',
Name: 'test',
Code: '1 line',
},
})
await cmdBar.progressCmdBar()
})
await test.step(`Ensure we created the project and are in the modeling scene`, async () => {
await editor.expectEditor.toContain('extrusionDistance = 12')
await toolbar.openPane('files')
await toolbar.expectFileTreeState(['main.kcl', 'test.kcl'])
})
})
})

View File

@ -135,4 +135,27 @@ export class CmdBarFixture {
await promptEditCommand.first().click()
}
}
get cmdSearchInput() {
return this.page.getByTestId('cmd-bar-search')
}
get argumentInput() {
return this.page.getByTestId('cmd-bar-arg-value')
}
get cmdOptions() {
return this.page.getByTestId('cmd-bar-option')
}
chooseCommand = async (commandName: string) => {
await this.cmdOptions.getByText(commandName).click()
}
/**
* Select an option from the command bar
*/
selectOption = (options: Parameters<typeof this.page.getByRole>[1]) => {
return this.page.getByRole('option', options)
}
}

View File

@ -121,18 +121,23 @@ export class AuthenticatedTronApp {
export const fixtures = {
cmdBar: async ({ page }: { page: Page }, use: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
await use(new CmdBarFixture(page))
},
editor: async ({ page }: { page: Page }, use: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
await use(new EditorFixture(page))
},
toolbar: async ({ page }: { page: Page }, use: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
await use(new ToolbarFixture(page))
},
scene: async ({ page }: { page: Page }, use: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
await use(new SceneFixture(page))
},
homePage: async ({ page }: { page: Page }, use: any) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
await use(new HomePageFixture(page))
},
}

View File

@ -103,7 +103,7 @@ export class HomePageFixture {
.toEqual(expectedState)
}
createAndGoToProject = async (projectTitle: string) => {
createAndGoToProject = async (projectTitle = 'project-$nnn') => {
await expect(this.projectSection).not.toHaveText('Loading your Projects...')
await this.projectButtonNew.click()
await this.projectTextName.click()

View File

@ -36,7 +36,8 @@ type DragFromHandler = (
export class SceneFixture {
public page: Page
public streamWrapper!: Locator
public loadingIndicator!: Locator
private exeIndicator!: Locator
constructor(page: Page) {
@ -64,6 +65,8 @@ export class SceneFixture {
this.page = page
this.exeIndicator = page.getByTestId('model-state-indicator-execution-done')
this.streamWrapper = page.getByTestId('stream')
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
}
makeMouseHelpers = (

View File

@ -14,6 +14,9 @@ export class ToolbarFixture {
extrudeButton!: Locator
loftButton!: Locator
sweepButton!: Locator
filletButton!: Locator
chamferButton!: Locator
shellButton!: Locator
offsetPlaneButton!: Locator
startSketchBtn!: Locator
@ -40,6 +43,9 @@ export class ToolbarFixture {
this.page = page
this.extrudeButton = page.getByTestId('extrude')
this.loftButton = page.getByTestId('loft')
this.sweepButton = page.getByTestId('sweep')
this.filletButton = page.getByTestId('fillet3d')
this.chamferButton = page.getByTestId('chamfer3d')
this.shellButton = page.getByTestId('shell')
this.offsetPlaneButton = page.getByTestId('plane-offset')
this.startSketchBtn = page.getByTestId('sketch')
@ -57,6 +63,10 @@ export class ToolbarFixture {
this.exeIndicator = page.getByTestId('model-state-indicator-execution-done')
}
get logoLink() {
return this.page.getByTestId('app-logo')
}
startSketchPlaneSelection = async () =>
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)

View File

@ -756,6 +756,17 @@ test(`Offset plane point-and-click`, async ({
})
await scene.expectPixelColor([74, 74, 74], testPoint, 15)
})
await test.step('Delete offset plane via feature tree selection', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation(
'Offset Plane',
0
)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await scene.expectPixelColor([50, 51, 96], testPoint, 15)
})
})
const loftPointAndClickCases = [
@ -818,12 +829,6 @@ loftPointAndClickCases.forEach(({ shouldPreselect }) => {
})
await selectSketches()
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: { Selection: '2 faces' },
commandName: 'Loft',
})
await cmdBar.progressCmdBar()
})
} else {
await test.step(`Preselect the two sketches`, async () => {
@ -833,12 +838,6 @@ loftPointAndClickCases.forEach(({ shouldPreselect }) => {
await test.step(`Go through the command bar flow with preselected sketches`, async () => {
await toolbar.loftButton.click()
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: { Selection: '2 faces' },
commandName: 'Loft',
})
await cmdBar.progressCmdBar()
})
}
@ -851,6 +850,603 @@ loftPointAndClickCases.forEach(({ shouldPreselect }) => {
})
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
})
await test.step('Delete loft via feature tree selection', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Loft', 0)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
})
})
})
// TODO: merge with above test. Right now we're not able to delete a loft
// right after creation via selection for some reason, so we go with a new instance
test('Loft and offset plane deletion via selection', async ({
context,
page,
homePage,
scene,
}) => {
const initialCode = `sketch001 = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 30 }, %)
plane001 = offsetPlane('XZ', 50)
sketch002 = startSketchOn(plane001)
|> circle({ center = [0, 0], radius = 20 }, %)
loft001 = loft([sketch001, sketch002])
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const [clickOnSketch2] = scene.makeMouseHelpers(testPoint.x, testPoint.y + 80)
await test.step(`Delete loft`, async () => {
// Check for loft
await scene.expectPixelColor([89, 89, 89], testPoint, 15)
await clickOnSketch1()
await expect(page.locator('.cm-activeLine')).toHaveText(`
|> circle({ center = [0, 0], radius = 30 }, %)
`)
await page.keyboard.press('Backspace')
// Check for sketch 1
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
})
await test.step('Delete sketch002', async () => {
await page.waitForTimeout(1000)
await clickOnSketch2()
await expect(page.locator('.cm-activeLine')).toHaveText(`
|> circle({ center = [0, 0], radius = 20 }, %)
`)
await page.keyboard.press('Backspace')
// Check for plane001
await scene.expectPixelColor([228, 228, 228], testPoint, 15)
})
await test.step('Delete plane001', async () => {
await page.waitForTimeout(1000)
await clickOnSketch2()
await expect(page.locator('.cm-activeLine')).toHaveText(`
plane001 = offsetPlane('XZ', 50)
`)
await page.keyboard.press('Backspace')
// Check for sketch 1
await scene.expectPixelColor([254, 254, 254], testPoint, 15)
})
})
test(`Sweep point-and-click`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn('YZ')
|> circle({
center = [0, 0],
radius = 500
}, %)
sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> xLine(-500, %)
|> tangentialArcTo([-2000, 500], %)
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
// One dumb hardcoded screen pixel value
const testPoint = { x: 700, y: 250 }
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const [clickOnSketch2] = scene.makeMouseHelpers(testPoint.x - 50, testPoint.y)
const sweepDeclaration = 'sweep001 = sweep({ path = sketch002 }, sketch001)'
await test.step(`Look for sketch001`, async () => {
await toolbar.closePane('code')
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
})
await test.step(`Go through the command bar flow`, async () => {
await toolbar.sweepButton.click()
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'profile',
currentArgValue: '',
headerArguments: {
Path: '',
Profile: '',
},
highlightedHeaderArg: 'profile',
stage: 'arguments',
})
await clickOnSketch1()
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'path',
currentArgValue: '',
headerArguments: {
Path: '',
Profile: '1 face',
},
highlightedHeaderArg: 'path',
stage: 'arguments',
})
await clickOnSketch2()
await cmdBar.expectState({
commandName: 'Sweep',
headerArguments: {
Path: '1 face',
Profile: '1 face',
},
stage: 'review',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
await scene.expectPixelColor([135, 64, 73], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(sweepDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: [sweepDeclaration],
highlightedCode: '',
})
await toolbar.closePane('code')
})
await test.step('Delete sweep via feature tree selection', async () => {
await toolbar.openPane('feature-tree')
await page.waitForTimeout(500)
const operationButton = await toolbar.getFeatureTreeOperation('Sweep', 0)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await page.waitForTimeout(500)
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
})
})
test(`Fillet point-and-click`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn('XY')
|> startProfileAt([-12, -6], %)
|> line([0, 12], %)
|> line([24, 0], %)
|> line([0, -12], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
extrude001 = extrude(-12, sketch001)
`
const firstFilletDeclaration = 'fillet({ radius = 5, tags = [seg01] }, %)'
const secondFilletDeclaration =
'fillet({ radius = 5, tags = [getOppositeEdge(seg01)] }, %)'
// Locators
const firstEdgeLocation = { x: 600, y: 193 }
const secondEdgeLocation = { x: 600, y: 383 }
const bodyLocation = { x: 630, y: 290 }
const [clickOnFirstEdge] = scene.makeMouseHelpers(
firstEdgeLocation.x,
firstEdgeLocation.y
)
const [clickOnSecondEdge] = scene.makeMouseHelpers(
secondEdgeLocation.x,
secondEdgeLocation.y
)
// Colors
const edgeColorWhite: [number, number, number] = [248, 248, 248]
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
const bodyColor: [number, number, number] = [155, 155, 155]
const filletColor: [number, number, number] = [127, 127, 127]
const backgroundColor: [number, number, number] = [30, 30, 30]
const lowTolerance = 20
const highTolerance = 40
// Setup
await test.step(`Initial test setup`, async () => {
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
// verify modeling scene is loaded
await scene.expectPixelColor(
backgroundColor,
secondEdgeLocation,
lowTolerance
)
// wait for stream to load
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
})
// Test 1: Command bar flow with preselected edges
await test.step(`Select first edge`, async () => {
await scene.expectPixelColor(
edgeColorWhite,
firstEdgeLocation,
lowTolerance
)
await clickOnFirstEdge()
await scene.expectPixelColor(
edgeColorYellow,
firstEdgeLocation,
highTolerance // Ubuntu color mismatch can require high tolerance
)
})
await test.step(`Apply fillet to the preselected edge`, async () => {
await page.waitForTimeout(100)
await toolbar.filletButton.click()
await cmdBar.expectState({
commandName: 'Fillet',
highlightedHeaderArg: 'selection',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Radius: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Fillet',
highlightedHeaderArg: 'radius',
currentArgKey: 'radius',
currentArgValue: '5',
headerArguments: {
Selection: '1 face',
Radius: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Fillet',
headerArguments: {
Selection: '1 face',
Radius: '5',
},
stage: 'review',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor`, async () => {
await editor.expectEditor.toContain(firstFilletDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: ['|>fillet({radius=5,tags=[seg01]},%)'],
highlightedCode: '',
})
})
await test.step(`Confirm scene has changed`, async () => {
await scene.expectPixelColor(filletColor, firstEdgeLocation, lowTolerance)
})
// Test 2: Command bar flow without preselected edges
await test.step(`Open fillet UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.filletButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Radius: '',
},
highlightedHeaderArg: 'selection',
commandName: 'Fillet',
})
})
await test.step(`Select second edge`, async () => {
await scene.expectPixelColor(
edgeColorWhite,
secondEdgeLocation,
lowTolerance
)
await clickOnSecondEdge()
await scene.expectPixelColor(
edgeColorYellow,
secondEdgeLocation,
highTolerance // Ubuntu color mismatch can require high tolerance
)
})
await test.step(`Apply fillet to the second edge`, async () => {
await cmdBar.expectState({
commandName: 'Fillet',
highlightedHeaderArg: 'selection',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Radius: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Fillet',
highlightedHeaderArg: 'radius',
currentArgKey: 'radius',
currentArgValue: '5',
headerArguments: {
Selection: '1 sweepEdge',
Radius: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Fillet',
headerArguments: {
Selection: '1 sweepEdge',
Radius: '5',
},
stage: 'review',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor`, async () => {
await editor.expectEditor.toContain(secondFilletDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: ['radius=5,'],
highlightedCode: '',
})
})
await test.step(`Confirm scene has changed`, async () => {
await scene.expectPixelColor(
backgroundColor,
secondEdgeLocation,
lowTolerance
)
})
})
test(`Chamfer point-and-click`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
// Code samples
const initialCode = `sketch001 = startSketchOn('XY')
|> startProfileAt([-12, -6], %)
|> line([0, 12], %)
|> line([24, 0], %)
|> line([0, -12], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)
extrude001 = extrude(-12, sketch001)
`
const firstChamferDeclaration = 'chamfer({ length = 5, tags = [seg01] }, %)'
const secondChamferDeclaration =
'chamfer({ length = 5, tags = [getOppositeEdge(seg01)] }, %)'
// Locators
const firstEdgeLocation = { x: 600, y: 193 }
const secondEdgeLocation = { x: 600, y: 383 }
const bodyLocation = { x: 630, y: 290 }
const [clickOnFirstEdge] = scene.makeMouseHelpers(
firstEdgeLocation.x,
firstEdgeLocation.y
)
const [clickOnSecondEdge] = scene.makeMouseHelpers(
secondEdgeLocation.x,
secondEdgeLocation.y
)
// Colors
const edgeColorWhite: [number, number, number] = [248, 248, 248]
const edgeColorYellow: [number, number, number] = [251, 251, 40] // Mac:B=67 Ubuntu:B=12
const bodyColor: [number, number, number] = [155, 155, 155]
const chamferColor: [number, number, number] = [168, 168, 168]
const backgroundColor: [number, number, number] = [30, 30, 30]
const lowTolerance = 20
const highTolerance = 40
// Setup
await test.step(`Initial test setup`, async () => {
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
// verify modeling scene is loaded
await scene.expectPixelColor(
backgroundColor,
secondEdgeLocation,
lowTolerance
)
// wait for stream to load
await scene.expectPixelColor(bodyColor, bodyLocation, highTolerance)
})
// Test 1: Command bar flow with preselected edges
await test.step(`Select first edge`, async () => {
await scene.expectPixelColor(
edgeColorWhite,
firstEdgeLocation,
lowTolerance
)
await clickOnFirstEdge()
await scene.expectPixelColor(
edgeColorYellow,
firstEdgeLocation,
highTolerance // Ubuntu color mismatch can require high tolerance
)
})
await test.step(`Apply chamfer to the preselected edge`, async () => {
await page.waitForTimeout(100)
await toolbar.chamferButton.click()
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'selection',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Length: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'length',
currentArgKey: 'length',
currentArgValue: '5',
headerArguments: {
Selection: '1 face',
Length: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Chamfer',
headerArguments: {
Selection: '1 face',
Length: '5',
},
stage: 'review',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor`, async () => {
await editor.expectEditor.toContain(firstChamferDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: ['|>chamfer({length=5,tags=[seg01]},%)'],
highlightedCode: '',
})
})
await test.step(`Confirm scene has changed`, async () => {
await scene.expectPixelColor(chamferColor, firstEdgeLocation, lowTolerance)
})
// Test 2: Command bar flow without preselected edges
await test.step(`Open chamfer UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.chamferButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Length: '',
},
highlightedHeaderArg: 'selection',
commandName: 'Chamfer',
})
})
await test.step(`Select second edge`, async () => {
await scene.expectPixelColor(
edgeColorWhite,
secondEdgeLocation,
lowTolerance
)
await clickOnSecondEdge()
await scene.expectPixelColor(
edgeColorYellow,
secondEdgeLocation,
highTolerance // Ubuntu color mismatch can require high tolerance
)
})
await test.step(`Apply chamfer to the second edge`, async () => {
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'selection',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Length: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'length',
currentArgKey: 'length',
currentArgValue: '5',
headerArguments: {
Selection: '1 sweepEdge',
Length: '',
},
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await cmdBar.expectState({
commandName: 'Chamfer',
headerArguments: {
Selection: '1 sweepEdge',
Length: '5',
},
stage: 'review',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor`, async () => {
await editor.expectEditor.toContain(secondChamferDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: ['length=5,'],
highlightedCode: '',
})
})
await test.step(`Confirm scene has changed`, async () => {
await scene.expectPixelColor(
backgroundColor,
secondEdgeLocation,
lowTolerance
)
})
})
@ -907,6 +1503,7 @@ shellPointAndClickCapCases.forEach(({ shouldPreselect }) => {
await clickOnCap()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
@ -927,6 +1524,7 @@ shellPointAndClickCapCases.forEach(({ shouldPreselect }) => {
await test.step(`Go through the command bar flow with a preselected face (cap)`, async () => {
await toolbar.shellButton.click()
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
@ -1008,6 +1606,7 @@ extrude001 = extrude(40, sketch001)
await page.waitForTimeout(500)
await page.keyboard.up('Shift')
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
@ -1030,4 +1629,162 @@ extrude001 = extrude(40, sketch001)
})
await scene.expectPixelColor([49, 49, 49], testPoint, 15)
})
await test.step('Delete shell via feature tree selection', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
await operationButton.click({ button: 'left' })
await page.keyboard.press('Backspace')
await scene.expectPixelColor([99, 99, 99], testPoint, 15)
})
})
const shellSketchOnFacesCases = [
`sketch001 = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 100 }, %)
|> extrude(100, %)
sketch002 = startSketchOn(sketch001, 'END')
|> circle({ center = [0, 0], radius = 50 }, %)
|> extrude(50, %)
`,
`sketch001 = startSketchOn('XZ')
|> circle({ center = [0, 0], radius = 100 }, %)
extrude001 = extrude(100, sketch001)
sketch002 = startSketchOn(extrude001, 'END')
|> circle({ center = [0, 0], radius = 50 }, %)
extrude002 = extrude(50, sketch002)
`,
]
shellSketchOnFacesCases.forEach((initialCode, index) => {
const hasExtrudesInPipe = index === 0
test(`Shell point-and-click sketch on face (extrudes in pipes: ${hasExtrudesInPipe})`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
// One dumb hardcoded screen pixel value
const testPoint = { x: 550, y: 295 }
const [clickOnCap] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
const shellDeclaration = `shell001 = shell({ faces = ['end'], thickness = 5 }, ${
hasExtrudesInPipe ? 'sketch002' : 'extrude002'
})`
await test.step(`Look for the grey of the shape`, async () => {
await toolbar.closePane('code')
await scene.expectPixelColor([128, 128, 128], testPoint, 15)
})
await test.step(`Go through the command bar flow, selecting a cap and keeping default thickness`, async () => {
await toolbar.shellButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Thickness: '',
},
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await clickOnCap()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
Selection: '1 cap',
Thickness: '5',
},
commandName: 'Shell',
})
await cmdBar.progressCmdBar()
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
await toolbar.openPane('code')
await editor.expectEditor.toContain(shellDeclaration)
await editor.expectState({
diagnostics: [],
activeLines: [shellDeclaration],
highlightedCode: '',
})
await toolbar.closePane('code')
await scene.expectPixelColor([73, 73, 73], testPoint, 15)
})
})
})
test(`Shell dry-run validation rejects sweeps`, async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn('YZ')
|> circle({
center = [0, 0],
radius = 500
}, %)
sketch002 = startSketchOn('XZ')
|> startProfileAt([0, 0], %)
|> xLine(-2000, %)
sweep001 = sweep({ path = sketch002 }, sketch001)
`
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
// One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 }
const [clickOnSweep] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
await test.step(`Confirm sweep exists`, async () => {
await toolbar.closePane('code')
await scene.expectPixelColor([231, 231, 231], testPoint, 15)
})
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
await toolbar.shellButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
currentArgValue: '',
headerArguments: {
Selection: '',
Thickness: '',
},
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await clickOnSweep()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await expect(
page.getByText('Unable to shell with the provided selection')
).toBeVisible()
await page.waitForTimeout(1000)
})
})

View File

@ -115,7 +115,7 @@ test(
)
test(
'yyyyyyyyy open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
'open a file in a project works and renders, open another file in different project with errors, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
@ -172,7 +172,7 @@ test(
await expect(page.getByRole('link', { name: 'bracket' })).toBeVisible()
await expect(page.getByText('broken-code')).toBeVisible()
await expect(page.getByText('bracket')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
await expect(page.getByText('Create project')).toBeVisible()
})
await test.step('opening broken code project should clear the scene and show the error', async () => {
// Go back home.
@ -199,7 +199,7 @@ test(
)
test(
'aaayyyyyyyy open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
'open a file in a project works and renders, open another file in different project that is empty, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
@ -253,7 +253,7 @@ test(
await expect(page.getByRole('link', { name: 'bracket' })).toBeVisible()
await expect(page.getByText('empty')).toBeVisible()
await expect(page.getByText('bracket')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
await expect(page.getByText('Create project')).toBeVisible()
})
await test.step('opening empty code project should clear the scene', async () => {
// Go back home.
@ -276,7 +276,7 @@ test(
)
test(
'nooooooooooooo open a file in a project works and renders, open empty file, it should clear the scene',
'open a file in a project works and renders, open empty file, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
@ -985,6 +985,126 @@ test.describe(`Project management commands`, () => {
})
}
)
test(`Create a new project with a colliding name`, async ({
context,
homePage,
toolbar,
cmdBar,
}) => {
const projectName = 'test-project'
await test.step(`Setup`, async () => {
await context.folderSetupFn(async (dir) => {
const projectDir = path.join(dir, projectName)
await Promise.all([fsp.mkdir(projectDir, { recursive: true })])
await Promise.all([
fsp.copyFile(
executorInputPath('router-template-slate.kcl'),
path.join(projectDir, 'main.kcl')
),
])
})
await homePage.expectState({
projectCards: [
{
title: projectName,
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
})
await test.step('Create a new project with the same name', async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('create project')
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Create project',
currentArgKey: 'name',
currentArgValue: '',
headerArguments: {
Name: '',
},
highlightedHeaderArg: 'name',
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
})
await test.step(`Check the project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
title: projectName + '-1',
fileCount: 1,
},
{
title: projectName,
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
})
await test.step('Create another project with the same name', async () => {
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('create project')
await cmdBar.expectState({
stage: 'arguments',
commandName: 'Create project',
currentArgKey: 'name',
currentArgValue: '',
headerArguments: {
Name: '',
},
highlightedHeaderArg: 'name',
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
})
await test.step(`Check the second project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
title: projectName + '-2',
fileCount: 1,
},
{
title: projectName + '-1',
fileCount: 1,
},
{
title: projectName,
fileCount: 1,
},
],
sortBy: 'last-modified-desc',
})
})
})
})
test(`Create a few projects using the default project name`, async ({
homePage,
toolbar,
}) => {
for (let i = 0; i < 12; i++) {
await test.step(`Create project ${i}`, async () => {
await homePage.expectState({
projectCards: Array.from({ length: i }, (_, i) => ({
title: `project-${i.toString().padStart(3, '0')}`,
fileCount: 1,
})).toReversed(),
sortBy: 'last-modified-desc',
})
await homePage.createAndGoToProject()
await toolbar.logoLink.click()
})
}
})
test(
@ -1391,7 +1511,7 @@ extrude001 = extrude(200, sketch001)`)
await page.getByTestId('app-logo').click()
await expect(
page.getByRole('button', { name: 'New project' })
page.getByRole('button', { name: 'Create project' })
).toBeVisible()
for (let i = 1; i <= 10; i++) {
@ -1465,7 +1585,7 @@ test(
await expect(page.getByRole('link', { name: 'bracket' })).toBeVisible()
await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
await expect(page.getByText('Create project')).toBeVisible()
})
await test.step('Opening the router-template project should load the stream', async () => {
@ -1494,7 +1614,7 @@ test(
await expect(page.getByRole('link', { name: 'bracket' })).toBeVisible()
await expect(page.getByText('router-template-slate')).toBeVisible()
await expect(page.getByText('New Project')).toBeVisible()
await expect(page.getByText('Create project')).toBeVisible()
})
}
)
@ -1885,3 +2005,48 @@ test.fixme(
})
}
)
test(
'project name with foreign characters should open',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'اَلْعَرَبِيَّةُ')
await fsp.mkdir(bracketDir, { recursive: true })
await fsp.copyFile(
executorInputPath('focusrite_scarlett_mounting_braket.kcl'),
path.join(bracketDir, 'main.kcl')
)
await fsp.writeFile(path.join(bracketDir, 'empty.kcl'), '')
})
await page.setBodyDimensions({ width: 1200, height: 500 })
const u = await getUtils(page)
page.on('console', console.log)
const pointOnModel = { x: 630, y: 280 }
await test.step('Opening the اَلْعَرَبِيَّةُ project should load the stream', async () => {
// expect to see the text bracket
await expect(page.getByText('اَلْعَرَبِيَّةُ')).toBeVisible()
await page.getByText('اَلْعَرَبِيَّةُ').click()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeEnabled({
timeout: 20_000,
})
// gray at this pixel means the stream has loaded in the most
// user way we can verify it (pixel color)
await expect
.poll(() => u.getGreatestPixDiff(pointOnModel, [85, 85, 85]), {
timeout: 10_000,
})
.toBeLessThan(15)
})
}
)

View File

@ -614,6 +614,38 @@ extrude001 = extrude(50, sketch001)
await expect(gizmo).toBeVisible()
})
})
test(`Refreshing the app doesn't cause the stream to pause on long-executing files`, async ({
context,
homePage,
scene,
toolbar,
viewport,
}) => {
await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego')
await fsp.mkdir(legoDir, { recursive: true })
await fsp.copyFile(
executorInputPath('lego.kcl'),
path.join(legoDir, 'main.kcl')
)
})
await test.step(`Test setup`, async () => {
await homePage.openProject('lego')
await toolbar.closePane('code')
})
await test.step(`Waiting for the loading spinner to disappear`, async () => {
await scene.loadingIndicator.waitFor({ state: 'detached' })
})
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
await scene.expectPixelColor(
[143, 143, 143],
{ x: (viewport?.width ?? 1200) / 2, y: (viewport?.height ?? 500) / 2 },
15
)
})
})
})
async function clickExportButton(page: Page) {

View File

@ -39,8 +39,8 @@ test.describe('Sketch tests', () => {
${startProfileAt1}
|> arc({
radius = screwRadius,
angle_start = 0,
angle_end = 360
angleStart = 0,
angleEnd = 360
}, %)
part001 = startSketchOn('XY')
@ -60,8 +60,8 @@ test.describe('Sketch tests', () => {
|> yLine(wireOffset, %)
|> arc({
radius = wireRadius,
angle_start = 0,
angle_end = 180
angleStart = 0,
angleEnd = 180
}, %)
|> yLine(-wireOffset, %)
|> xLine(-width / 4, %)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 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: 59 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 129 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: 53 KiB

After

Width:  |  Height:  |  Size: 54 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: 52 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -1078,7 +1078,7 @@ export async function createProject({
returnHome?: boolean
}) {
await test.step(`Create project and navigate to it`, async () => {
await page.getByRole('button', { name: 'New project' }).click()
await page.getByRole('button', { name: 'Create project' }).click()
await page.getByRole('textbox', { name: 'Name' }).fill(name)
await page.getByRole('button', { name: 'Continue' }).click()

View File

@ -8,8 +8,8 @@ import { UnitLength_type } from '@kittycad/lib/dist/types/src/models'
test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL sample "car-wheel.kcl",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/car-wheel/car-wheel.kcl
* Note this test implicitly depends on the KCL sample "a-parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
*/
test('Web: should overwrite current code, cannot create new file', async ({
editor,
@ -29,8 +29,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const newSample = {
file: 'car-wheel' + FILE_EXT,
title: 'Car Wheel',
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
}
const commandBarButton = page.getByRole('button', { name: 'Commands' })
const samplesCommandOption = page.getByRole('option', {
@ -75,8 +75,8 @@ test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL samples:
* "car-wheel.kcl": https://github.com/KittyCAD/kcl-samples/blob/main/car-wheel/car-wheel.kcl
* "gear-rack.kcl": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/gear-rack.kcl
* "a-parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
* "gear-rack": https://github.com/KittyCAD/kcl-samples/blob/main/gear-rack/main.kcl
*/
test(
'Desktop: should create new file by default, optionally overwrite',
@ -93,8 +93,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const sampleOne = {
file: 'car-wheel' + FILE_EXT,
title: 'Car Wheel',
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
}
const sampleTwo = {
file: 'gear-rack' + FILE_EXT,

View File

@ -389,25 +389,25 @@ test.describe('Testing selections', () => {
await expect(u.codeLocator).toContainText(`sketch005 = startSketchOn({
plane = {
origin = { x = 0, y = -50, z = 0 },
x_axis = { x = 1, y = 0, z = 0 },
y_axis = { x = 0, y = 0, z = 1 },
z_axis = { x = 0, y = -1, z = 0 }
xAxis = { x = 1, y = 0, z = 0 },
yAxis = { x = 0, y = 0, z = 1 },
zAxis = { x = 0, y = -1, z = 0 }
}
})`)
await expect(u.codeLocator).toContainText(`sketch003 = startSketchOn({
plane = {
origin = { x = 116.53, y = 0, z = 163.25 },
x_axis = { x = -0.81, y = 0, z = 0.58 },
y_axis = { x = 0, y = -1, z = 0 },
z_axis = { x = 0.58, y = 0, z = 0.81 }
xAxis = { x = -0.81, y = 0, z = 0.58 },
yAxis = { x = 0, y = -1, z = 0 },
zAxis = { x = 0.58, y = 0, z = 0.81 }
}
})`)
await expect(u.codeLocator).toContainText(`sketch002 = startSketchOn({
plane = {
origin = { x = -91.74, y = 0, z = 80.89 },
x_axis = { x = -0.66, y = 0, z = -0.75 },
y_axis = { x = 0, y = -1, z = 0 },
z_axis = { x = -0.75, y = 0, z = 0.66 }
xAxis = { x = -0.66, y = 0, z = -0.75 },
yAxis = { x = 0, y = -1, z = 0 },
zAxis = { x = -0.75, y = 0, z = 0.66 }
}
})`)
@ -906,53 +906,6 @@ test.describe('Testing selections', () => {
).not.toBeDisabled()
})
test('Fillet button states test', async ({ page, homePage }) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn('XZ')
|> startProfileAt([-5, -5], %)
|> line([0, 10], %)
|> line([10, 0], %)
|> line([0, -10], %)
|> lineTo([profileStartX(%), profileStartY(%)], %)
|> close(%)`
)
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
const selectSegment = () => page.getByText(`line([10, 0], %)`).click()
const selectClose = () => page.getByText(`close(%)`).click()
const clickEmpty = () => page.mouse.click(950, 100)
// Now that we don't disable toolbar buttons based on selection,
// but rather based on a "selection" step in the command palette,
// the fillet button should always be enabled with a good network connection.
// I'm not sure if this test is actually useful anymore.
await selectSegment()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
await clickEmpty()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
// test fillet button with the body in the scene
const codeToAdd = `${await u.codeLocator.allInnerTexts()}
extrude001 = extrude(10, sketch001)`
await u.codeLocator.clear()
await u.codeLocator.fill(codeToAdd)
await selectSegment()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
await selectClose()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
await clickEmpty()
await expect(page.getByRole('button', { name: 'Fillet' })).toBeEnabled()
})
const removeAfterFirstParenthesis = (inputString: string) => {
const index = inputString.indexOf('(')
if (index !== -1) {

18
flake.lock generated
View File

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1721933792,
"narHash": "sha256-zYVwABlQnxpbaHMfX6Wt9jhyQstFYwN2XjleOJV3VVg=",
"lastModified": 1736320768,
"narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2122a9b35b35719ad9a395fe783eabb092df01b1",
"rev": "4bc9c909d9ac828a039f288cf872d16d38185db8",
"type": "github"
},
"original": {
@ -18,11 +18,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1718428119,
"narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=",
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5",
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github"
},
"original": {
@ -43,11 +43,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1721960387,
"narHash": "sha256-o21ax+745ETGXrcgc/yUuLw1SI77ymp3xEpJt+w/kks=",
"lastModified": 1736476219,
"narHash": "sha256-+qyv3QqdZCdZ3cSO/cbpEY6tntyYjfe1bB12mdpNFaY=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "9cbf831c5b20a53354fc12758abd05966f9f1699",
"rev": "de30cc5963da22e9742bbbbb9a3344570ed237b9",
"type": "github"
},
"original": {

1
interface.d.ts vendored
View File

@ -93,5 +93,6 @@ export interface IElectronAPI {
declare global {
interface Window {
electron: IElectronAPI
openExternalLink: (e: React.MouseEvent<HTMLAnchorElement>) => void
}
}

View File

@ -15,7 +15,7 @@
"@codemirror/autocomplete": "^6.17.0",
"@codemirror/commands": "^6.6.0",
"@codemirror/language": "^6.10.3",
"@codemirror/lint": "^6.8.1",
"@codemirror/lint": "^6.8.4",
"@codemirror/search": "^6.5.6",
"@codemirror/state": "^6.4.1",
"@codemirror/theme-one-dark": "^6.1.2",
@ -26,7 +26,7 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.0",
"@kittycad/lib": "2.0.12",
"@kittycad/lib": "2.0.13",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.1",
"@react-hook/resize-observer": "^2.0.1",
@ -52,20 +52,20 @@
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-hotkeys-hook": "^4.5.1",
"react-hotkeys-hook": "^4.6.1",
"react-json-view": "^1.21.3",
"react-modal": "^3.16.1",
"react-modal": "^3.16.3",
"react-modal-promise": "^1.0.2",
"react-router-dom": "^6.28.0",
"sketch-helpers": "^0.0.4",
"three": "^0.166.1",
"three": "^0.172.0",
"ua-parser-js": "^1.0.37",
"uuid": "^11.0.2",
"vscode-jsonrpc": "^8.2.1",
"vscode-languageserver-protocol": "^3.17.5",
"vscode-uri": "^3.0.8",
"web-vitals": "^3.5.2",
"xstate": "^5.17.4",
"xstate": "^5.19.2",
"yargs": "^17.7.2"
},
"scripts": {
@ -91,8 +91,8 @@
"build:wasm": "yarn wasm-prep && cd src/wasm-lib && wasm-pack build --release --target web --out-dir pkg && cargo test -p kcl-lib export_bindings && cd ../.. && yarn isomorphic-copy-wasm && yarn fmt",
"remove-importmeta": "sed -i 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\"; sed -i '' 's/import.meta.url/window.location.origin/g' \"./src/wasm-lib/pkg/wasm_lib.js\" || echo \"sed for both mac and linux\"",
"wasm-prep": "rimraf src/wasm-lib/pkg && mkdirp src/wasm-lib/pkg && rimraf src/wasm-lib/kcl/bindings",
"lint-fix": "eslint --fix src e2e packages/codemirror-lsp-client",
"lint": "eslint --max-warnings 0 src e2e packages/codemirror-lsp-client",
"lint-fix": "eslint --fix --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src",
"lint": "eslint --max-warnings 0 --ext .ts --ext .tsx src e2e packages/codemirror-lsp-client/src",
"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",
@ -149,12 +149,11 @@
"@electron-forge/plugin-vite": "7.4.0",
"@electron/fuses": "1.8.0",
"@iarna/toml": "^2.2.5",
"@lezer/generator": "^1.7.1",
"@lezer/generator": "^1.7.2",
"@nabla/vite-plugin-eslint": "^2.0.5",
"@playwright/test": "^1.49.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^15.0.2",
"@types/d3-force": "^3.0.10",
"@types/diff": "^6.0.0",
"@types/electron": "^1.6.10",
"@types/isomorphic-fetch": "^0.0.39",
@ -166,27 +165,28 @@
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.1",
"@types/react-modal": "^3.16.3",
"@types/three": "^0.163.0",
"@types/three": "^0.172.0",
"@types/ua-parser-js": "^0.7.39",
"@types/uuid": "^9.0.8",
"@types/wicg-file-system-access": "^2023.10.5",
"@types/ws": "^8.5.13",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"@vitejs/plugin-react": "^4.3.0",
"@vitest/web-worker": "^1.5.0",
"@xstate/cli": "^0.5.17",
"autoprefixer": "^10.4.19",
"d3-force": "^3.0.0",
"electron": "32.1.2",
"electron-builder": "24.13.3",
"electron-notarize": "1.2.2",
"eslint": "^8.0.1",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-css-modules": "^2.12.0",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jest": "^28.10.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.3",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-suggest-no-throw": "^1.0.0",
"happy-dom": "^15.11.7",
"eslint-plugin-testing-library": "^7.1.1",
"happy-dom": "^16.3.0",
"http-server": "^14.1.1",
"husky": "^9.1.5",
"kill-port": "^2.0.1",
@ -199,7 +199,8 @@
"setimmediate": "^1.0.5",
"tailwindcss": "^3.4.1",
"ts-node": "^10.0.0",
"typescript": "^5.7.2",
"typescript": "^5.7.3",
"typescript-eslint": "^8.19.1",
"vite": "^5.4.6",
"vite-plugin-package-version": "^1.1.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -4,4 +4,5 @@ dist
tsconfig.tsbuildinfo
*.d.ts
*.js
!postcss.config.js
!rollup.config.js

View File

@ -28,6 +28,7 @@
"@rollup/plugin-typescript": "^12.1.2",
"rollup": "^4.29.1",
"rollup-plugin-dts": "^6.1.1",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.1.8"
},
"files": [

View File

@ -0,0 +1 @@
// This is here to prevent using the one in the root of the project.

View File

@ -85,7 +85,7 @@ commaSep1NoTrailingComma<term> { term ("," term)* }
@tokens {
String[isolate] { "'" ("\\" _ | !['\\])* "'" | '"' ("\\" _ | !["\\])* '"' }
Number { "." @digit+ | @digit+ ("." @digit*)? }
Number { "." @digit+ | @digit+ ("." @digit+)? }
@precedence { Number, "." }
AddOp { "+" | "-" }

View File

@ -0,0 +1,43 @@
# spaced
a = [0 .. 1]
==>
Program(VariableDeclaration(VariableDefinition,
Equals,
ArrayExpression(IntegerRange(Number,
Number))))
# compact
a = [0..1]
==>
Program(VariableDeclaration(VariableDefinition,
Equals,
ArrayExpression(IntegerRange(Number,
Number))))
# expr spaced
a = [start .. start + 10]
==>
Program(VariableDeclaration(VariableDefinition,
Equals,
ArrayExpression(IntegerRange(VariableName,
BinaryExpression(VariableName,
AddOp,
Number)))))
# expr compact
a = [start..start + 10]
==>
Program(VariableDeclaration(VariableDefinition,
Equals,
ArrayExpression(IntegerRange(VariableName,
BinaryExpression(VariableName,
AddOp,
Number)))))

View File

@ -398,7 +398,7 @@ check-error@^2.1.1:
resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc"
integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==
debug@^4.3.7:
debug@^4.1.1, debug@^4.3.7:
version "4.4.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
@ -471,6 +471,11 @@ function-bind@^1.1.2:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
globrex@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
@ -647,6 +652,11 @@ tinyspy@^3.0.2:
resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a"
integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==
tsconfck@^3.0.3:
version "3.1.4"
resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.1.4.tgz#de01a15334962e2feb526824339b51be26712229"
integrity sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==
typescript@^5.7.2:
version "5.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
@ -663,6 +673,15 @@ vite-node@2.1.8:
pathe "^1.1.2"
vite "^5.0.0"
vite-tsconfig-paths@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9"
integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==
dependencies:
debug "^4.1.1"
globrex "^0.1.2"
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.11"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.11.tgz#3b415cd4aed781a356c1de5a9ebafb837715f6e5"

View File

@ -29,7 +29,7 @@
"vscode-uri": "^3.0.8"
},
"devDependencies": {
"@types/node": "^20.14.9",
"@types/node": "^22.10.6",
"ts-node": "^10.9.2"
}
}

View File

@ -42,7 +42,7 @@ export default class StreamDemuxer extends Queue<Uint8Array> {
// try to parse the content-length from the headers
const length = parseInt(match[1])
if (isNaN(length))
if (Number.isNaN(length))
return Promise.reject(new Error('invalid content length'))
// slice the headers since we now have the content length

View File

@ -368,13 +368,20 @@ export class LanguageServerPlugin implements PluginValue {
sortText,
filterText,
}) => {
const detailText = [
deprecated ? 'Deprecated' : undefined,
labelDetails ? labelDetails.detail : detail,
]
// Don't let undefined appear.
.filter(Boolean)
.join(' ')
const completion: Completion & {
filterText: string
sortText?: string
apply: string
} = {
label,
detail: labelDetails ? labelDetails.detail : detail,
detail: detailText,
apply: label,
type: kind && CompletionItemKindMap[kind].toLowerCase(),
sortText: sortText ?? label,
@ -382,7 +389,11 @@ export class LanguageServerPlugin implements PluginValue {
}
if (documentation) {
completion.info = () => {
const htmlString = formatMarkdownContents(documentation)
const deprecatedHtml = deprecated
? '<p><strong>Deprecated</strong></p>'
: ''
const htmlString =
deprecatedHtml + formatMarkdownContents(documentation)
const htmlNode = document.createElement('div')
htmlNode.style.display = 'contents'
htmlNode.innerHTML = htmlString

View File

@ -109,12 +109,12 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@types/node@^20.14.9":
version "20.14.9"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.9.tgz#12e8e765ab27f8c421a1820c99f5f313a933b420"
integrity sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==
"@types/node@^22.10.6":
version "22.10.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.6.tgz#5c6795e71635876039f853cbccd59f523d9e4239"
integrity sha512-qNiuwC4ZDAUNcY47xgaSuS92cjf8JbSUoaKS77bmLG1rU7MlATVSiw/IlrjtIyyskXBZ8KkNfjK/P5na7rgXbQ==
dependencies:
undici-types "~5.26.4"
undici-types "~6.20.0"
acorn-walk@^8.1.1:
version "8.3.3"
@ -187,10 +187,10 @@ typescript@^5.7.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
undici-types@~5.26.4:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
undici-types@~6.20.0:
version "6.20.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
v8-compile-cache-lib@^3.0.1:
version "3.0.1"

View File

@ -32,10 +32,9 @@ export default defineConfig({
},
projects: [
{
name: 'Google Chrome',
name: 'chromium',
use: {
...devices['Desktop Chrome'],
channel: 'chrome',
contextOptions: {
/* Chromium is the only one with these permission types */
permissions: ['clipboard-write', 'clipboard-read'],

View File

@ -1,172 +1,212 @@
[
{
"file": "80-20-rail.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "80-20-rail/main.kcl",
"multipleFiles": false,
"title": "80/20 Rail",
"description": "An 80/20 extruded aluminum linear rail. T-slot profile adjustable by profile height, rail length, and origin position"
},
{
"file": "a-parametric-bearing-pillow-block.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "a-parametric-bearing-pillow-block/main.kcl",
"multipleFiles": false,
"title": "A Parametric Bearing Pillow Block",
"description": "A bearing pillow block, also known as a plummer block or pillow block bearing, is a pedestal used to provide support for a rotating shaft with the help of compatible bearings and various accessories. Housing a bearing, the pillow block provides a secure and stable foundation that allows the shaft to rotate smoothly within its machinery setup. These components are essential in a wide range of mechanical systems and machinery, playing a key role in reducing friction and supporting radial and axial loads."
},
{
"file": "ball-bearing.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "ball-bearing/main.kcl",
"multipleFiles": false,
"title": "Ball Bearing",
"description": "A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads."
},
{
"file": "bracket.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "bracket/main.kcl",
"multipleFiles": false,
"title": "Shelf Bracket",
"description": "This is a bracket that holds a shelf. It is made of aluminum and is designed to hold a force of 300 lbs. The bracket is 6 inches wide and the force is applied at the end of the shelf, 12 inches from the wall. The bracket has a factor of safety of 1.2. The legs of the bracket are 5 inches and 2 inches long. The thickness of the bracket is calculated from the constraints provided."
},
{
"file": "brake-caliper.kcl",
"title": "Brake Caliper",
"description": "Brake calipers are used to squeeze the brake pads against the rotor, causing larger and larger amounts of friction depending on how hard the brakes are pressed."
},
{
"file": "car-wheel.kcl",
"title": "Car Wheel",
"description": "A sports car wheel with a circular lug pattern and spokes."
},
{
"file": "car-wheel-assembly.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "car-wheel-assembly/main.kcl",
"multipleFiles": true,
"title": "Car Wheel Assembly",
"description": "A car wheel assembly with a rotor, tire, and lug nuts."
},
{
"file": "dodecahedron.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "dodecahedron/main.kcl",
"multipleFiles": false,
"title": "Hollow Dodecahedron",
"description": "A regular dodecahedron or pentagonal dodecahedron is a dodecahedron composed of regular pentagonal faces, three meeting at each vertex. This example shows constructing the individual faces of the dodecahedron and extruding inwards."
},
{
"file": "enclosure.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "enclosure/main.kcl",
"multipleFiles": false,
"title": "Enclosure",
"description": "An enclosure body and sealing lid for storing items"
},
{
"file": "flange-with-patterns.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "flange-with-patterns/main.kcl",
"multipleFiles": false,
"title": "Flange",
"description": "A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others."
},
{
"file": "flange-xy.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "flange-xy/main.kcl",
"multipleFiles": false,
"title": "Flange with XY coordinates",
"description": "A flange is a flat rim, collar, or rib, typically forged or cast, that is used to strengthen an object, guide it, or attach it to another object. Flanges are known for their use in various applications, including piping, plumbing, and mechanical engineering, among others."
},
{
"file": "focusrite-scarlett-mounting-bracket.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "focusrite-scarlett-mounting-bracket/main.kcl",
"multipleFiles": false,
"title": "A mounting bracket for the Focusrite Scarlett Solo audio interface",
"description": "This is a bracket that holds an audio device underneath a desk or shelf. The audio device has dimensions of 144mm wide, 80mm length and 45mm depth with fillets of 6mm. This mounting bracket is designed to be 3D printed with PLA material"
},
{
"file": "food-service-spatula.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "food-service-spatula/main.kcl",
"multipleFiles": false,
"title": "Food Service Spatula",
"description": "Use these spatulas for mixing, flipping, and scraping."
},
{
"file": "french-press.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "french-press/main.kcl",
"multipleFiles": false,
"title": "French Press",
"description": "A french press immersion coffee maker"
},
{
"file": "gear.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "gear/main.kcl",
"multipleFiles": false,
"title": "Spur Gear",
"description": "A rotating machine part having cut teeth or, in the case of a cogwheel, inserted teeth (called cogs), which mesh with another toothed part to transmit torque. Geared devices can change the speed, torque, and direction of a power source. The two elements that define a gear are its circular shape and the teeth that are integrated into its outer edge, which are designed to fit into the teeth of another gear."
},
{
"file": "gear-rack.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "gear-rack/main.kcl",
"multipleFiles": false,
"title": "100mm Gear Rack",
"description": "A flat bar or rail that is engraved with teeth along its length. These teeth are designed to mesh with the teeth of a gear, known as a pinion. When the pinion, a small cylindrical gear, rotates, its teeth engage with the teeth on the rack, causing the rack to move linearly. Conversely, linear motion applied to the rack will cause the pinion to rotate."
},
{
"file": "hex-nut.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "hex-nut/main.kcl",
"multipleFiles": false,
"title": "Hex nut",
"description": "A hex nut is a type of fastener with a threaded hole and a hexagonal outer shape, used in a wide variety of applications to secure parts together. The hexagonal shape allows for a greater torque to be applied with wrenches or tools, making it one of the most common nut types in hardware."
},
{
"file": "i-beam.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "i-beam/main.kcl",
"multipleFiles": false,
"title": "I-beam",
"description": "A structural metal beam with an I shaped cross section. Often used in construction"
},
{
"file": "kitt.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "kitt/main.kcl",
"multipleFiles": false,
"title": "Kitt",
"description": "The beloved KittyCAD mascot in a voxelized style."
},
{
"file": "lego.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "lego/main.kcl",
"multipleFiles": false,
"title": "Lego Brick",
"description": "A standard Lego brick. This is a small, plastic construction block toy that can be interlocked with other blocks to build various structures, models, and figures. There are a lot of hacks used in this code."
},
{
"file": "lug-nut.kcl",
"title": "Lug Nut",
"description": "lug Nuts are essential components used to create secure connections, whether for electrical purposes, like terminating wires or grounding, or for mechanical purposes, such as providing mounting points or reinforcing structural joints."
},
{
"file": "mounting-plate.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "mounting-plate/main.kcl",
"multipleFiles": false,
"title": "Mounting Plate",
"description": "A flat piece of material, often metal or plastic, that serves as a support or base for attaching, securing, or mounting various types of equipment, devices, or components."
},
{
"file": "multi-axis-robot.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "multi-axis-robot/main.kcl",
"multipleFiles": true,
"title": "Robot Arm",
"description": "A 4 axis robotic arm for industrial use. These machines can be used for assembly, packaging, organization of goods, and quality inspection processes"
},
{
"file": "pipe.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "pipe/main.kcl",
"multipleFiles": false,
"title": "Pipe",
"description": "A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow."
},
{
"file": "pipe-flange-assembly.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "pipe-flange-assembly/main.kcl",
"multipleFiles": false,
"title": "Pipe and Flange Assembly",
"description": "A crucial component in various piping systems, designed to facilitate the connection, disconnection, and access to piping for inspection, cleaning, and modifications. This assembly combines pipes (long cylindrical conduits) with flanges (plate-like fittings) to create a secure yet detachable joint."
},
{
"file": "pipe-with-bend.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "pipe-with-bend/main.kcl",
"multipleFiles": false,
"title": "Pipe with bend",
"description": "A tubular section or hollow cylinder, usually but not necessarily of circular cross-section, used mainly to convey substances that can flow."
},
{
"file": "poopy-shoe.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "poopy-shoe/main.kcl",
"multipleFiles": false,
"title": "Poopy Shoe",
"description": "poop shute for bambu labs printer - optimized for printing."
},
{
"file": "router-template-cross-bar.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "router-template-cross-bar/main.kcl",
"multipleFiles": false,
"title": "Router template for a cross bar",
"description": "A guide for routing a notch into a cross bar."
},
{
"file": "router-template-slate.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "router-template-slate/main.kcl",
"multipleFiles": false,
"title": "Router template for a slate",
"description": "A guide for routing a slate for a cross bar."
},
{
"file": "sheet-metal-bracket.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "sheet-metal-bracket/main.kcl",
"multipleFiles": false,
"title": "Sheet Metal Bracket",
"description": "A component typically made from flat sheet metal through various manufacturing processes such as bending, punching, cutting, and forming. These brackets are used to support, attach, or mount other hardware components, often providing a structural or functional base for assembly."
},
{
"file": "socket-head-cap-screw.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "socket-head-cap-screw/main.kcl",
"multipleFiles": false,
"title": "Socket Head Cap Screw",
"description": "This is for a #10-24 screw that is 1.00 inches long. A socket head cap screw is a type of fastener that is widely used in a variety of applications requiring a high strength fastening solution. It is characterized by its cylindrical head and internal hexagonal drive, which allows for tightening with an Allen wrench or hex key."
},
{
"file": "tire.kcl",
"title": "Tire",
"description": "A tire is a critical component of a vehicle that provides the necessary traction and grip between the car and the road. It supports the vehicle's weight and absorbs shocks from road irregularities."
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "walkie-talkie/main.kcl",
"multipleFiles": true,
"title": "Walkie Talkie",
"description": "A portable, handheld two-way radio device that allows users to communicate wirelessly over short to medium distances. It operates on specific radio frequencies and features a push-to-talk button for transmitting messages, making it ideal for quick and reliable communication in outdoor, work, or emergency settings."
},
{
"file": "washer.kcl",
"file": "main.kcl",
"pathFromProjectDirectoryToFirstFile": "washer/main.kcl",
"multipleFiles": false,
"title": "Washer",
"description": "A small, typically disk-shaped component with a hole in the middle, used in a wide range of applications, primarily in conjunction with fasteners like bolts and screws. Washers distribute the load of a fastener across a broader area. This is especially important when the fastening surface is soft or uneven, as it helps to prevent damage to the surface and ensures the load is evenly distributed, reducing the risk of the fastener becoming loose over time."
},
{
"file": "wheel-rotor.kcl",
"title": "Wheel rotor",
"description": "A component of a disc brake system. It provides a surface for brake pads to press against, generating the friction needed to slow or stop the vehicle."
}
]

View File

@ -22,6 +22,8 @@ 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 { useCommandsContext } from 'hooks/useCommandsContext'
import { maybeWriteToDisk } from 'lib/telemetry'
maybeWriteToDisk()
.then(() => {})
@ -29,6 +31,20 @@ maybeWriteToDisk()
export function App() {
const { project, file } = useLoaderData() as IndexLoaderData
const { commandBarSend } = useCommandsContext()
// Keep a lookout for a URL query string that invokes the 'import file from URL' command
useCreateFileLinkQuery((argDefaultValues) => {
commandBarSend({
type: 'Find and select command',
data: {
groupId: 'projects',
name: 'Import file from URL',
argDefaultValues,
},
})
})
useRefreshSettings(PATHS.FILE + 'SETTINGS')
const navigate = useNavigate()
const filePath = useAbsoluteFilePath()

View File

@ -35,7 +35,7 @@ import { CommandBarProvider } from 'components/CommandBar/CommandBarProvider'
import SettingsAuthProvider from 'components/SettingsAuthProvider'
import LspProvider from 'components/LspProvider'
import { KclContextProvider } from 'lang/KclProvider'
import { BROWSER_PROJECT_NAME } from 'lib/constants'
import { ASK_TO_OPEN_QUERY_PARAM, BROWSER_PROJECT_NAME } from 'lib/constants'
import { CoreDumpManager } from 'lib/coredump'
import { codeManager, engineCommandManager } from 'lib/singletons'
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
@ -47,6 +47,7 @@ import { AppStateProvider } from 'AppState'
import { reportRejection } from 'lib/trap'
import { RouteProvider } from 'components/RouteProvider'
import { ProjectsContextProvider } from 'components/ProjectsContextProvider'
import { OpenInDesktopAppHandler } from 'components/OpenInDesktopAppHandler'
const createRouter = isDesktop() ? createHashRouter : createBrowserRouter
@ -58,6 +59,7 @@ const router = createRouter([
/* Make sure auth is the outermost provider or else we will have
* inefficient re-renders, use the react profiler to see. */
element: (
<OpenInDesktopAppHandler>
<CommandBarProvider>
<RouteProvider>
<SettingsAuthProvider>
@ -75,16 +77,26 @@ const router = createRouter([
</SettingsAuthProvider>
</RouteProvider>
</CommandBarProvider>
</OpenInDesktopAppHandler>
),
errorElement: <ErrorPage />,
children: [
{
path: PATHS.INDEX,
loader: async () => {
loader: async ({ request }) => {
const onDesktop = isDesktop()
return onDesktop
? redirect(PATHS.HOME)
: redirect(PATHS.FILE + '/%2F' + BROWSER_PROJECT_NAME)
const url = new URL(request.url)
if (onDesktop) {
return redirect(PATHS.HOME + (url.search || ''))
} else {
const searchParams = new URLSearchParams(url.search)
if (!searchParams.has(ASK_TO_OPEN_QUERY_PARAM)) {
return redirect(
PATHS.FILE + '/%2F' + BROWSER_PROJECT_NAME + (url.search || '')
)
}
}
return null
},
},
{

View File

@ -1,4 +1,4 @@
import { useRef, useMemo, memo } from 'react'
import { useRef, useMemo, memo, useCallback, useState } from 'react'
import { isCursorInSketchCommandRange } from 'lang/util'
import { engineCommandManager, kclManager } from 'lib/singletons'
import { useModelingContext } from 'hooks/useModelingContext'
@ -34,8 +34,7 @@ export function Toolbar({
const bgClassName = '!bg-transparent'
const buttonBgClassName =
'bg-chalkboard-transparent dark:bg-transparent disabled:bg-transparent dark:disabled:bg-transparent enabled:hover:bg-chalkboard-10 dark:enabled:hover:bg-chalkboard-100 pressed:!bg-primary pressed:enabled:hover:!text-chalkboard-10'
const buttonBorderClassName =
'!border-transparent hover:!border-chalkboard-20 dark:enabled:hover:!border-primary pressed:!border-primary ui-open:!border-primary'
const buttonBorderClassName = '!border-transparent'
const sketchPathId = useMemo(() => {
if (!isSingleCursorInPipe(context.selectionRanges, kclManager.ast))
@ -50,6 +49,7 @@ export function Toolbar({
const { overallState } = useNetworkContext()
const { isExecuting } = useKclContext()
const { isStreamReady } = useAppState()
const [showRichContent, setShowRichContent] = useState(false)
const disableAllButtons =
(overallState !== NetworkHealthState.Ok &&
@ -77,6 +77,40 @@ export function Toolbar({
[state, send, commandBarSend, sketchPathId]
)
const tooltipContentClassName = !showRichContent
? ''
: '!text-left text-wrap !text-xs !p-0 !pb-2 flex gap-2 !max-w-none !w-72 flex-col items-stretch'
const richContentTimeout = useRef<number | null>(null)
const richContentClearTimeout = useRef<number | null>(null)
// On mouse enter, show rich content after a 1s delay
const handleMouseEnter = useCallback(() => {
// Cancel the clear timeout if it's already set
if (richContentClearTimeout.current) {
clearTimeout(richContentClearTimeout.current)
}
// Start our own timeout to show the rich content
richContentTimeout.current = window.setTimeout(() => {
setShowRichContent(true)
if (richContentClearTimeout.current) {
clearTimeout(richContentClearTimeout.current)
}
}, 1000)
}, [setShowRichContent])
// On mouse leave, clear the timeout and hide rich content
const handleMouseLeave = useCallback(() => {
// Clear the timeout to show rich content
if (richContentTimeout.current) {
clearTimeout(richContentTimeout.current)
}
// Start a timeout to hide the rich content
richContentClearTimeout.current = window.setTimeout(() => {
setShowRichContent(false)
if (richContentClearTimeout.current) {
clearTimeout(richContentClearTimeout.current)
}
}, 500)
}, [setShowRichContent])
/**
* Resolve all the callbacks and values for the current mode,
* so we don't need to worry about the other modes
@ -173,6 +207,12 @@ export function Toolbar({
itemConfig.disabled === true,
status: itemConfig.status,
}))}
>
<div
className="contents"
// Mouse events do not fire on disabled buttons
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<ActionButton
Element="button"
@ -206,11 +246,26 @@ export function Toolbar({
>
{maybeIconConfig[0].title}
</span>
</ActionButton>
<ToolbarItemTooltip
itemConfig={maybeIconConfig[0]}
configCallbackProps={configCallbackProps}
wrapperClassName="ui-open:!hidden"
contentClassName={tooltipContentClassName}
>
{showRichContent ? (
<ToolbarItemTooltipRichContent
itemConfig={maybeIconConfig[0]}
/>
) : (
<ToolbarItemTooltipShortContent
status={maybeIconConfig[0].status}
title={maybeIconConfig[0].title}
hotkey={maybeIconConfig[0].hotkey}
/>
)}
</ToolbarItemTooltip>
</ActionButton>
</div>
</ActionButtonDropdown>
)
}
@ -218,7 +273,13 @@ export function Toolbar({
// A single button
return (
<div className="relative" key={itemConfig.id}>
<div
className="relative"
key={itemConfig.id}
// Mouse events do not fire on disabled buttons
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<ActionButton
Element="button"
key={itemConfig.id}
@ -255,7 +316,18 @@ export function Toolbar({
<ToolbarItemTooltip
itemConfig={itemConfig}
configCallbackProps={configCallbackProps}
contentClassName={tooltipContentClassName}
>
{showRichContent ? (
<ToolbarItemTooltipRichContent itemConfig={itemConfig} />
) : (
<ToolbarItemTooltipShortContent
status={itemConfig.status}
title={itemConfig.title}
hotkey={itemConfig.hotkey}
/>
)}
</ToolbarItemTooltip>
</div>
)
})}
@ -269,6 +341,12 @@ export function Toolbar({
)
}
interface ToolbarItemContentsProps extends React.PropsWithChildren {
itemConfig: ToolbarItemResolved
configCallbackProps: ToolbarItemCallbackProps
wrapperClassName?: string
contentClassName?: string
}
/**
* The single button and dropdown button share content, so we extract it here
* It contains a tooltip with the title, description, and links
@ -277,12 +355,10 @@ export function Toolbar({
const ToolbarItemTooltip = memo(function ToolbarItemContents({
itemConfig,
configCallbackProps,
}: {
itemConfig: ToolbarItemResolved
configCallbackProps: ToolbarItemCallbackProps
}) {
const { state } = useModelingContext()
wrapperClassName = '',
contentClassName = '',
children,
}: ToolbarItemContentsProps) {
useHotkeys(
itemConfig.hotkey || '',
() => {
@ -305,11 +381,50 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
? ({ '-webkit-app-region': 'no-drag' } as React.CSSProperties)
: {}
}
hoverOnly
position="bottom"
wrapperClassName="!p-4 !pointer-events-auto"
contentClassName="!text-left text-wrap !text-xs !p-0 !pb-2 flex gap-2 !max-w-none !w-72 flex-col items-stretch"
wrapperClassName={'!p-4 !pointer-events-auto ' + wrapperClassName}
contentClassName={contentClassName}
delay={0}
>
{children}
</Tooltip>
)
})
const ToolbarItemTooltipShortContent = ({
status,
title,
hotkey,
}: {
status: string
title: string
hotkey?: string | string[]
}) => (
<span
className={`text-sm ${
status !== 'available' ? 'text-chalkboard-70 dark:text-chalkboard-40' : ''
}`}
>
{title}
{hotkey && (
<kbd className="inline-block ml-2 flex-none hotkey">{hotkey}</kbd>
)}
</span>
)
const ToolbarItemTooltipRichContent = ({
itemConfig,
}: {
itemConfig: ToolbarItemResolved
}) => {
const { state } = useModelingContext()
return (
<>
<div className="rounded-top flex items-center gap-2 pt-3 pb-2 px-2 bg-chalkboard-20/50 dark:bg-chalkboard-80/50">
{itemConfig.icon && (
<CustomIcon className="w-5 h-5" name={itemConfig.icon} />
)}
<span
className={`text-sm flex-1 ${
itemConfig.status !== 'available'
@ -378,6 +493,6 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
</ul>
</>
)}
</Tooltip>
</>
)
})
}

View File

@ -108,6 +108,8 @@ export class CameraControls {
interactionGuards: MouseGuard = cameraMouseDragGuards.Zoo
isFovAnimationInProgress = false
perspectiveFovBeforeOrtho = 45
// NOTE: Duplicated state across Provider and singleton. Mapped from settingsMachine
_setting_allowOrbitInSketchMode = false
get isPerspective() {
return this.camera instanceof PerspectiveCamera
}

View File

@ -25,13 +25,13 @@ import {
CallExpression,
PathToNode,
Program,
SourceRange,
Expr,
parse,
recast,
defaultSourceRange,
resultIsOk,
ProgramMemory,
topLevelRange,
} from 'lang/wasm'
import { CustomIcon, CustomIconName } from 'components/CustomIcon'
import { ConstrainInfo } from 'lang/std/stdTypes'
@ -600,8 +600,8 @@ const ConstraintSymbol = ({
if (err(_node)) return
const node = _node.node
const range: SourceRange = node
? [node.start, node.end, true]
const range = node
? topLevelRange(node.start, node.end)
: defaultSourceRange()
if (_type === 'intersectionTag') return null

View File

@ -1,5 +1,6 @@
import {
BoxGeometry,
Color,
DoubleSide,
Group,
Intersection,
@ -58,7 +59,9 @@ import {
sourceRangeFromRust,
resultIsOk,
SourceRange,
topLevelRange,
} from 'lang/wasm'
import { calculate_circle_from_3_points } from '../wasm-lib/pkg/wasm_lib'
import {
engineCommandManager,
kclManager,
@ -70,7 +73,7 @@ import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
import { executeAst, ToolTip } from 'lang/langHelpers'
import {
createProfileStartHandle,
createArcGeometry,
createCircleGeometry,
SegmentUtils,
segmentUtils,
} from './segments'
@ -109,6 +112,8 @@ import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Point3d } from 'wasm-lib/kcl/bindings/Point3d'
import { SegmentInputs } from 'lang/std/stdTypes'
import { Node } from 'wasm-lib/kcl/bindings/Node'
import { LabeledArg } from 'wasm-lib/kcl/bindings/LabeledArg'
import { Literal } from 'wasm-lib/kcl/bindings/Literal'
import { radToDeg } from 'three/src/math/MathUtils'
import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph'
@ -624,7 +629,7 @@ export class SceneEntities {
const startRange = _node1.node.start
const endRange = _node1.node.end
const sourceRange: SourceRange = [startRange, endRange, true]
const sourceRange = topLevelRange(startRange, endRange)
const selection: Selections = computeSelectionFromSourceRangeAndAST(
sourceRange,
maybeModdedAst
@ -1261,110 +1266,98 @@ export class SceneEntities {
const groupOfDrafts = new Group()
groupOfDrafts.name = 'circle-3-point-group'
groupOfDrafts.position.copy(sketchOrigin)
// lee: I'm keeping this here as a developer gotchya:
// Do not reorient your surfaces to the intersection plane. Your points are
// already in 3D space, not 2D. If you intersect say XZ, you want the points
// to continue to live at the 3D intersection point, not be rotated to end
// up elsewhere!
// groupOfDrafts.setRotationFromQuaternion(orientation)
// If you use 3D points, do not rotate anything.
// If you use 2D points (easier to deal with, generally do this!), then
// rotate the group just like this! Remember to rotate other groups too!
groupOfDrafts.setRotationFromQuaternion(orientation)
this.scene.add(groupOfDrafts)
const DRAFT_POINT_RADIUS = 6
// How large the points on the circle will render as
const DRAFT_POINT_RADIUS = 10 // px
const createPoint = (center: Vector3): number => {
// The target of our dragging
let target: Object3D | undefined = undefined
// The KCL this will generate.
const kclCircle3Point = parse(`circleThreePoint(
p1 = [0.0, 0.0],
p2 = [0.0, 0.0],
p3 = [0.0, 0.0],
)`)
const createPoint = (
center: Vector3,
opts?: { noInteraction?: boolean }
): Mesh => {
const geometry = new SphereGeometry(DRAFT_POINT_RADIUS)
const color = getThemeColorForThreeJs(sceneInfra._theme)
const material = new MeshBasicMaterial({ color })
const material = new MeshBasicMaterial({
color: opts?.noInteraction
? sceneInfra._theme === 'light'
? new Color(color).multiplyScalar(0.15)
: new Color(0x010101).multiplyScalar(2000)
: color,
})
const mesh = new Mesh(geometry, material)
mesh.userData = { type: CIRCLE_3_POINT_DRAFT_POINT }
mesh.userData = {
type: opts?.noInteraction ? 'ghost' : CIRCLE_3_POINT_DRAFT_POINT,
}
mesh.renderOrder = 1000
mesh.layers.set(SKETCH_LAYER)
mesh.position.copy(center)
mesh.scale.set(scale, scale, scale)
mesh.renderOrder = 100
groupOfDrafts.add(mesh)
return mesh.id
return mesh
}
const circle3Point = (
points: Vector2[]
): undefined | { center: Vector3; radius: number } => {
// A 3-point circle is undefined if it doesn't have 3 points :)
if (points.length !== 3) return undefined
// y = (i/j)(x-h) + b
// i and j variables for the slopes
const i = [points[1].x - points[0].x, points[2].x - points[1].x]
const j = [points[1].y - points[0].y, points[2].y - points[1].y]
// Our / threejs coordinate system affects this a lot. If you take this
// code into a different code base, you may have to adjust a/b to being
// -1/a/b, b/a, etc! In this case, a/-b did the trick.
const m = [i[0] / -j[0], i[1] / -j[1]]
const h = [
(points[0].x + points[1].x) / 2,
(points[1].x + points[2].x) / 2,
]
const b = [
(points[0].y + points[1].y) / 2,
(points[1].y + points[2].y) / 2,
]
// Algebraically derived
const x = (-m[0] * h[0] + b[0] - b[1] + m[1] * h[1]) / (m[1] - m[0])
const y = m[0] * (x - h[0]) + b[0]
const center = new Vector3(x, y, 0)
const radius = Math.sqrt((points[1].x - x) ** 2 + (points[1].y - y) ** 2)
return {
center,
radius,
}
}
// TO BE SHORT LIVED: unused function to draw the circle and lines.
// @ts-ignore
// eslint-disable-next-line
const createCircle3Point = (points: Vector2[]) => {
const circleParams = circle3Point(points)
// A circle cannot be created for these points.
if (!circleParams) return
const createCircle3PointGraphic = async (
points: Vector2[],
center: Vector2,
radius: number
) => {
if (
Number.isNaN(radius) ||
Number.isNaN(center.x) ||
Number.isNaN(center.y)
)
return
const color = getThemeColorForThreeJs(sceneInfra._theme)
const geometryCircle = createArcGeometry({
center: [circleParams.center.x, circleParams.center.y],
radius: circleParams.radius,
startAngle: 0,
endAngle: Math.PI * 2,
ccw: true,
isDashed: true,
scale,
const lineCircle = createCircleGeometry({
center: [center.x, center.y],
radius,
color,
isDashed: false,
scale: 1,
})
const materialCircle = new MeshBasicMaterial({ color })
lineCircle.userData = { type: CIRCLE_3_POINT_DRAFT_CIRCLE }
lineCircle.layers.set(SKETCH_LAYER)
// devnote: it's a mistake to use these with EllipseCurve :)
// lineCircle.position.set(center.x, center.y, 0)
// lineCircle.scale.set(scale, scale, scale)
if (groupCircle) groupOfDrafts.remove(groupCircle)
groupCircle = new Group()
groupCircle.renderOrder = 1
groupCircle.add(lineCircle)
const meshCircle = new Mesh(geometryCircle, materialCircle)
meshCircle.userData = { type: CIRCLE_3_POINT_DRAFT_CIRCLE }
meshCircle.layers.set(SKETCH_LAYER)
meshCircle.position.set(circleParams.center.x, circleParams.center.y, 0)
meshCircle.scale.set(scale, scale, scale)
groupCircle.add(meshCircle)
const pointMesh = createPoint(new Vector3(center.x, center.y, 0), {
noInteraction: true,
})
groupCircle.add(pointMesh)
const geometryPolyLine = new BufferGeometry().setFromPoints([
...points,
points[0],
...points.map((p) => new Vector3(p.x, p.y, 0)),
new Vector3(points[0].x, points[0].y, 0),
])
const materialPolyLine = new LineDashedMaterial({
color,
scale,
scale: 1 / scale,
dashSize: 6,
gapSize: 6,
})
@ -1375,13 +1368,146 @@ export class SceneEntities {
groupOfDrafts.add(groupCircle)
}
// The target of our dragging
let target: Object3D | undefined = undefined
const insertCircle3PointKclIntoAstSnapshot = (
points: Vector2[]
): Program => {
if (err(kclCircle3Point) || kclCircle3Point.program === null)
return kclManager.ast
if (kclCircle3Point.program.body[0].type !== 'ExpressionStatement')
return kclManager.ast
if (
kclCircle3Point.program.body[0].expression.type !== 'CallExpressionKw'
)
return kclManager.ast
const arg = (x: LabeledArg): Literal[] | undefined => {
if (
'arg' in x &&
'elements' in x.arg &&
x.arg.type === 'ArrayExpression'
) {
if (x.arg.elements.every((x) => x.type === 'Literal')) {
return x.arg.elements
}
}
return undefined
}
const kclCircle3PointArgs =
kclCircle3Point.program.body[0].expression.arguments
const arg0 = arg(kclCircle3PointArgs[0])
if (!arg0) return kclManager.ast
arg0[0].value = { value: points[0].x, suffix: 'None' }
arg0[0].raw = points[0].x.toString()
arg0[1].value = { value: points[0].y, suffix: 'None' }
arg0[1].raw = points[0].y.toString()
const arg1 = arg(kclCircle3PointArgs[1])
if (!arg1) return kclManager.ast
arg1[0].value = { value: points[1].x, suffix: 'None' }
arg1[0].raw = points[1].x.toString()
arg1[1].value = { value: points[1].y, suffix: 'None' }
arg1[1].raw = points[1].y.toString()
const arg2 = arg(kclCircle3PointArgs[2])
if (!arg2) return kclManager.ast
arg2[0].value = { value: points[2].x, suffix: 'None' }
arg2[0].raw = points[2].x.toString()
arg2[1].value = { value: points[2].y, suffix: 'None' }
arg2[1].raw = points[2].y.toString()
const astSnapshot = structuredClone(kclManager.ast)
const startSketchOnASTNode = getNodeFromPath<VariableDeclaration>(
astSnapshot,
startSketchOnASTNodePath,
'VariableDeclaration'
)
if (err(startSketchOnASTNode)) return astSnapshot
// It's possible we're already dealing with a PipeExpression.
// Modify the current one.
if (
startSketchOnASTNode.node.declaration.init.type === 'PipeExpression' &&
startSketchOnASTNode.node.declaration.init.body[1].type ===
'CallExpressionKw' &&
startSketchOnASTNode.node.declaration.init.body.length >= 2
) {
startSketchOnASTNode.node.declaration.init.body[1].arguments =
kclCircle3Point.program.body[0].expression.arguments
} else {
// Clone a new node based on the old, and replace the old with the new.
const clonedStartSketchOnASTNode = structuredClone(startSketchOnASTNode)
startSketchOnASTNode.node.declaration.init = createPipeExpression([
clonedStartSketchOnASTNode.node.declaration.init,
kclCircle3Point.program.body[0].expression,
])
}
// Return the `Program`
return astSnapshot
}
const updateCircle3Point = async (opts?: { execute?: true }) => {
const points_ = Array.from(points.values())
const circleParams = calculate_circle_from_3_points(
points_[0].x,
points_[0].y,
points_[1].x,
points_[1].y,
points_[2].x,
points_[2].y
)
if (Number.isNaN(circleParams.radius)) return
await createCircle3PointGraphic(
points_,
new Vector2(circleParams.center_x, circleParams.center_y),
circleParams.radius
)
const astWithNewCode = insertCircle3PointKclIntoAstSnapshot(points_)
const codeAsString = recast(astWithNewCode)
if (err(codeAsString)) return
codeManager.updateCodeStateEditor(codeAsString)
}
const cleanupFn = () => {
this.scene.remove(groupOfDrafts)
}
// The AST node we extracted earlier may already have a circleThreePoint!
// Use the points in the AST as starting points.
const astSnapshot = structuredClone(kclManager.ast)
const maybeVariableDeclaration = getNodeFromPath<VariableDeclaration>(
astSnapshot,
startSketchOnASTNodePath,
'VariableDeclaration'
)
if (err(maybeVariableDeclaration))
return () => {
done()
}
const maybeCallExpressionKw = maybeVariableDeclaration.node.declaration.init
if (
maybeCallExpressionKw.type === 'PipeExpression' &&
maybeCallExpressionKw.body[1].type === 'CallExpressionKw' &&
maybeCallExpressionKw.body[1]?.callee.name === 'circleThreePoint'
) {
maybeCallExpressionKw?.body[1].arguments
.map(
({ arg }: any) =>
new Vector2(arg.elements[0].value, arg.elements[1].value)
)
.forEach((point: Vector2) => {
const pointMesh = createPoint(new Vector3(point.x, point.y, 0))
groupOfDrafts.add(pointMesh)
points.set(pointMesh.id, point)
})
void updateCircle3Point()
}
sceneInfra.setCallbacks({
async onDrag(args) {
const draftPointsIntersected = args.intersects.filter(
@ -1397,8 +1523,18 @@ export class SceneEntities {
// The user was off their mark! Missed the object to select.
if (!target) return
target.position.copy(args.intersectionPoint.threeD)
target.position.copy(
new Vector3(
args.intersectionPoint.twoD.x,
args.intersectionPoint.twoD.y,
0
)
)
points.set(target.id, args.intersectionPoint.twoD)
if (points.size <= 2) return
await updateCircle3Point()
},
async onDragEnd(_args) {
target = undefined
@ -1407,45 +1543,19 @@ export class SceneEntities {
if (points.size >= 3) return
if (!args.intersectionPoint) return
const id = createPoint(args.intersectionPoint.threeD)
points.set(id, args.intersectionPoint.twoD)
if (points.size < 2) return
// We've now got 3 points, let's create our circle!
const astSnapshot = structuredClone(kclManager.ast)
let nodeQueryResult
nodeQueryResult = getNodeFromPath<VariableDeclaration>(
astSnapshot,
startSketchOnASTNodePath,
'VariableDeclaration'
const pointMesh = createPoint(
new Vector3(
args.intersectionPoint.twoD.x,
args.intersectionPoint.twoD.y,
0
)
if (err(nodeQueryResult)) return Promise.reject(nodeQueryResult)
const startSketchOnASTNode = nodeQueryResult
)
groupOfDrafts.add(pointMesh)
points.set(pointMesh.id, args.intersectionPoint.twoD)
const circleParams = circle3Point(Array.from(points.values()))
if (points.size <= 2) return
if (!circleParams) return
const kclCircle3Point = parse(`circle({
center = [${circleParams.center.x}, ${circleParams.center.y}],
radius = ${circleParams.radius},
}, %)`)
if (err(kclCircle3Point) || kclCircle3Point.program === null) return
if (kclCircle3Point.program.body[0].type !== 'ExpressionStatement')
return
const clonedStartSketchOnASTNode = structuredClone(startSketchOnASTNode)
startSketchOnASTNode.node.declaration.init = createPipeExpression([
clonedStartSketchOnASTNode.node.declaration.init,
kclCircle3Point.program.body[0].expression,
])
await kclManager.executeAstMock(astSnapshot)
await codeManager.updateEditorWithAstAndWriteToFile(astSnapshot)
done()
await updateCircle3Point()
},
})
@ -1903,7 +2013,7 @@ export class SceneEntities {
kclManager.programMemory,
{
type: 'sourceRange',
sourceRange: [node.start, node.end, true],
sourceRange: topLevelRange(node.start, node.end),
},
getChangeSketchInput()
)
@ -1941,8 +2051,8 @@ export class SceneEntities {
)
if (!(sk instanceof Reason)) {
sketch = sk
} else if ((maybeSketch as Solid).sketch) {
sketch = (maybeSketch as Solid).sketch
} else if (maybeSketch && (maybeSketch.value as Solid)?.sketch) {
sketch = (maybeSketch.value as Solid).sketch
}
if (!sketch) return
@ -2154,7 +2264,7 @@ export class SceneEntities {
)
if (trap(_node, { suppress: true })) return
const node = _node.node
editorManager.setHighlightRange([[node.start, node.end, true]])
editorManager.setHighlightRange([topLevelRange(node.start, node.end)])
const yellow = 0xffff00
colorSegment(selected, yellow)
const extraSegmentGroup = parent.getObjectByName(EXTRA_SEGMENT_HANDLE)
@ -2431,7 +2541,7 @@ export function sketchFromPathToNode({
const varDec = _varDec.node
const result = programMemory.get(varDec?.id?.name || '')
if (result?.type === 'Solid') {
return result.sketch
return result.value.sketch
}
const sg = sketchFromKclValue(result, varDec?.id?.name)
if (err(sg)) {

View File

@ -9,6 +9,9 @@ import {
ExtrudeGeometry,
Group,
LineCurve3,
LineBasicMaterial,
LineDashedMaterial,
Line,
Mesh,
MeshBasicMaterial,
NormalBufferAttributes,
@ -1003,6 +1006,49 @@ export function createArcGeometry({
return geo
}
// (lee) The above is much more complex than necessary.
// I've derived the new code from:
// https://threejs.org/docs/#api/en/extras/curves/EllipseCurve
// I'm not sure why it wasn't done like this in the first place?
// I don't touch the code above because it may break something else.
export function createCircleGeometry({
center,
radius,
color,
isDashed = false,
scale = 1,
}: {
center: Coords2d
radius: number
color: number
isDashed?: boolean
scale?: number
}): Line {
const circle = new EllipseCurve(
center[0],
center[1],
radius,
radius,
0,
Math.PI * 2,
true,
scale
)
const points = circle.getPoints(75) // just enough points to not see edges.
const geometry = new BufferGeometry().setFromPoints(points)
const material = !isDashed
? new LineBasicMaterial({ color })
: new LineDashedMaterial({
color,
scale,
dashSize: 6,
gapSize: 6,
})
const line = new Line(geometry, material)
line.computeLineDistances()
return line
}
export function dashedStraight(
from: Coords2d,
to: Coords2d,

View File

@ -1,9 +1,11 @@
import { Popover } from '@headlessui/react'
import { ActionButtonProps } from './ActionButton'
import { CustomIcon } from './CustomIcon'
import Tooltip from './Tooltip'
type ActionButtonSplitProps = ActionButtonProps & { Element: 'button' } & {
name?: string
dropdownTooltipText?: string
splitMenuItems: {
id: string
label: string
@ -17,6 +19,7 @@ type ActionButtonSplitProps = ActionButtonProps & { Element: 'button' } & {
export function ActionButtonDropdown({
splitMenuItems,
className,
dropdownTooltipText = 'More tools',
children,
...props
}: ActionButtonSplitProps) {
@ -26,7 +29,14 @@ export function ActionButtonDropdown({
{({ close }) => (
<>
{children}
<Popover.Button className="border-transparent dark:border-transparent p-0 m-0 rounded-none !outline-none ui-open:border-primary ui-open:bg-primary">
<Popover.Button
className={
'!border-transparent dark:!border-transparent ' +
'bg-chalkboard-transparent dark:bg-transparent disabled:bg-transparent dark:disabled:bg-transparent ' +
'enabled:hover:bg-chalkboard-10 dark:enabled:hover:bg-chalkboard-100 ' +
'pressed:!bg-primary pressed:enabled:hover:!text-chalkboard-10 p-0 m-0 rounded-none !outline-none ui-open:border-primary ui-open:bg-primary'
}
>
<CustomIcon
name="caretDown"
className={
@ -37,6 +47,14 @@ export function ActionButtonDropdown({
<span className="sr-only">
{props.name ? props.name + ': ' : ''}open menu
</span>
<Tooltip
delay={0}
position="bottom"
hoverOnly
wrapperClassName="ui-open:!hidden"
>
{dropdownTooltipText}
</Tooltip>
</Popover.Button>
<Popover.Panel
as="ul"

View File

@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from 'react'
import { trap } from 'lib/trap'
import { codeToIdSelections } from 'lib/selections'
import { codeRefFromRange } from 'lang/std/artifactGraph'
import { defaultSourceRange } from 'lang/wasm'
import { defaultSourceRange, SourceRange, topLevelRange } from 'lang/wasm'
export function AstExplorer() {
const { context } = useModelingContext()
@ -118,19 +118,19 @@ function DisplayObj({
hasCursor ? 'bg-violet-100/80 dark:bg-violet-100/25' : ''
}`}
onMouseEnter={(e) => {
editorManager.setHighlightRange([[obj?.start || 0, obj.end, true]])
editorManager.setHighlightRange([
topLevelRange(obj?.start || 0, obj.end),
])
e.stopPropagation()
}}
onMouseMove={(e) => {
e.stopPropagation()
editorManager.setHighlightRange([[obj?.start || 0, obj.end, true]])
editorManager.setHighlightRange([
topLevelRange(obj?.start || 0, obj.end),
])
}}
onClick={(e) => {
const range: [number, number, boolean] = [
obj?.start || 0,
obj.end || 0,
true,
]
const range = topLevelRange(obj?.start || 0, obj.end || 0)
const idInfo = codeToIdSelections([
{ codeRef: codeRefFromRange(range, kclManager.ast) },
])[0]

View File

@ -129,11 +129,13 @@ function CommandArgOptionInput({
<label
htmlFor="option-input"
className="capitalize px-2 py-1 rounded-l bg-chalkboard-100 dark:bg-chalkboard-80 text-chalkboard-10 border-b border-b-chalkboard-100 dark:border-b-chalkboard-80"
data-testid="cmd-bar-arg-name"
>
{argName}
</label>
<Combobox.Input
id="option-input"
data-testid="cmd-bar-arg-value"
ref={inputRef}
onChange={(event) =>
!event.target.disabled && setQuery(event.target.value)

View File

@ -22,6 +22,7 @@ export const CommandBar = () => {
// Close the command bar when navigating
useEffect(() => {
if (commandBarState.matches('Closed')) return
commandBarSend({ type: 'Close' })
}, [pathname])

View File

@ -17,7 +17,7 @@ import { StateFrom } from 'xstate'
const semanticEntityNames: {
[key: string]: Array<Artifact['type'] | 'defaultPlane'>
} = {
face: ['wall', 'cap', 'solid2D'],
face: ['wall', 'cap', 'solid2d'],
edge: ['segment', 'sweepEdge', 'edgeCutEdge'],
point: [],
plane: ['defaultPlane'],

View File

@ -4,6 +4,8 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
import { Command } from 'lib/commandTypes'
import { useEffect, useState } from 'react'
import { CustomIcon } from './CustomIcon'
import { getActorNextEvents } from 'lib/utils'
import { sortCommands } from 'lib/commandUtils'
function CommandComboBox({
options,
@ -18,8 +20,16 @@ function CommandComboBox({
const defaultOption =
options.find((o) => 'isCurrent' in o && o.isCurrent) || null
// sort disabled commands to the bottom
const sortedOptions = options
.map((command) => ({
command,
disabled: optionIsDisabled(command),
}))
.sort(sortCommands)
.map(({ command }) => command)
const fuse = new Fuse(options, {
const fuse = new Fuse(sortedOptions, {
keys: ['displayName', 'name', 'description'],
threshold: 0.3,
ignoreLocation: true,
@ -27,7 +37,7 @@ function CommandComboBox({
useEffect(() => {
const results = fuse.search(query).map((result) => result.item)
setFilteredOptions(query.length > 0 ? results : options)
setFilteredOptions(query.length > 0 ? results : sortedOptions)
}, [query])
function handleSelection(command: Command) {
@ -42,6 +52,7 @@ function CommandComboBox({
className="w-5 h-5 bg-primary/10 dark:bg-primary text-primary dark:text-inherit"
/>
<Combobox.Input
data-testid="cmd-bar-search"
onChange={(event) => setQuery(event.target.value)}
className="w-full bg-transparent focus:outline-none selection:bg-primary/20 dark:selection:bg-primary/40 dark:focus:outline-none"
onKeyDown={(event) => {
@ -73,7 +84,9 @@ function CommandComboBox({
<Combobox.Option
key={option.groupId + option.name + (option.displayName || '')}
value={option}
className="flex items-center gap-4 px-4 py-1.5 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90"
className="flex items-center gap-4 px-4 py-1.5 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90 ui-disabled:!text-chalkboard-50"
disabled={optionIsDisabled(option)}
data-testid={`cmd-bar-option`}
>
{'icon' in option && option.icon && (
<CustomIcon name={option.icon} className="w-5 h-5" />
@ -96,3 +109,11 @@ function CommandComboBox({
}
export default CommandComboBox
function optionIsDisabled(option: Command): boolean {
return (
'machineActor' in option &&
option.machineActor !== undefined &&
!getActorNextEvents(option.machineActor.getSnapshot()).includes(option.name)
)
}

View File

@ -538,6 +538,16 @@ const CustomIconMap = {
/>
</svg>
),
helix: (
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M12.3796 6.35525C10.6758 5.64945 8.44129 5.27796 6.92519 5.64172C6.15726 5.82597 5.7318 6.05228 5.55779 6.21295C5.76304 6.32354 6.2288 6.43945 7.03653 6.43302C7.87009 6.42638 8.9975 6.29045 10.4229 5.9501L10.6551 6.92275C9.17724 7.27564 7.9725 7.42559 7.04449 7.43298C6.14216 7.44017 5.42343 7.31395 4.98579 7.03617C4.75792 6.89153 4.53857 6.65945 4.50435 6.32695C4.47054 5.99852 4.63374 5.72683 4.81912 5.53684C5.17998 5.16702 5.83926 4.87389 6.69188 4.66932C8.48928 4.23806 10.9508 4.68095 12.7623 5.43139C13.669 5.80697 14.4784 6.28567 14.9739 6.82869C15.2234 7.10197 15.4238 7.42493 15.4827 7.78937C15.5448 8.1741 15.4392 8.54567 15.1831 8.86785C14.9896 9.11133 14.6502 9.31092 14.327 9.47089C14.1575 9.55477 13.9707 9.63785 13.7736 9.71907C14.257 9.99254 14.6732 10.2984 14.9739 10.6279C15.2234 10.9011 15.4238 11.2241 15.4827 11.5885C15.5448 11.9733 15.4392 12.3448 15.1831 12.667C14.9896 12.9105 14.6502 13.1101 14.327 13.2701C14.1575 13.3539 13.9707 13.437 13.7735 13.5182C14.3755 13.8587 14.8991 14.2636 15.2067 14.7211L14.3767 15.2789C14.1912 15.0029 13.8109 14.6842 13.2483 14.3702C13.0112 14.2378 12.7496 14.1107 12.4694 13.9913C11.8027 14.2087 11.1417 14.3953 10.6642 14.5188L10.6552 14.5212L10.6551 14.5211C9.17724 14.874 7.9725 15.0239 7.04449 15.0313C6.14216 15.0385 5.42343 14.9123 4.98579 14.6345C4.75792 14.4899 4.53857 14.2578 4.50435 13.9253C4.47054 13.5969 4.63374 13.3252 4.81912 13.1352C5.17998 12.7653 5.83926 12.4722 6.69188 12.2677C8.12302 11.9243 9.96538 12.1368 11.5511 12.6039C11.5872 12.6145 11.6233 12.6253 11.6593 12.6363L10.0638 13.2745C8.93153 13.0645 7.80454 13.0291 6.92519 13.2401C6.15727 13.4243 5.73181 13.6506 5.5578 13.8113C5.76305 13.9219 6.2288 14.0378 7.03653 14.0313C7.8692 14.0247 8.99509 13.8891 10.4183 13.5495C10.5419 13.5175 10.678 13.4812 10.8233 13.4412C10.8184 13.4399 10.8134 13.4387 10.8085 13.4374L12.6 12.9L12.5922 12.8948C12.6584 12.8718 12.7243 12.8485 12.7894 12.825C13.2047 12.6754 13.5845 12.5217 13.8834 12.3738C14.2059 12.2142 14.359 12.0967 14.4003 12.0448C14.4964 11.9239 14.509 11.832 14.4955 11.748C14.4786 11.6437 14.4094 11.4927 14.2353 11.302C13.8963 10.9305 13.2766 10.536 12.4694 10.1921C11.8027 10.4096 11.1417 10.5962 10.6642 10.7197L10.6552 10.722L10.6551 10.7219C9.17724 11.0748 7.9725 11.2248 7.04449 11.2322C6.14216 11.2393 5.42343 11.1131 4.98579 10.8353C4.75792 10.6907 4.53857 10.4586 4.50435 10.1261C4.47054 9.79768 4.63374 9.526 4.81912 9.33601C5.17998 8.96618 5.83926 8.67306 6.69188 8.46848C8.14467 8.11991 10.0313 8.34242 11.6579 8.83682L10.0624 9.47503C8.9375 9.26666 7.80922 9.22878 6.92519 9.44089C6.15726 9.62514 5.7318 9.85144 5.55779 10.0121C5.76304 10.1227 6.2288 10.2386 7.03653 10.2322C7.86921 10.2255 8.9951 10.0899 10.4183 9.75035C10.542 9.71834 10.6781 9.68201 10.8235 9.64197L10.8072 9.63784L12.6 9.1L12.593 9.09536C12.659 9.0724 12.7245 9.04921 12.7894 9.02583C13.2047 8.87627 13.5845 8.72256 13.8834 8.57464C14.2059 8.41505 14.359 8.29757 14.4003 8.24564C14.4964 8.1247 14.509 8.0328 14.4955 7.94882C14.4786 7.84455 14.4094 7.69357 14.2353 7.50279C13.8839 7.11769 13.2307 6.7078 12.3796 6.35525ZM5.47539 9.95537C5.47546 9.95536 5.47623 9.95615 5.47745 9.95779C5.47592 9.9562 5.47531 9.95538 5.47539 9.95537ZM5.49369 10.0846C5.49289 10.0866 5.49232 10.0876 5.49223 10.0876C5.49215 10.0877 5.49255 10.0866 5.49369 10.0846ZM5.47539 13.7545C5.47546 13.7545 5.47623 13.7553 5.47745 13.757C5.47592 13.7554 5.47531 13.7546 5.47539 13.7545ZM5.49369 13.8838C5.49289 13.8858 5.49232 13.8868 5.49223 13.8868C5.49215 13.8868 5.49255 13.8858 5.49369 13.8838ZM5.47539 6.1562C5.47546 6.15619 5.47623 6.15698 5.47745 6.15862C5.47592 6.15704 5.47531 6.15622 5.47539 6.1562ZM5.49369 6.28544C5.49289 6.28746 5.49232 6.28848 5.49223 6.28848C5.49215 6.28849 5.49255 6.28748 5.49369 6.28544Z"
fill="currentColor"
/>
</svg>
),
hole: (
<svg
viewBox="0 0 20 20"

View File

@ -1,10 +1,7 @@
import { useMemo } from 'react'
import { engineCommandManager } from 'lib/singletons'
import {
ArtifactGraph,
expandPlane,
PlaneArtifactRich,
} from 'lang/std/artifactGraph'
import { expandPlane, PlaneArtifactRich } from 'lang/std/artifactGraph'
import { ArtifactGraph } from 'lang/wasm'
import { DebugDisplayArray, GenericObj } from './DebugDisplayObj'
export function DebugFeatureTree() {

View File

@ -48,8 +48,9 @@ export const FileMachineProvider = ({
}) => {
const navigate = useNavigate()
const { commandBarSend } = useCommandsContext()
const { settings } = useSettingsAuthContext()
const { project, file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const { settings, auth } = useSettingsAuthContext()
const projectData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
const { project, file } = projectData
const [kclSamples, setKclSamples] = React.useState<KclSamplesManifestItem[]>(
[]
)
@ -57,7 +58,9 @@ export const FileMachineProvider = ({
useEffect(() => {
markOnce('code/didLoadFile')
async function fetchKclSamples() {
setKclSamples(await getKclSamplesManifest())
const manifest = await getKclSamplesManifest()
const filteredFiles = manifest.filter((file) => !file.multipleFiles)
setKclSamples(filteredFiles)
}
fetchKclSamples().catch(reportError)
}, [])
@ -294,8 +297,14 @@ export const FileMachineProvider = ({
const kclCommandMemo = useMemo(
() =>
kclCommands(
async (data) => {
kclCommands({
authToken: auth?.context?.token ?? '',
projectData,
settings: {
defaultUnit: settings?.context?.modeling.defaultUnit.current ?? 'mm',
},
specialPropsForSampleCommand: {
onSubmit: async (data) => {
if (data.method === 'overwrite') {
codeManager.updateCodeStateEditor(data.code)
await kclManager.executeCode(true)
@ -323,11 +332,12 @@ export const FileMachineProvider = ({
})
}
},
kclSamples.map((sample) => ({
value: sample.file,
providedOptions: kclSamples.map((sample) => ({
value: sample.pathFromProjectDirectoryToFirstFile,
name: sample.title,
}))
).filter(
})),
},
}).filter(
(command) => kclSamples.length || command.name !== 'open-kcl-example'
),
[codeManager, kclManager, send, kclSamples]

View File

@ -148,6 +148,7 @@ function HelpMenuItem({
return (
<li className="p-0 m-0">
{as === 'a' ? (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<a
{...(props as React.ComponentProps<'a'>)}
onClick={openExternalBrowserIfDesktop(

View File

@ -111,7 +111,7 @@ export const ModelingMachineProvider = ({
auth,
settings: {
context: {
app: { theme, enableSSAO },
app: { theme, enableSSAO, allowOrbitInSketchMode },
modeling: {
defaultUnit,
cameraProjection,
@ -121,6 +121,7 @@ export const ModelingMachineProvider = ({
},
},
} = useSettingsAuthContext()
const previousAllowOrbitInSketchMode = useRef(allowOrbitInSketchMode.current)
const navigate = useNavigate()
const { context, send: fileMachineSend } = useFileContext()
const { file } = useLoaderData() as IndexLoaderData
@ -157,12 +158,10 @@ export const ModelingMachineProvider = ({
'enable copilot': () => {
editorManager.setCopilotEnabled(true)
},
// tsc reports this typing as perfectly fine, but eslint is complaining.
// It's actually nonsensical, so I'm quieting.
// eslint-disable-next-line @typescript-eslint/no-misused-promises
'sketch exit execute': async ({
context: { store },
}): Promise<void> => {
'sketch exit execute': ({ context: { store } }) => {
// TODO: Remove this async callback. For some reason eslint wouldn't
// let me disable @typescript-eslint/no-misused-promises for the line.
;(async () => {
// When cancelling the sketch mode we should disable sketch mode within the engine.
await engineCommandManager.sendSceneCommand({
type: 'modeling_cmd_req',
@ -190,6 +189,7 @@ export const ModelingMachineProvider = ({
})
})
.catch(reportRejection)
})().catch(reportRejection)
},
'Set mouse state': assign(({ context, event }) => {
if (event.type !== 'Set mouse state') return {}
@ -271,6 +271,7 @@ export const ModelingMachineProvider = ({
cmd_id: uuidv4(),
cmd: {
type: 'default_camera_center_to_selection',
camera_movement: 'vantage',
},
})
.catch(reportRejection)
@ -634,7 +635,8 @@ export const ModelingMachineProvider = ({
input.plane
)
await kclManager.updateAst(modifiedAst, false)
sceneInfra.camControls.enableRotate = false
sceneInfra.camControls.enableRotate =
sceneInfra.camControls._setting_allowOrbitInSketchMode
sceneInfra.camControls.syncDirection = 'clientToEngine'
await letEngineAnimateAndSyncCamAfter(
@ -647,6 +649,7 @@ export const ModelingMachineProvider = ({
zAxis: input.zAxis,
yAxis: input.yAxis,
origin: [0, 0, 0],
animateTargetId: input.planeId,
}
}),
'animate-to-sketch': fromPromise(
@ -671,6 +674,7 @@ export const ModelingMachineProvider = ({
origin: info.sketchDetails.origin.map(
(a) => a / sceneInfra._baseUnitMultiplier
) as [number, number, number],
animateTargetId: info?.sketchDetails?.faceId || '',
}
}
),
@ -1188,6 +1192,41 @@ export const ModelingMachineProvider = ({
}
}, [engineCommandManager.engineConnection, modelingSend])
useEffect(() => {
// Only trigger this if the state actually changes, if it stays the same do not reload the camera
if (
previousAllowOrbitInSketchMode.current === allowOrbitInSketchMode.current
) {
//no op
previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
return
}
const inSketchMode = modelingState.matches('Sketch')
// If you are in sketch mode and you disable the orbit, return back to the normal view to the target
if (!allowOrbitInSketchMode.current) {
const targetId = modelingState.context.sketchDetails?.animateTargetId
if (inSketchMode && targetId) {
letEngineAnimateAndSyncCamAfter(engineCommandManager, targetId)
.then(() => {})
.catch((e) => {
console.error(
'failed to sync engine and client scene after disabling allow orbit in sketch mode'
)
console.error(e)
})
}
}
// While you are in sketch mode you should be able to control the enable rotate
// Once you exit it goes back to normal
if (inSketchMode) {
sceneInfra.camControls.enableRotate = allowOrbitInSketchMode.current
}
previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
}, [allowOrbitInSketchMode])
// Allow using the delete key to delete solids
useHotkeys(['backspace', 'delete', 'del'], () => {
modelingSend({ type: 'Delete selection' })

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