Compare commits

...

36 Commits

Author SHA1 Message Date
7ca51be5bc Hook react-router-dom into XState in one location 2025-04-08 13:23:53 -04:00
0bb5797377 Fix unclickable state while opening share link in browser (#6201)
* Fix unclickable state, don't show warning if query present

* Leave a note about need for a web test

* Fix browser share links by waiting for network connection

* Don't worry about engineConnection on home route
2025-04-08 13:10:49 -04:00
c3097aa334 fix missing extension (#6205)
* fix missing extension

* fix e2e

* better name
2025-04-08 15:41:48 +00:00
2cd0fcc9a7 #6157 Dispatch wheel event to camControls when hovering segment label (#6158)
dispatch wheel event to camControls when hovering segment label
2025-04-08 11:12:12 -04:00
5b653fb558 Change unit conversion functions to operate on input rather than return a conversion factor (#6181)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-08 02:21:23 +00:00
6a5b23f848 Bump the minor group with 7 updates (#6191)
Bumps the minor group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [three](https://github.com/mrdoob/three.js) | `0.174.0` | `0.175.0` |
| [@types/three](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/three) | `0.174.0` | `0.175.0` |
| [@electron-forge/cli](https://github.com/electron/forge) | `7.7.0` | `7.8.0` |
| [@electron-forge/plugin-fuses](https://github.com/electron/forge) | `7.7.0` | `7.8.0` |
| [@electron-forge/plugin-vite](https://github.com/electron/forge/tree/HEAD/packages/plugin/vite) | `7.7.0` | `7.8.0` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.13.14` | `22.14.0` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.26.1` | `8.29.0` |


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

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

Updates `@electron-forge/cli` from 7.7.0 to 7.8.0
- [Release notes](https://github.com/electron/forge/releases)
- [Changelog](https://github.com/electron/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/electron/forge/compare/v7.7.0...v7.8.0)

Updates `@electron-forge/plugin-fuses` from 7.7.0 to 7.8.0
- [Release notes](https://github.com/electron/forge/releases)
- [Changelog](https://github.com/electron/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/electron/forge/compare/v7.7.0...v7.8.0)

Updates `@electron-forge/plugin-vite` from 7.7.0 to 7.8.0
- [Release notes](https://github.com/electron/forge/releases)
- [Changelog](https://github.com/electron/forge/blob/main/CHANGELOG.md)
- [Commits](https://github.com/electron/forge/commits/v7.8.0/packages/plugin/vite)

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

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

Updates `typescript-eslint` from 8.26.1 to 8.29.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.29.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: three
  dependency-version: 0.175.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@types/three"
  dependency-version: 0.175.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@electron-forge/cli"
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@electron-forge/plugin-fuses"
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@electron-forge/plugin-vite"
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@types/node"
  dependency-version: 22.14.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: "@types/three"
  dependency-version: 0.175.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
- dependency-name: typescript-eslint
  dependency-version: 8.29.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 22:24:57 +00:00
a480783ee8 Quick app rename typo fix in settings.md (#6198) 2025-04-07 21:09:27 +00:00
bc0f5b5787 Add point-and-click Insert from local project files (#6129)
* WIP: Add point-and-click Import for geometry
Will eventually fix #6120
Right now the whole loop is there but the codemod doesn't work yet

* Better pathToNOde, log on non-working cm dispatch call

* Add workaround to updateModelingState not working

* Back to updateModelingState with a skip flag

* Better todo

* Change working from Import to Insert, cleanups

* Sister command in kclCommands to populate file options

* Improve path selector

* Unsure: move importAstMod to kclCommands onSubmit 😶

* Add e2e test

* Clean up for review

* Add native file menu entry and test

* No await yo lint said so

* @lrev-Dev's suggestion to remove a comment

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

* Update to scene.settled(cmdBar)

* Lint

---------

Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
2025-04-07 20:28:11 +00:00
962eb0e376 Install and start Vector on macOS CI runners (#6147)
* Install vector on macOS

* Include platform information
2025-04-07 20:22:27 +00:00
ababe24b97 Implement polar std function in KCL (#6180)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-07 15:16:43 -05:00
1bf7a2abd4 Bump typescript from 5.8.2 to 5.8.3 in /packages/codemirror-lsp-client in the patch group (#6188)
Bump typescript in /packages/codemirror-lsp-client in the patch group

Bumps the patch group in /packages/codemirror-lsp-client with 1 update: [typescript](https://github.com/microsoft/TypeScript).


Updates `typescript` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 20:12:36 +00:00
0ea4f94e8f Bump @types/node from 22.13.13 to 22.14.0 in /packages/codemirror-lsp-client in the minor group (#6189)
Bump @types/node in /packages/codemirror-lsp-client in the minor group

Bumps the minor group in /packages/codemirror-lsp-client with 1 update: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node).


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

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 22.14.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 17:50:09 +00:00
6cc6130b6a Bump the major group in /packages/codemirror-lang-kcl with 2 updates (#6194)
Bumps the major group in /packages/codemirror-lang-kcl with 2 updates: [vite-tsconfig-paths](https://github.com/aleclarson/vite-tsconfig-paths) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `vite-tsconfig-paths` from 4.3.2 to 5.1.4
- [Release notes](https://github.com/aleclarson/vite-tsconfig-paths/releases)
- [Commits](https://github.com/aleclarson/vite-tsconfig-paths/compare/v4.3.2...v5.1.4)

Updates `vitest` from 2.1.9 to 3.1.1
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v3.1.1/packages/vitest)

---
updated-dependencies:
- dependency-name: vite-tsconfig-paths
  dependency-version: 5.1.4
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: major
- dependency-name: vitest
  dependency-version: 3.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 17:44:10 +00:00
8294903cd0 Bump taiki-e/install-action from 2.49.30 to 2.49.45 in the patch group (#6185)
Bumps the patch group with 1 update: [taiki-e/install-action](https://github.com/taiki-e/install-action).


Updates `taiki-e/install-action` from 2.49.30 to 2.49.45
- [Release notes](https://github.com/taiki-e/install-action/releases)
- [Commits](https://github.com/taiki-e/install-action/compare/v2.49.30...v2.49.45)

---
updated-dependencies:
- dependency-name: taiki-e/install-action
  dependency-version: 2.49.45
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 17:43:36 +00:00
7b7379c3dd Bump the patch group with 6 updates (#6186)
Bumps the patch group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@kittycad/lib](https://github.com/KittyCAD/kittycad.ts) | `2.0.26` | `2.0.28` |
| [@lezer/generator](https://github.com/lezer-parser/generator) | `1.7.2` | `1.7.3` |
| [@types/wicg-file-system-access](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/wicg-file-system-access) | `2023.10.5` | `2023.10.6` |
| [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) | `8.18.0` | `8.18.1` |
| [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) | `7.37.4` | `7.37.5` |
| [typescript](https://github.com/microsoft/TypeScript) | `5.8.2` | `5.8.3` |


Updates `@kittycad/lib` from 2.0.26 to 2.0.28
- [Release notes](https://github.com/KittyCAD/kittycad.ts/releases)
- [Commits](https://github.com/KittyCAD/kittycad.ts/compare/v2.0.26...v2.0.28)

Updates `@lezer/generator` from 1.7.2 to 1.7.3
- [Changelog](https://github.com/lezer-parser/generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lezer-parser/generator/compare/1.7.2...1.7.3)

Updates `@types/wicg-file-system-access` from 2023.10.5 to 2023.10.6
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/wicg-file-system-access)

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

Updates `eslint-plugin-react` from 7.37.4 to 7.37.5
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.37.4...v7.37.5)

Updates `typescript` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: "@kittycad/lib"
  dependency-version: 2.0.28
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: "@lezer/generator"
  dependency-version: 1.7.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: "@types/wicg-file-system-access"
  dependency-version: 2023.10.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: "@types/ws"
  dependency-version: 8.18.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: eslint-plugin-react
  dependency-version: 7.37.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 17:37:29 +00:00
9acdf1e42f Bump the patch group in /rust/kcl-language-server with 3 updates (#6183)
Bumps the patch group in /rust/kcl-language-server with 3 updates: [@vscode/vsce](https://github.com/Microsoft/vsce), [esbuild](https://github.com/evanw/esbuild) and [typescript](https://github.com/microsoft/TypeScript).


Updates `@vscode/vsce` from 3.3.0 to 3.3.2
- [Release notes](https://github.com/Microsoft/vsce/releases)
- [Commits](https://github.com/Microsoft/vsce/compare/v3.3.0...v3.3.2)

Updates `esbuild` from 0.25.1 to 0.25.2
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.1...v0.25.2)

Updates `typescript` from 5.8.2 to 5.8.3
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/commits)

---
updated-dependencies:
- dependency-name: "@vscode/vsce"
  dependency-version: 3.3.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: esbuild
  dependency-version: 0.25.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: typescript
  dependency-version: 5.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 17:03:31 +00:00
5dd95d27de Bump the patch group in /packages/codemirror-lang-kcl with 2 updates (#6193)
Bumps the patch group in /packages/codemirror-lang-kcl with 2 updates: [@codemirror/state](https://github.com/codemirror/state) and [@lezer/generator](https://github.com/lezer-parser/generator).


Updates `@codemirror/state` from 6.5.0 to 6.5.2
- [Changelog](https://github.com/codemirror/state/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codemirror/state/compare/6.5.0...6.5.2)

Updates `@lezer/generator` from 1.7.2 to 1.7.3
- [Changelog](https://github.com/lezer-parser/generator/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lezer-parser/generator/compare/1.7.2...1.7.3)

---
updated-dependencies:
- dependency-name: "@codemirror/state"
  dependency-version: 6.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patch
- dependency-name: "@lezer/generator"
  dependency-version: 1.7.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 16:48:48 +00:00
1016b4c879 Remove unnecessary timeouts waiting for command bar (#6199) 2025-04-07 16:46:16 +00:00
df6f571294 Stream handling / Stream idle mode v2; a ton of network related changes (ping; scene indicator -> stream indicator, stream resizing (even on pause)) (#5312)
* Add back stream idle mode

* Shut up codespell

* Correct serialization; only expose at user level

* cargo fmt

* tsc lint fmt

* Move engineStreamMachine as a global actor; tons of more work

* Fix up everything after bumping kittycad/lib

* Remove camera sync

* Use pause/play iconology

* Add back better ping indicator

* wip

* Fix streamIdleMode checkbox being wonky

* yarn fmt

* Massive extinction event for waitForExecutionDone; try to stop projects view switching from crashing

* Clear diagnostics when unmounting code editor!

* wip

* Rework initial root projects dir + deflake many projects tests

* More e2e fixes

* Deflake revolve some revolve tests

* Fix the rest of the mfing tests

* yarn fmt

* yarn lint

* yarn tsc

* Fix tsc after rebase

* wip

* less flaky point and click

* wip

* Fixup after rebase

* Fix more tests

* Fix 2 more

* Fix up named-views tests

* yarn fmt lint tsc

* Fix up new changes

* Get rid of 1 cyclic dependency

* Fix another cyclic mfer!

* fmt

* fmt tsc

* Fix zoom to fit being frigged

* a new list of circular deps

* Remove NetworkHealthIndicator test that was shit

* Fix the bad reload repeat issue kevin started on

* Fix zoom to fit at the right moments...

* Fix cache count numbers in editor test

* Remove a test race - poll window info.

* Qualify fail function

* Try something

* Use scene.connectionEstablished

* Hopefully fix snapshots at least

* Add app console.log

* Fix native menu tests more

* tsc lint

* Fix camera failure

* Try again

* Test attempt number 15345203, action!

* Add back old window detection heuristic

* Remove firstWindow to complete the work of 2342d04fe2

* Tweak some tests for MacOS

* Tweak "set appearance" test for MacOS

Revert this if it messes up any other platform's color checks!

* Are you serious? This was all that needed formatting?

* More color tweaks

Local MacOS and CI MacOS don't agree

* Fixes on apperance e2e test for stream idle branch (#6168)

pierremtb/stream-idle-revamp-appearance-fixes

* Another apperance fix

* Skip one native menu test to make stream idle green (#6169)

* pierremtb/stream-idle-revamp-more-fixes

* Fix lint

* Update snapshot for test_generate_settings_docs

---------

Co-authored-by: lee-at-zoo-corp <lee@zoo.dev>
Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
Co-authored-by: Pierre Jacquier <pierrejacquier39@gmail.com>
Co-authored-by: Pierre Jacquier <pierre@zoo.dev>
2025-04-07 07:08:31 -04:00
be05dd7ba1 More propagation of numeric types (#6177)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-07 19:02:41 +12:00
bc22d888ee Apply type-directed coercions to arguments in calls of user functions (#6179)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-07 18:02:46 +12:00
e6ae89ebf9 Erase comment start positions from snapshot tests (#6178)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-07 17:42:15 +12:00
e7b23e1638 Implement coercion of numeric types for ascription and arithmetic (off by default) (#6175)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-07 16:13:15 +12:00
ce7a967f5f Reduce the number of reps in the add_lots test (#6174)
Signed-off-by: Nick Cameron <nrc@ncameron.org>
2025-04-06 22:41:48 -04:00
38446b5b2a take things off the batch in a more safe way (#6171)
Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-06 03:54:32 +00:00
48e1a8ed02 attempt to import win-ca on windows (#6136)
* attempt to import win-ca on windows

otherwise we won't see system x509 cert authorities, which leaves people
high and dry if they're using an enterprise mitm tls box (😢)
2025-04-05 16:30:48 +00:00
a059166b9c Upgrade e2e-tests windows runner from 4 cores to 8 (#6166)
* Change e2e-tests runner to windows-latest-8-cores

* Clean up for PR
2025-04-05 08:44:50 -07:00
086a2b851d Follow-up fixes after bearing sample rename (#6164) 2025-04-05 11:00:47 +00:00
8e4c5fb24d Add test for #5799: "Only showing axis planes when there are no errors" (#6007)
* first pass at adding test for Only showing axis planes when there are no errors

* fix test Only show axis planes when there are no errors

* PR feedback
2025-04-04 23:41:09 +02:00
6993893600 Wait for export button to make test more reliable (#6143) 2025-04-04 16:53:57 -04:00
bfdf8babed sketching on a mirror2d thats been extruded fixed! (#6149)
* updates

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

* snap

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

* fixes

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

* add sample

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>

* fixes

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

* snap

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

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2025-04-04 12:55:21 -07:00
4d31fb890d Bump vite from 5.4.16 to 5.4.17 in /packages/codemirror-lang-kcl in the security group (#6150)
Bump vite in /packages/codemirror-lang-kcl in the security group

Bumps the security group in /packages/codemirror-lang-kcl with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.16 to 5.4.17
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.17/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.17/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.17
  dependency-type: indirect
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 18:57:20 +00:00
ef451fd8f7 Bump vite from 5.4.16 to 5.4.17 in the security group (#6151)
Bumps the security group with 1 update: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 5.4.16 to 5.4.17
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.17/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.17/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.17
  dependency-type: direct:development
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-04 18:40:35 +00:00
656eb0abec Update all KCL-Samples to be more ME friendly (#6132)
* update all kcl-samples

* updates

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

* fixes

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

* updates

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

* updates

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

* Update kcl-samples simulation test output

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-04-04 11:03:13 -07:00
a7896329f7 Shorten feedback cycle for legitimate failures (#6146)
Stop sooner with legitimate failures
2025-04-04 17:29:29 +00:00
b9e11ac201 Remove the camera projection toggle from the UI (#6077)
* Remove E2E test behavior for projection toggle UI

Even though the test is `fixme`'d this should make it easier to
ressurect. The test is still flaky but it runs now.

* Remove projection toggle from the UI
2025-04-04 16:41:56 +00:00
494 changed files with 64800 additions and 64287 deletions

View File

@ -1,3 +1,3 @@
[codespell]
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,atleast,ue,afterall,ser,fromM,FromM
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,./public/kcl-samples,./rust/kcl-lib/tests/kcl_samples,tsconfig.tsbuildinfo

24
.github/ci-cd-scripts/start-vector-macos.sh vendored Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
set -euo pipefail
# Install vector
brew tap vectordotdev/brew && brew install vector
# Configure vector
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i '' "s#OS_NAME#${OS_NAME}#g" /tmp/vector.toml
sed -i '' "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i '' "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i '' "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i '' "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i '' "s#GH_ACTIONS_AXIOM_TOKEN#${GH_ACTIONS_AXIOM_TOKEN}#g" /tmp/vector.toml
# Display settings
echo
echo 'Vector config:'
cat /tmp/vector.toml
echo
# Start in the background
$(brew --prefix)/opt/vector/bin/vector --config /tmp/vector.toml &

24
.github/ci-cd-scripts/start-vector-ubuntu.sh vendored Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
set -euo pipefail
# Install vector
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev | bash -s -- -y
# Configure vector
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i "s#OS_NAME#${OS_NAME}#g" /tmp/vector.toml
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${GH_ACTIONS_AXIOM_TOKEN}#g" /tmp/vector.toml
# Display settings
echo
echo 'Vector config:'
cat /tmp/vector.toml
echo
# Start in background
${HOME}/.vector/bin/vector --config /tmp/vector.toml &

View File

@ -24,7 +24,7 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache: false # Configured below.
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with:
tool: wasm-pack
- name: Rust Cache

View File

@ -77,7 +77,7 @@ jobs:
with:
cache: false # Configured below.
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
with:
tool: wasm-pack

View File

@ -34,20 +34,11 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
cache: false # Configured below.
- name: Install vector
run: |
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh
/tmp/vector.sh -y -no-modify-path
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
cat /tmp/vector.toml
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- name: Start Vector
run: .github/ci-cd-scripts/start-vector-ubuntu.sh
env:
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
OS_NAME: ${{ env.OS_NAME }}
- uses: taiki-e/install-action@cargo-llvm-cov
- uses: taiki-e/install-action@nextest
- name: Install just

View File

@ -140,7 +140,7 @@ jobs:
with:
cache: false # Configured below.
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
with:
tool: wasm-pack
@ -281,7 +281,7 @@ jobs:
os:
- "runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64"
- namespace-profile-macos-8-cores
- windows-latest
- windows-latest-8-cores
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
# Disable macos and windows tests on hourly e2e tests since we only care
@ -292,7 +292,7 @@ jobs:
exclude:
- os: namespace-profile-macos-8-cores
isScheduled: true
- os: windows-latest
- os: windows-latest-8-cores
isScheduled: true
# TODO: add ref here for main and latest release tag
runs-on: ${{ matrix.os }}
@ -339,22 +339,12 @@ jobs:
if: needs.conditions.outputs.should-run == 'true'
run: yarn tronb:vite:dev
- name: Install vector
if: ${{ needs.conditions.outputs.should-run == 'true' && contains(matrix.os, 'ubuntu') }}
shell: bash
run: |
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh
/tmp/vector.sh -y -no-modify-path
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
cat /tmp/vector.toml
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- name: Start Vector
if: ${{ needs.conditions.outputs.should-run == 'true' && !contains(matrix.os, 'windows') }}
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
env:
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
OS_NAME: ${{ env.OS_NAME }}
- uses: actions/download-artifact@v4
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
@ -370,8 +360,8 @@ jobs:
with:
shell: bash
command: .github/ci-cd-scripts/playwright-electron.sh ${{matrix.shardIndex}} ${{matrix.shardTotal}} ${{ env.OS_NAME }}
timeout_minutes: 45
max_attempts: 15
timeout_minutes: 30
max_attempts: 9
env:
FAIL_ON_CONSOLE_ERRORS: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}

View File

@ -51,7 +51,7 @@ jobs:
with:
cache: false # Configured below.
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with:
tool: wasm-pack
@ -191,7 +191,7 @@ jobs:
cache: 'yarn'
- run: yarn install
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with:
tool: wasm-pack
@ -236,7 +236,7 @@ jobs:
cache: 'yarn'
- run: yarn install
- uses: taiki-e/install-action@37bdc826eaedac215f638a96472df572feab0f9b
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
with:
tool: wasm-pack

View File

@ -8,6 +8,7 @@ include = ["/tmp/github-actions.log"]
type = "remap"
inputs = [ "github-actions-file" ]
source = '''
.platform = "OS_NAME"
.action = "GITHUB_WORKFLOW"
.repo = "GITHUB_REPOSITORY"
.sha = "GITHUB_SHA"

View File

@ -18,7 +18,7 @@ std::math::PI: number = 3.14159265358979323846264338327950288_
circumference = 70
exampleSketch = startSketchOn(XZ)
|> circle(center = [0, 0], radius = circumference/ (2 * PI))
|> circle(center = [0, 0], radius = circumference / (2 * PI))
example = extrude(exampleSketch, length = 5)
```

45
docs/kcl/fromCm.md Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -65,11 +65,15 @@ layout: manual
* [`chamfer`](kcl/chamfer)
* [`circleThreePoint`](kcl/circleThreePoint)
* [`close`](kcl/close)
* [`cm`](kcl/cm)
* [`extrude`](kcl/extrude)
* [`fillet`](kcl/fillet)
* [`floor`](kcl/floor)
* [`ft`](kcl/ft)
* [`fromCm`](kcl/fromCm)
* [`fromFt`](kcl/fromFt)
* [`fromInches`](kcl/fromInches)
* [`fromM`](kcl/fromM)
* [`fromMm`](kcl/fromMm)
* [`fromYd`](kcl/fromYd)
* [`getCommonEdge`](kcl/getCommonEdge)
* [`getNextAdjacentEdge`](kcl/getNextAdjacentEdge)
* [`getOppositeEdge`](kcl/getOppositeEdge)
@ -77,7 +81,6 @@ layout: manual
* [`helix`](kcl/std-helix)
* [`hole`](kcl/hole)
* [`hollow`](kcl/hollow)
* [`inch`](kcl/inch)
* [`lastSegX`](kcl/lastSegX)
* [`lastSegY`](kcl/lastSegY)
* [`legAngX`](kcl/legAngX)
@ -89,11 +92,9 @@ layout: manual
* [`log`](kcl/log)
* [`log10`](kcl/log10)
* [`log2`](kcl/log2)
* [`m`](kcl/m)
* [`map`](kcl/map)
* [`max`](kcl/max)
* [`min`](kcl/min)
* [`mm`](kcl/mm)
* [`offsetPlane`](kcl/offsetPlane)
* [`patternCircular2d`](kcl/patternCircular2d)
* [`patternCircular3d`](kcl/patternCircular3d)
@ -101,7 +102,6 @@ layout: manual
* [`patternLinear3d`](kcl/patternLinear3d)
* [`patternTransform`](kcl/patternTransform)
* [`patternTransform2d`](kcl/patternTransform2d)
* [`polar`](kcl/polar)
* [`polygon`](kcl/polygon)
* [`pop`](kcl/pop)
* [`pow`](kcl/pow)
@ -137,12 +137,12 @@ layout: manual
* [`translate`](kcl/translate)
* [`xLine`](kcl/xLine)
* [`yLine`](kcl/yLine)
* [`yd`](kcl/yd)
* **std::math**
* [`E`](kcl/consts/std-math-E)
* [`PI`](kcl/consts/std-math-PI)
* [`TAU`](kcl/consts/std-math-TAU)
* [`cos`](kcl/std-math-cos)
* [`polar`](kcl/std-math-polar)
* [`sin`](kcl/std-math-sin)
* [`tan`](kcl/std-math-tan)
* **std::sketch**

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@ layout: manual
# KCL Settings
There are three levels of settings available in the KittyCAD Design Studiolication:
There are three levels of settings available in Zoo Design Studio:
1. [User Settings](/docs/kcl/settings/user): Global settings that apply to all projects, stored in `user.toml`
2. [Project Settings](/docs/kcl/settings/project): Settings specific to a project, stored in `project.toml`
@ -14,7 +14,7 @@ There are three levels of settings available in the KittyCAD Design Studiolicati
## Configuration Files
The KittyCAD Design Studio uses TOML files for configuration:
Zoo Design Studio uses TOML files for configuration:
* **User Settings**: `user.toml` - See [complete documentation](/docs/kcl/settings/user)
* **Project Settings**: `project.toml` - See [complete documentation](/docs/kcl/settings/project)

View File

@ -96,7 +96,7 @@ Permanently dismiss the banner warning to download the desktop app. This setting
##### stream_idle_mode
When the user is idle, and this is true, the stream will be torn down.
When the user is idle, teardown the stream after some time.
**Default:** None

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -79599,34 +79599,6 @@
"exampleSketch = startSketchOn(-XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [10, 0])\n |> line(end = [0, 10])\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
]
},
{
"name": "cm",
"summary": "Centimeters conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to centimeters.\n\nFor example, if the current project uses inches, this function will return `0.393701`. If the current project uses millimeters, this function will return `10`. If the current project uses centimeters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * cm()` is more readable that your intent is \"I want 10 centimeters\" than `10 * 10`, if the project settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * cm()"
]
},
{
"name": "e",
"summary": "Return the value of Eulers number `e`.",
@ -97490,14 +97462,28 @@
]
},
{
"name": "ft",
"summary": "Feet conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to feet.\n\nFor example, if the current project uses inches, this function will return `12`. If the current project uses millimeters, this function will return `304.8`. If the current project uses feet, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * ft()` is more readable that your intent is \"I want 10 feet\" than `10 * 304.8`, if the project settings are in millimeters.",
"name": "fromCm",
"summary": "Converts a number from centimeters to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in centimeters.\n\nFor example, if the current file uses inches, `fromCm(1)` will return `0.393701`. If the current file uses millimeters, `fromCm(1)` will return `10`. If the current file uses centimeters, `fromCm(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromCm(10)` is more readable that your intent is \"I want 10 centimeters\" than `10 * 10`, if the file settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
@ -97514,7 +97500,217 @@
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * ft()"
"totalWidth = fromCm(10)"
]
},
{
"name": "fromFt",
"summary": "Converts a number from feet to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in feet.\n\nFor example, if the current file uses inches, `fromFt(1)` will return `12`. If the current file uses millimeters, `fromFt(1)` will return `304.8`. If the current file uses feet, `fromFt(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromFt(10)` is more readable that your intent is \"I want 10 feet\" than `10 * 304.8`, if the file settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = fromFt(10)"
]
},
{
"name": "fromInches",
"summary": "Converts a number from inches to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in inches.\n\nFor example, if the current file uses inches, `fromInches(1)` will return `1`. If the current file uses millimeters, `fromInches(1)` will return `25.4`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromInches(10)` is more readable that your intent is \"I want 10 inches\" than `10 * 25.4`, if the file settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = fromInches(10)"
]
},
{
"name": "fromM",
"summary": "Converts a number from meters to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in meters.\n\nFor example, if the current file uses inches, `fromM(1)` will return `39.3701`. If the current file uses millimeters, `fromM(1)` will return `1000`. If the current file uses meters, `fromM(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromM(10)` is more readable that your intent is \"I want 10 meters\" than `10 * 1000`, if the file settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * fromM(10)"
]
},
{
"name": "fromMm",
"summary": "Converts a number from mm to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in millimeters.\n\nFor example, if the current file uses inches, `fromMm(1)` will return `1/25.4`. If the current file uses millimeters, `fromMm(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromMm(10)` is more readable that your intent is \"I want 10 millimeters\" than `10 * (1/25.4)`, if the file settings are in inches.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = fromMm(10)"
]
},
{
"name": "fromYd",
"summary": "Converts a number from yards to the current default unit.",
"description": "No matter what units the current file uses, this function will always return a number equivalent to the input in yards.\n\nFor example, if the current file uses inches, `fromYd(1)` will return `36`. If the current file uses millimeters, `fromYd(1)` will return `914.4`. If the current file uses yards, `fromYd(1)` will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the file settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `fromYd(10)` is more readable that your intent is \"I want 10 yards\" than `10 * 914.4`, if the file settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [
{
"name": "input",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = fromYd(10)"
]
},
{
@ -106369,34 +106565,6 @@
"import height, buildSketch from \"common.kcl\"\n\nplane = XZ\nmargin = 2\ns1 = buildSketch(plane, [0, 0])\ns2 = buildSketch(plane, [0, height() + margin])"
]
},
{
"name": "inch",
"summary": "Inches conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to inches.\n\nFor example, if the current project uses inches, this function will return `1`. If the current project uses millimeters, this function will return `25.4`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * inch()` is more readable that your intent is \"I want 10 inches\" than `10 * 25.4`, if the project settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * inch()"
]
},
{
"name": "int",
"summary": "Convert a number to an integer.",
@ -111321,7 +111489,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -113005,7 +113173,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -134361,34 +134529,6 @@
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = [log2(100), 0])\n |> line(end = [5, 8])\n |> line(end = [-10, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{
"name": "m",
"summary": "Meters conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to meters.\n\nFor example, if the current project uses inches, this function will return `39.3701`. If the current project uses millimeters, this function will return `1000`. If the current project uses meters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * m()` is more readable that your intent is \"I want 10 meters\" than `10 * 1000`, if the project settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * m()"
]
},
{
"name": "map",
"summary": "Apply a function to every element of a list.",
@ -141853,34 +141993,6 @@
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> angledLine({\n angle = 70,\n length = min(15, 31, 4, 13, 22)\n }, %)\n |> line(end = [20, 0])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{
"name": "mm",
"summary": "Millimeters conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to millimeters.\n\nFor example, if the current project uses inches, this function will return `(1/25.4)`. If the current project uses millimeters, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * mm()` is more readable that your intent is \"I want 10 millimeters\" than `10 * (1/25.4)`, if the project settings are in inches.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * mm()"
]
},
{
"name": "offsetPlane",
"summary": "Offset a plane by a distance along its normal.",
@ -201537,76 +201649,6 @@
"circumference = 70\n\nexampleSketch = startSketchOn(XZ)\n |> circle(center = [0, 0], radius = circumference / (2 * pi()))\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{
"name": "polar",
"summary": "Convert polar/sphere (azimuth, elevation, distance) coordinates to cartesian (x/y/z grid) coordinates.",
"description": "",
"tags": [],
"keywordArguments": false,
"args": [
{
"name": "data",
"type": "PolarCoordsData",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "PolarCoordsData",
"description": "Data for polar coordinates.",
"type": "object",
"required": [
"angle",
"length"
],
"properties": {
"angle": {
"description": "The angle of the line (in degrees).",
"type": "number",
"format": "double"
},
"length": {
"description": "The length of the line.",
"allOf": [
{
"$ref": "#/components/schemas/TyF64"
}
]
}
},
"definitions": {
"TyF64": {
"type": "number",
"format": "double"
}
}
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
}
],
"returnValue": {
"name": "",
"type": "[number]",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "Array_size_2_of_double",
"type": "array",
"items": {
"type": "number",
"format": "double"
},
"maxItems": 2,
"minItems": 2
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> line(end = polar({ angle = 30, length = 5 }), tag = $thing)\n |> line(end = [0, 5])\n |> line(end = [segEndX(thing), 0])\n |> line(end = [-20, 10])\n |> close()\n\nexample = extrude(exampleSketch, length = 5)"
]
},
{
"name": "polygon",
"summary": "Create a regular polygon with the specified number of sides that is either inscribed or circumscribed around a circle of the specified radius.",
@ -258524,14 +258566,19 @@
"type": "[number]",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "Array_size_2_of_double",
"title": "Array_size_2_of_TyF64",
"type": "array",
"items": {
"type": "number",
"format": "double"
"$ref": "#/components/schemas/TyF64"
},
"maxItems": 2,
"minItems": 2
"minItems": 2,
"definitions": {
"TyF64": {
"type": "number",
"format": "double"
}
}
},
"required": true,
"includeInSnippet": true,
@ -258577,7 +258624,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -258625,7 +258672,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -258673,7 +258720,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -258721,14 +258768,19 @@
"type": "[number]",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "Array_size_2_of_double",
"title": "Array_size_2_of_TyF64",
"type": "array",
"items": {
"type": "number",
"format": "double"
"$ref": "#/components/schemas/TyF64"
},
"maxItems": 2,
"minItems": 2
"minItems": 2,
"definitions": {
"TyF64": {
"type": "number",
"format": "double"
}
}
},
"required": true,
"includeInSnippet": true,
@ -258774,7 +258826,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -258822,7 +258874,7 @@
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"title": "TyF64",
"type": "number",
"format": "double"
},
@ -336171,33 +336223,5 @@
"examples": [
"exampleSketch = startSketchOn(XZ)\n |> startProfileAt([0, 0], %)\n |> yLine(length = 15)\n |> angledLine({ angle = 30, length = 15 }, %)\n |> line(end = [8, -10])\n |> yLine(length = -5)\n |> close()\n\nexample = extrude(exampleSketch, length = 10)"
]
},
{
"name": "yd",
"summary": "Yards conversion factor for current projects units.",
"description": "No matter what units the current project uses, this function will always return the conversion factor to yards.\n\nFor example, if the current project uses inches, this function will return `36`. If the current project uses millimeters, this function will return `914.4`. If the current project uses yards, this function will return `1`.\n\n**Caution**: This function is only intended to be used when you absolutely MUST have different units in your code than the project settings. Otherwise, it is a bad pattern to use this function.\n\nWe merely provide these functions for convenience and readability, as `10 * yd()` is more readable that your intent is \"I want 10 yards\" than `10 * 914.4`, if the project settings are in millimeters.",
"tags": [
"units"
],
"keywordArguments": false,
"args": [],
"returnValue": {
"name": "",
"type": "number",
"schema": {
"$schema": "https://spec.openapis.org/oas/3.0/schema/2019-04-02#/definitions/Schema",
"title": "double",
"type": "number",
"format": "double"
},
"required": true,
"includeInSnippet": true,
"labelRequired": true
},
"unpublished": false,
"deprecated": false,
"examples": [
"totalWidth = 10 * yd()"
]
}
]

View File

@ -1,22 +0,0 @@
---
title: "PolarCoordsData"
excerpt: "Data for polar coordinates."
layout: manual
---
Data for polar coordinates.
**Type:** `object`
## Properties
| Property | Type | Description | Required |
|----------|------|-------------|----------|
| `angle` |[`number`](/docs/kcl/types/number)| The angle of the line (in degrees). | No |
| `length` |[`number`](/docs/kcl/types/number)| The length of the line. | No |

View File

@ -38,7 +38,7 @@ test.describe('Point and click for boolean workflows', () => {
path.resolve(
__dirname,
'../../',
'./rust/kcl-lib/e2e/executor/inputs/boolean-setup-with'
'./rust/kcl-lib/e2e/executor/inputs/boolean-setup-with-sketch-on-faces.kcl'
),
'utf-8'
)
@ -46,8 +46,6 @@ test.describe('Point and click for boolean workflows', () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Test coordinates for selection - these might need adjustment based on actual scene layout
@ -77,6 +75,7 @@ test.describe('Point and click for boolean workflows', () => {
// Select first object in the scene, expect there to be a pixel diff from the selection color change
await clickFirstObject({ pixelDiff: 50 })
await page.waitForTimeout(1000)
// For subtract, we need to proceed to the next step before selecting the second object
if (operationName !== 'subtract') {
@ -87,6 +86,8 @@ test.describe('Point and click for boolean workflows', () => {
// Select second object
await clickSecondObject({ pixelDiff: 50 })
await page.waitForTimeout(1000)
// Confirm the operation in the command bar
await cmdBar.progressCmdBar()

View File

@ -4,6 +4,7 @@ import { uuidv4 } from '@src/lib/utils'
import type { HomePageFixture } from '@e2e/playwright/fixtures/homePageFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
@ -15,6 +16,7 @@ test.describe(
page: Page,
homePage: HomePageFixture,
scene: SceneFixture,
toolbar: ToolbarFixture,
plane: string,
clickCoords: { x: number; y: number }
) => {
@ -59,9 +61,12 @@ test.describe(
await u.sendCustomCmd(updateCamCommand)
await u.closeDebugPanel()
await page.mouse.click(clickCoords.x, clickCoords.y)
await page.waitForTimeout(600) // wait for animation
await toolbar.waitUntilSketchingReady()
await expect(
page.getByRole('button', { name: 'line Line', exact: true })
).toBeVisible()
@ -117,11 +122,12 @@ test.describe(
]
for (const config of planeConfigs) {
test(config.plane, async ({ page, homePage, scene }) => {
test(config.plane, async ({ page, homePage, scene, toolbar }) => {
await sketchOnPlaneAndBackSideTest(
page,
homePage,
scene,
toolbar,
config.plane,
config.coords
)

View File

@ -15,6 +15,7 @@ test.describe('Code pane and errors', { tag: ['@skipWin'] }, () => {
page,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
@ -36,7 +37,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Ensure no badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')
@ -171,6 +172,8 @@ extrude001 = extrude(sketch001, length = 5)`
context,
page,
homePage,
scene,
cmdBar,
}) => {
// Load the app with the working starter code
await context.addInitScript((code) => {
@ -180,9 +183,7 @@ extrude001 = extrude(sketch001, length = 5)`
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
// FIXME: await scene.waitForExecutionDone() does not work. It still fails.
// I needed to increase this timeout to get this to pass.
await page.waitForTimeout(10000)
await scene.settled(cmdBar)
// Ensure badge is present
const codePaneButtonHolder = page.locator('#code-button-holder')

View File

@ -317,9 +317,13 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
test('Can switch between sketch tools via command bar', async ({
page,
homePage,
scene,
cmdBar,
toolbar,
}) => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
const sketchButton = page.getByRole('button', { name: 'Start Sketch' })
const cmdBarButton = page.getByRole('button', { name: 'Commands' })
@ -343,7 +347,9 @@ test.describe('Command bar tests', { tag: ['@skipWin'] }, () => {
// Start a sketch
await sketchButton.click()
await page.mouse.click(700, 200)
await toolbar.waitUntilSketchingReady()
// Switch between sketch tools via the command bar
await expect(lineToolButton).toHaveAttribute('aria-pressed', 'true')

View File

@ -11,7 +11,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test(
'export works on the first try',
{ tag: ['@electron', '@skipLocalEngine'] },
async ({ page, context, scene, tronApp }, testInfo) => {
async ({ page, context, scene, tronApp, cmdBar }, testInfo) => {
if (!tronApp) {
fail()
}
@ -32,53 +32,41 @@ test(
})
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await test.step('on open of project', async () => {
await expect(page.getByText(`bracket`)).toBeVisible()
// Open the project
const projectName = page.getByText(`bracket`)
await expect(projectName).toBeVisible()
await projectName.click()
await scene.settled(cmdBar)
// open the project
await page.getByText(`bracket`).click()
// expect zero errors in guter
// Expect zero errors in gutter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// export the model
// Click the export button
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
await scene.waitForExecutionDone()
const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `main.kcl`, so the export file name should be `main.gltf`
const exportFileName = `main.gltf`
// Click the export button
await exportButton.click()
// Select the first format option
const gltfOption = cmdBar.selectOption({ name: 'glTF' })
const exportFileName = `main.gltf` // source file is named `main.kcl`
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.waitForTimeout(500)
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed.
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
@ -86,6 +74,7 @@ test(
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
// Check for the exported file
const firstFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName
@ -112,60 +101,50 @@ test(
const u = await getUtils(page)
await u.openFilePanel()
// Click on the other file
const otherKclButton = page.getByRole('button', { name: 'other.kcl' })
// Click the file
await otherKclButton.click()
// Close the file pane
await u.closeFilePanel()
await scene.settled(cmdBar)
// FIXME: await scene.waitForExecutionDone() does not work. The modeling indicator stays in -receive-reliable and not execution done
await page.waitForTimeout(10000)
// expect zero errors in guter
// Expect zero errors in gutter
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
// export the model
// Click the export button
const exportButton = page.getByTestId('export-pane-button')
await expect(exportButton).toBeVisible()
const gltfOption = page.getByText('glTF')
const submitButton = page.getByText('Confirm Export')
const exportingToastMessage = page.getByText(`Exporting...`)
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
// The open file's name is `other.kcl`, so the export file name should be `other.gltf`
const exportFileName = `other.gltf`
// Click the export button
await exportButton.click()
// Select the first format option
const gltfOption = cmdBar.selectOption({ name: 'glTF' })
const exportFileName = `other.gltf` // source file is named `other.kcl`
await expect(gltfOption).toBeVisible()
await expect(page.getByText('STL')).toBeVisible()
await page.keyboard.press('Enter')
// Click the checkbox
const submitButton = page.getByText('Confirm Export')
await expect(submitButton).toBeVisible()
await page.keyboard.press('Enter')
// Find the toast.
// Look out for the toast message
const exportingToastMessage = page.getByText(`Exporting...`)
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
await expect(exportingToastMessage).toBeVisible()
await expect(alreadyExportingToastMessage).not.toBeVisible()
// Expect it to succeed
const errorToastMessage = page.getByText(`Error while exporting`)
const engineErrorToastMessage = page.getByText(`Nothing to export`)
await expect(errorToastMessage).not.toBeVisible()
await expect(engineErrorToastMessage).not.toBeVisible()
const successToastMessage = page.getByText(`Exported successfully`)
await test.step('Check the success toast message shows and nothing else', async () =>
Promise.all([
expect(alreadyExportingToastMessage).not.toBeVisible(),
expect(errorToastMessage).not.toBeVisible(),
expect(engineErrorToastMessage).not.toBeVisible(),
expect(successToastMessage).toBeVisible(),
expect(exportingToastMessage).not.toBeVisible(),
]))
await expect(successToastMessage).toBeVisible()
await expect(exportingToastMessage).not.toBeVisible()
// Check for the exported file=
const secondFileFullPath = path.resolve(
getPlaywrightDownloadDir(tronApp.projectDirName),
exportFileName

View File

@ -78,12 +78,14 @@ sketch001 = startSketchOn(XY)
// Ensure we execute the first time.
await u.openDebugPanel()
await expect(
page.locator('[data-receive-command-type="scene_clear_all"]')
).toHaveCount(1)
await expect(
page.locator('[data-message-type="execution-done"]')
).toHaveCount(2)
await expect
.poll(() =>
page.locator('[data-receive-command-type="scene_clear_all"]').count()
)
.toBe(1)
await expect
.poll(() => page.locator('[data-message-type="execution-done"]').count())
.toBe(2)
// Add whitespace to the end of the code.
await u.codeLocator.click()
@ -110,12 +112,14 @@ sketch001 = startSketchOn(XY)
test('ensure we use the cache, and do not clear on append', async ({
homePage,
page,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await u.codeLocator.click()
await page.keyboard.type(`sketch001 = startSketchOn(XY)
@ -499,7 +503,7 @@ sketch_001 = startSketchOn(XY)
await page.keyboard.press('ArrowLeft')
await page.keyboard.press('ArrowRight')
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// error in guter
await expect(page.locator('.cm-lint-marker-info').first()).toBeVisible()
@ -1315,4 +1319,38 @@ sketch001 = startSketchOn(XZ)
const element = page.locator('[data-overlay-index="1"]')
await expect(element).toHaveAttribute('data-overlay-visible', 'true')
})
test(`Only show axis planes when there are no errors`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`sketch001 = startSketchOn(XZ)
profile001 = circle(sketch001, center = [-100.0, -100.0], radius = 50.0)
sketch002 = startSketchOn(XZ)
profile002 = circle(sketch002, center = [-100.0, 100.0], radius = 50.0)
extrude001 = extrude(profile002, length = 0)` // length = 0 is causing the error
)
})
const viewportSize = { width: 1200, height: 800 }
await page.setBodyDimensions(viewportSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await scene.expectPixelColor(
TEST_COLORS.DARK_MODE_BKGD,
// This is a position where the blue part of the axis plane is visible if its rendered
{ x: viewportSize.width * 0.75, y: viewportSize.height * 0.2 },
15
)
})
})

View File

@ -64,7 +64,7 @@ test.describe('Feature Tree pane', () => {
test(
'User can go to definition and go to function definition',
{ tag: '@electron' },
async ({ context, homePage, scene, editor, toolbar }) => {
async ({ context, homePage, scene, editor, toolbar, cmdBar, page }) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'test-sample')
await fsp.mkdir(bracketDir, { recursive: true })
@ -86,9 +86,13 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await editor.closePane()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
await expect
.poll(() => page.getByText('Feature tree').count())
.toBeGreaterThan(1)
})
async function testViewSource({
@ -254,7 +258,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
})
@ -339,7 +343,7 @@ test.describe('Feature Tree pane', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openFeatureTreePane()
})
@ -414,8 +418,7 @@ profile003 = startProfileAt([0, -4.93], sketch001)
const planeColor: [number, number, number] = [74, 74, 74]
await homePage.openProject('test-sample')
// FIXME: @lf94 has a better way to verify execution completion, in a PR rn
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step(`Verify we see the sketch`, async () => {
await scene.expectPixelColor(sketchColor, testPoint, 10)

View File

@ -47,6 +47,7 @@ test.describe('integrations tests', () => {
await scene.connectionEstablished()
await scene.settled(cmdBar)
await clickObj()
await page.waitForTimeout(1000)
await scene.moveNoWhere()
await editor.expectState({
activeLines: [
@ -72,11 +73,11 @@ test.describe('integrations tests', () => {
})
await test.step('setup for next assertion', async () => {
await toolbar.openFile('main.kcl')
await scene.settled(cmdBar)
await page.waitForTimeout(1000)
await clickObj()
await page.waitForTimeout(1000)
await scene.moveNoWhere()
await page.waitForTimeout(1000)
await editor.expectState({
activeLines: [
'|>startProfileAt([75.8,317.2],%)//[$startCapTag,$EndCapTag]',
@ -89,7 +90,7 @@ test.describe('integrations tests', () => {
await toolbar.expectFileTreeState(['main.kcl', fileName])
})
await test.step('check sketch mode is exited when opening a different file', async () => {
await toolbar.openFile(fileName, { wait: false })
await toolbar.openFile(fileName)
// check we're out of sketch mode
await expect(toolbar.exitSketchBtn).not.toBeVisible()

View File

@ -112,22 +112,16 @@ export class CmdBarFixture {
* and assumes we are past the `pickCommand` step.
*/
progressCmdBar = async (shouldFuzzProgressMethod = true) => {
// FIXME: Progressing the command bar is a race condition. We have an async useEffect that reports the final state via useCalculateKclExpression. If this does not run quickly enough, it will not "fail" the continue because you can press continue if the state is not ready. E2E tests do not know this.
// Wait 1250ms to assume the await executeAst of the KCL input field is finished
await this.page.waitForTimeout(1250)
if (shouldFuzzProgressMethod || Math.random() > 0.5) {
const arrowButton = this.page.getByRole('button', {
name: 'arrow right Continue',
})
if (await arrowButton.isVisible()) {
await arrowButton.click()
} else {
await this.page
.getByRole('button', { name: 'checkmark Submit command' })
.click()
}
await this.page.waitForTimeout(2000)
const arrowButton = this.page.getByRole('button', {
name: 'arrow right Continue',
})
if (await arrowButton.isVisible()) {
await arrowButton.click()
} else {
await this.page.keyboard.press('Enter')
await this.page
.getByRole('button', { name: 'checkmark Submit command' })
.click()
}
}

View File

@ -39,7 +39,8 @@ export class AuthenticatedApp {
}
async initialise(code = '') {
await setup(this.context, this.page, this.testInfo)
const testDir = this.testInfo.outputPath('electron-test-projects-dir')
await setup(this.context, this.page, testDir, this.testInfo)
const u = await getUtils(this.page)
await this.page.addInitScript(async (code) => {
@ -102,11 +103,11 @@ export class ElectronZoo {
return resolve(undefined)
}
if (Date.now() - timeA > 10000) {
if (Date.now() - timeA > 3000) {
return resolve(undefined)
}
setTimeout(checkDisconnected, 0)
setTimeout(checkDisconnected, 1)
}
checkDisconnected()
})
@ -128,11 +129,9 @@ export class ElectronZoo {
const that = this
const options = {
timeout: 120000,
args: ['.', '--no-sandbox'],
env: {
...process.env,
TEST_SETTINGS_FILE_KEY: this.projectDirName,
IS_PLAYWRIGHT: 'true',
},
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
@ -200,7 +199,14 @@ export class ElectronZoo {
await this.context.tracing.startChunk()
await setup(this.context, this.page, testInfo)
// THIS IS ABSOLUTELY NECESSARY TO CHANGE THE PROJECT DIRECTORY BETWEEN
// TESTS BECAUSE OF THE ELECTRON INSTANCE REUSE.
await this.electron?.evaluate(({ app }, projectDirName) => {
// @ts-ignore can't declaration merge see main.ts
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
}, this.projectDirName)
await setup(this.context, this.page, this.projectDirName, testInfo)
await this.cleanProjectDir()
@ -250,11 +256,6 @@ export class ElectronZoo {
// return app.reuseWindowForTest();
// });
await this.electron?.evaluate(({ app }, projectDirName) => {
// @ts-ignore can't declaration merge see main.ts
app.testProperty['TEST_SETTINGS_FILE_KEY'] = projectDirName
}, this.projectDirName)
// Always start at the root view
await this.page.goto(this.firstUrl)
@ -278,8 +279,9 @@ export class ElectronZoo {
// Not a problem if it already exists.
}
const tempSettingsFilePath = path.join(
const tempSettingsFilePath = path.resolve(
this.projectDirName,
'..',
SETTINGS_FILE_NAME
)

View File

@ -43,21 +43,13 @@ type DragFromHandler = (
export class SceneFixture {
public page: Page
public streamWrapper!: Locator
public loadingIndicator!: Locator
public networkToggleConnected!: Locator
public startEditSketchBtn!: Locator
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-execution-done')
.or(this.page.getByTestId('model-state-indicator-receive-reliable'))
}
constructor(page: Page) {
this.page = page
this.streamWrapper = page.getByTestId('stream')
this.networkToggleConnected = page.getByTestId('network-toggle-ok')
this.loadingIndicator = this.streamWrapper.getByTestId('loading')
this.startEditSketchBtn = page
.getByRole('button', { name: 'Start Sketch' })
.or(page.getByRole('button', { name: 'Edit Sketch' }))
@ -231,10 +223,6 @@ export class SceneFixture {
}
}
waitForExecutionDone = async () => {
await expect(this.exeIndicator).toBeVisible({ timeout: 30000 })
}
connectionEstablished = async () => {
const timeout = 30000
await expect(this.networkToggleConnected).toBeVisible({ timeout })
@ -243,6 +231,9 @@ export class SceneFixture {
settled = async (cmdBar: CmdBarFixture) => {
const u = await getUtils(this.page)
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
await cmdBar.openCmdBar()
await cmdBar.chooseCommand('Settings · app · show debug panel')
await cmdBar.selectOption({ name: 'on' }).click()
@ -250,10 +241,6 @@ export class SceneFixture {
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
await this.waitForExecutionDone()
await expect(this.startEditSketchBtn).not.toBeDisabled()
await expect(this.startEditSketchBtn).toBeVisible()
}
expectPixelColor = async (

View File

@ -44,6 +44,7 @@ export class ToolbarFixture {
featureTreePane!: Locator
gizmo!: Locator
gizmoDisabled!: Locator
insertButton!: Locator
constructor(page: Page) {
this.page = page
@ -78,18 +79,14 @@ export class ToolbarFixture {
// element or two different elements can represent these states.
this.gizmo = page.getByTestId('gizmo')
this.gizmoDisabled = page.getByTestId('gizmo-disabled')
this.insertButton = page.getByTestId('insert-pane-button')
}
get logoLink() {
return this.page.getByTestId('app-logo')
}
get exeIndicator() {
return this.page
.getByTestId('model-state-indicator-receive-reliable')
.or(this.page.getByTestId('model-state-indicator-execution-done'))
}
startSketchPlaneSelection = async () =>
doAndWaitForImageDiff(this.page, () => this.startSketchBtn.click(), 500)
@ -165,16 +162,10 @@ export class ToolbarFixture {
}
}
/**
* Opens file by it's name and waits for execution to finish
* Opens file by it's name
*/
openFile = async (
fileName: string,
{ wait }: { wait?: boolean } = { wait: true }
) => {
openFile = async (fileName: string) => {
await this.filePane.getByText(fileName).click()
if (wait) {
await expect(this.exeIndicator).toBeVisible({ timeout: 15_000 })
}
}
selectCenterRectangle = async () => {
await this.page

View File

@ -10,6 +10,7 @@ test.describe('Import UI tests', () => {
toolbar,
scene,
editor,
cmdBar,
}) => {
await context.folderSetupFn(async (dir) => {
const projectDir = path.join(dir, 'import-test')
@ -61,7 +62,7 @@ sketch002 = startSketchOn(extrude001, seg01)`
})
await homePage.openProject('import-test')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await scene.moveCameraTo(
{

View File

@ -7,7 +7,7 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test(
'When machine-api server not found butt is disabled and shows the reason',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -23,10 +23,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
const notFoundText = 'Machine API server was not discovered'
await expect(page.getByText(notFoundText).first()).not.toBeVisible()
@ -47,7 +44,7 @@ test(
test(
'When machine-api server not found home screen & project status shows the reason',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -71,10 +68,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(page.getByText(notFoundText).nth(1)).not.toBeVisible()

View File

@ -88,7 +88,7 @@ test.describe('Named view tests', () => {
// Create and load project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create named view
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
@ -110,14 +110,17 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
})
test('Verify named view gets deleted', async ({
cmdBar,
@ -130,7 +133,7 @@ test.describe('Named view tests', () => {
// Create project and go into the project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create a new named view
await cmdBar.openCmdBar()
@ -152,14 +155,16 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
// Delete a named view
await cmdBar.openCmdBar()
@ -167,14 +172,16 @@ test.describe('Named view tests', () => {
cmdBar.selectOption({ name: myNamedView2 })
await cmdBar.progressCmdBar(false)
// Read project.toml into memory again since we deleted a named view
tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory again since we deleted a named view
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// // Write the entire tomlString to a snapshot.
// // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
// // Write the entire tomlString to a snapshot.
// // There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-deleted')
}).toPass()
})
test('Verify named view gets loaded', async ({
cmdBar,
@ -186,7 +193,7 @@ test.describe('Named view tests', () => {
// Create project and go into the project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create a new named view
await cmdBar.openCmdBar()
@ -208,14 +215,16 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-named-view-gets-created')
}).toPass()
// Create a load a named view
await cmdBar.openCmdBar()
@ -239,7 +248,7 @@ test.describe('Named view tests', () => {
// Create and load project
await createProject({ name: projectName, page })
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// Create named view
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
@ -282,13 +291,15 @@ test.describe('Named view tests', () => {
expect(exists).toBe(true)
}).toPass()
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
await expect(async () => {
// Read project.toml into memory
let tomlString = await fsp.readFile(tempProjectSettingsFilePath, 'utf-8')
// Rewrite the uuids in the named views to match snapshot otherwise they will be randomly generated from rust and break
tomlString = tomlStringOverWriteNamedViewUuids(tomlString)
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
// Write the entire tomlString to a snapshot.
// There are many key/value pairs to check this is a safer match.
expect(tomlString).toMatchSnapshot('verify-two-named-view-gets-created')
}).toPass()
})
})

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
import * as fsp from 'fs/promises'
import path from 'path'
import { executorInputPath } from '@e2e/playwright/test-utils'
import { test } from '@e2e/playwright/zoo-test'
// test file is for testing point an click code gen functionality that's assemblies related
test.describe('Point-and-click assemblies tests', () => {
test(
`Insert kcl part into assembly as whole module import`,
{ tag: ['@electron'] },
async ({
context,
page,
homePage,
scene,
editor,
toolbar,
cmdBar,
tronApp,
}) => {
if (!tronApp) {
fail()
}
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
const initialColor: [number, number, number] = [50, 50, 50]
const partColor: [number, number, number] = [150, 150, 150]
const tolerance = 50
await test.step('Setup parts and expect empty assembly scene', async () => {
const projectName = 'assembly'
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, projectName)
await fsp.mkdir(bracketDir, { recursive: true })
await Promise.all([
fsp.copyFile(
executorInputPath('cylinder-inches.kcl'),
path.join(bracketDir, 'cylinder.kcl')
),
fsp.copyFile(
executorInputPath('e2e-can-sketch-on-chamfer.kcl'),
path.join(bracketDir, 'bracket.kcl')
),
fsp.writeFile(path.join(bracketDir, 'main.kcl'), ''),
])
})
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.openProject(projectName)
await scene.settled(cmdBar)
await scene.expectPixelColor(initialColor, testPoint, tolerance)
})
await test.step('Insert first part into the assembly', async () => {
await toolbar.insertButton.click()
await cmdBar.selectOption({ name: 'cylinder.kcl' }).click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'localName',
currentArgValue: '',
headerArguments: { Path: 'cylinder.kcl', LocalName: '' },
highlightedHeaderArg: 'localName',
commandName: 'Insert',
})
await page.keyboard.insertText('cylinder')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: { Path: 'cylinder.kcl', LocalName: 'cylinder' },
commandName: 'Insert',
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(
`
import "cylinder.kcl" as cylinder
cylinder
`,
{ shouldNormalise: true }
)
await scene.expectPixelColor(partColor, testPoint, tolerance)
})
await test.step('Insert second part into the assembly', async () => {
await toolbar.insertButton.click()
await cmdBar.selectOption({ name: 'bracket.kcl' }).click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'localName',
currentArgValue: '',
headerArguments: { Path: 'bracket.kcl', LocalName: '' },
highlightedHeaderArg: 'localName',
commandName: 'Insert',
})
await page.keyboard.insertText('bracket')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: { Path: 'bracket.kcl', LocalName: 'bracket' },
commandName: 'Insert',
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain(
`
import "cylinder.kcl" as cylinder
import "bracket.kcl" as bracket
cylinder
bracket
`,
{ shouldNormalise: true }
)
})
}
)
})

View File

@ -5,13 +5,14 @@ import path from 'node:path'
import type { EditorFixture } from '@e2e/playwright/fixtures/editorFixture'
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
import type { ToolbarFixture } from '@e2e/playwright/fixtures/toolbarFixture'
import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
// test file is for testing point an click code gen functionality that's not sketch mode related
test.describe('Point-and-click tests', () => {
test('verify extruding circle works', async ({
page,
context,
homePage,
cmdBar,
@ -30,8 +31,9 @@ test.describe('Point-and-click tests', () => {
await context.addInitScript((file) => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
const [clickCircle, moveToCircle] = scene.makeMouseHelpers(582, 217)
@ -72,7 +74,6 @@ test.describe('Point-and-click tests', () => {
await test.step('do extrude flow and check extrude code is added to editor', async () => {
await toolbar.extrudeButton.click()
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'distance',
@ -186,6 +187,7 @@ test.describe('Point-and-click tests', () => {
editor,
toolbar,
scene,
cmdBar,
}) => {
const file = await fs.readFile(
path.resolve(
@ -200,9 +202,7 @@ test.describe('Point-and-click tests', () => {
}, file)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await expect(
page.getByTestId('model-state-indicator-receive-reliable')
).toBeVisible()
await scene.settled(cmdBar)
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -377,6 +377,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
editor,
toolbar,
scene,
cmdBar,
}) => {
const file = await fs.readFile(
path.resolve(
@ -392,7 +393,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const sketchOnAChamfer = _sketchOnAChamfer(page, editor, toolbar, scene)
@ -479,6 +480,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await page.setBodyDimensions(viewPortSize)
await homePage.goToModelingScene()
await scene.connectionEstablished()
// Constants and locators
// These are mappings from screenspace to KCL coordinates,
@ -537,8 +539,7 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
await toolbar.startSketchPlaneSelection()
await moveToXzPlane()
await clickOnXzPlane()
// timeout wait for engine animation is unavoidable
await page.waitForTimeout(600)
await toolbar.waitUntilSketchingReady()
await editor.expectEditor.toContain(expectedCodeSnippets.sketchOnXzPlane)
})
await test.step(`Place a point a few pixels off the middle, verify it still snaps to 0,0`, async () => {
@ -580,9 +581,8 @@ profile001 = startProfileAt([205.96, 254.59], sketch002)
editor,
toolbar,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const initialCode = `closedSketch = startSketchOn(XZ)
|> circle(center = [8, 5], radius = 2)
openSketch = startSketchOn(XY)
@ -599,8 +599,6 @@ openSketch = startSketchOn(XY)
}, initialCode)
await homePage.goToModelingScene()
await u.waitForPageLoad()
await page.waitForTimeout(1000)
const pointInsideCircle = {
x: viewPortSize.width * 0.63,
@ -625,15 +623,16 @@ openSketch = startSketchOn(XY)
const exitSketch = async () => {
await test.step(`Exit sketch mode`, async () => {
await toolbar.exitSketchBtn.click()
await expect(toolbar.exitSketchBtn).not.toBeVisible()
await expect(toolbar.startSketchBtn).toBeEnabled()
})
}
await test.step(`Double-click on the closed sketch`, async () => {
await scene.settled(cmdBar)
await moveToCircle()
await page.waitForTimeout(1000)
await dblClickCircle()
await expect(toolbar.startSketchBtn).not.toBeVisible()
await page.waitForTimeout(1000)
await expect(toolbar.exitSketchBtn).toBeVisible()
await editor.expectState({
activeLines: [`|>circle(center=[8,5],radius=2)`],
@ -670,7 +669,6 @@ openSketch = startSketchOn(XY)
// There is a full execution after exiting sketch that clears the scene.
await page.waitForTimeout(500)
await dblClickOpenPath()
await expect(toolbar.startSketchBtn).not.toBeVisible()
await expect(toolbar.exitSketchBtn).toBeVisible()
// Wait for enter sketch mode to complete
await page.waitForTimeout(500)
@ -1031,6 +1029,9 @@ openSketch = startSketchOn(XY)
})
await test.step(`Go through the command bar flow`, async () => {
await toolbar.offsetPlaneButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'plane',
@ -1088,6 +1089,7 @@ openSketch = startSketchOn(XY)
const expectedLine = `axis=X,`
await homePage.goToModelingScene()
await scene.connectionEstablished()
await test.step(`Go through the command bar flow`, async () => {
await toolbar.helixButton.click()
@ -1106,6 +1108,7 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
await expect.poll(() => page.getByText('Axis').count()).toBe(6)
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -1233,6 +1236,7 @@ openSketch = startSketchOn(XY)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.settled(cmdBar)
await test.step(`Go through the command bar flow`, async () => {
await toolbar.closePane('code')
@ -1252,15 +1256,22 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.selectOption({ name: 'Edge' }).click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnEdge()
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.argumentInput.focus()
await page.waitForTimeout(1000)
await page.keyboard.insertText('20')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('0')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await page.keyboard.insertText('100')
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -1274,6 +1285,7 @@ openSketch = startSketchOn(XY)
commandName: 'Helix',
})
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
@ -1369,7 +1381,7 @@ extrude001 = extrude(profile001, length = 100)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 620, y: 257 }
@ -1530,6 +1542,9 @@ extrude001 = extrude(profile001, length = 100)
if (!shouldPreselect) {
await test.step(`Go through the command bar flow without preselected sketches`, async () => {
await toolbar.loftButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -1579,6 +1594,7 @@ extrude001 = extrude(profile001, length = 100)
page,
homePage,
scene,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XZ)
|> circle(center = [0, 0], radius = 30)
@ -1592,7 +1608,7 @@ loft001 = loft([sketch001, sketch002])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
@ -1687,7 +1703,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
@ -1707,6 +1723,9 @@ sketch002 = startSketchOn(XZ)
await test.step(`Go through the command bar flow`, async () => {
await toolbar.sweepButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'target',
@ -1826,7 +1845,7 @@ sketch002 = startSketchOn(XZ)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 700, y: 250 }
@ -1843,6 +1862,9 @@ sketch002 = startSketchOn(XZ)
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
await toolbar.sweepButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
commandName: 'Sweep',
currentArgKey: 'target',
@ -2059,6 +2081,9 @@ extrude001 = extrude(sketch001, length = -12)
await test.step(`Open fillet UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.filletButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -2184,6 +2209,7 @@ extrude001 = extrude(sketch001, length = -12)
homePage,
scene,
toolbar,
cmdBar,
}) => {
const initialCode = `sketch001 = startSketchOn(XY)
profile001 = circle(
@ -2200,7 +2226,7 @@ fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step('Double-click in feature tree and expect error toast', async () => {
await toolbar.openPane('feature-tree')
@ -2521,7 +2547,7 @@ extrude001 = extrude(sketch001, length = -12)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
})
// Test 1: Command bar flow with preselected edges
@ -2554,6 +2580,7 @@ extrude001 = extrude(sketch001, length = -12)
stage: 'arguments',
})
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.expectState({
commandName: 'Chamfer',
highlightedHeaderArg: 'length',
@ -2565,7 +2592,10 @@ extrude001 = extrude(sketch001, length = -12)
},
stage: 'arguments',
})
await cmdBar.argumentInput.focus()
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(1000)
await cmdBar.expectState({
commandName: 'Chamfer',
headerArguments: {
@ -2649,6 +2679,9 @@ extrude001 = extrude(sketch001, length = -12)
await test.step(`Open chamfer UI without selecting edges`, async () => {
await page.waitForTimeout(100)
await toolbar.chamferButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -2771,6 +2804,7 @@ extrude001 = extrude(sketch001, length = -12)
scene,
editor,
toolbar,
cmdBar,
}) => {
// Code samples
const initialCode = `@settings(defaultLengthUnit = in)
@ -2814,7 +2848,7 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// verify modeling scene is loaded
await scene.expectPixelColor(
@ -2936,9 +2970,11 @@ extrude001 = extrude(sketch001, length = 30)
await context.addInitScript((initialCode) => {
localStorage.setItem('persistCode', initialCode)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
// One dumb hardcoded screen pixel value
const testPoint = { x: 575, y: 200 }
@ -2955,6 +2991,9 @@ extrude001 = extrude(sketch001, length = 30)
if (!shouldPreselect) {
await test.step(`Go through the command bar flow without preselected faces`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3015,7 +3054,6 @@ extrude001 = extrude(sketch001, length = 30)
})
await test.step('Edit shell via feature tree selection works', async () => {
await toolbar.closePane('code')
await toolbar.openPane('feature-tree')
const operationButton = await toolbar.getFeatureTreeOperation(
'Shell',
@ -3044,7 +3082,6 @@ extrude001 = extrude(sketch001, length = 30)
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
@ -3079,7 +3116,7 @@ extrude001 = extrude(sketch001, length = 40)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 180 }
@ -3097,6 +3134,9 @@ extrude001 = extrude(sketch001, length = 40)
await test.step(`Go through the command bar flow, selecting a wall and keeping default thickness`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3108,6 +3148,9 @@ extrude001 = extrude(sketch001, length = 40)
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnCap()
await page.keyboard.down('Shift')
await clickOnWall()
@ -3116,6 +3159,7 @@ extrude001 = extrude(sketch001, length = 40)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3124,7 +3168,9 @@ extrude001 = extrude(sketch001, length = 40)
},
commandName: 'Shell',
})
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
})
await test.step(`Confirm code is added to the editor, scene has changed`, async () => {
@ -3139,7 +3185,6 @@ extrude001 = extrude(sketch001, length = 40)
})
await test.step('Edit shell via feature tree selection works', async () => {
await editor.closePane()
const operationButton = await toolbar.getFeatureTreeOperation('Shell', 0)
await operationButton.dblclick({ button: 'left' })
await cmdBar.expectState({
@ -3154,6 +3199,7 @@ extrude001 = extrude(sketch001, length = 40)
})
await page.keyboard.insertText('1')
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3164,7 +3210,6 @@ extrude001 = extrude(sketch001, length = 40)
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor([150, 150, 150], testPoint, 15)
await toolbar.openPane('code')
await editor.expectEditor.toContain(editedShellDeclaration)
await editor.expectState({
diagnostics: [],
@ -3218,7 +3263,7 @@ extrude002 = extrude(sketch002, length = 50)
}, initialCode)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 580, y: 320 }
@ -3243,12 +3288,13 @@ extrude002 = extrude(sketch002, length = 50)
highlightedHeaderArg: 'selection',
commandName: 'Shell',
})
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await clickOnCap()
await page.waitForTimeout(500)
await page.waitForTimeout(1000)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.progressCmdBar()
await page.waitForTimeout(500)
await cmdBar.expectState({
stage: 'review',
headerArguments: {
@ -3306,7 +3352,7 @@ profile001 = startProfileAt([-20, 20], sketch001)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await toolbar.openPane('feature-tree')
// One dumb hardcoded screen pixel value
@ -3386,7 +3432,7 @@ sweep001 = sweep(sketch001, path = sketch002)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 }
@ -3399,6 +3445,9 @@ sweep001 = sweep(sketch001, path = sketch002)
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
await toolbar.shellButton.click()
await expect
.poll(() => page.getByText('Please select one').count())
.toBe(1)
await cmdBar.expectState({
stage: 'arguments',
currentArgKey: 'selection',
@ -3462,12 +3511,13 @@ segAng(rectangleSegmentA002),
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `segAng(rectangleSegmentA002) - 90,`
const codeToSelection = `segAng(rectangleSegmentA002) - 90,`
// revolve
await page.getByText(codeToSelecton).click()
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await toolbar.revolveButton.click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3541,15 +3591,17 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `center = [-11.34, 10.0]`
const codeToSelection = `center = [-11.34, 10.0]`
// revolve
await page.getByText(codeToSelecton).click()
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await toolbar.revolveButton.click()
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> angledLine([0, 202.6], %, $rectangleSegmentA001)`
const lineCodeToSelection = `angledLine([0, 202.6], %, $rectangleSegmentA001)`
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3595,6 +3647,7 @@ sketch002 = startSketchOn(extrude001, rectangleSegmentA001)
await editor.expectEditor.toContain(
newCodeToFind.replace('angle = 360', 'angle = angle001')
)
expect(editor.expectEditor.toContain(newCodeToFind)).toBeTruthy()
})
test('revolve sketch circle around line segment from startProfileAt sketch', async ({
context,
@ -3628,15 +3681,20 @@ sketch003 = startSketchOn(extrude001, 'START')
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// select line of code
const codeToSelecton = `center = [-0.69, 0.56]`
const codeToSelection = `center = [-0.69, 0.56]`
// revolve
await page.getByText(codeToSelecton).click()
await toolbar.revolveButton.click()
await page.waitForTimeout(1000)
await editor.scrollToText(codeToSelection)
await page.getByText(codeToSelection).click()
await expect.poll(() => page.getByText('AxisOrEdge').count()).toBe(2)
await page.getByText('Edge', { exact: true }).click()
const lineCodeToSelection = `|> xLine(length = 2.6)`
const lineCodeToSelection = `length = 2.6`
await editor.scrollToText(lineCodeToSelection)
await page.getByText(lineCodeToSelection).click()
await cmdBar.progressCmdBar()
await cmdBar.progressCmdBar()
@ -3703,21 +3761,22 @@ extrude001 = extrude(profile001, length = 100)
}, initialCode)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// One dumb hardcoded screen pixel value
const testPoint = { x: 500, y: 250 }
const initialColor: [number, number, number] = [123, 123, 123]
const tolerance = 50
await test.step(`Confirm extrude exists with default appearance`, async () => {
await toolbar.closePane('code')
await scene.expectPixelColor(initialColor, testPoint, 15)
await scene.expectPixelColor(initialColor, testPoint, tolerance)
})
async function setApperanceAndCheck(
option: string,
hex: string,
shapeColor: [number, number, number]
shapeColor?: [number, number, number]
) {
await toolbar.openPane('feature-tree')
const enterAppearanceFlow = async (stepName: string) =>
@ -3766,7 +3825,9 @@ extrude001 = extrude(profile001, length = 100)
})
await cmdBar.progressCmdBar()
await toolbar.closePane('feature-tree')
await scene.expectPixelColor(shapeColor, testPoint, 10)
if (shapeColor) {
await scene.expectPixelColor(shapeColor, testPoint, tolerance)
}
await toolbar.openPane('code')
if (hex === 'default') {
const anyAppearanceDeclaration = `|> appearance(`
@ -3785,16 +3846,17 @@ extrude001 = extrude(profile001, length = 100)
}
await test.step(`Go through the Set Appearance flow for all options`, async () => {
await setApperanceAndCheck('Red', '#FF0000', [180, 0, 0])
await setApperanceAndCheck('Green', '#00FF00', [0, 180, 0])
await setApperanceAndCheck('Blue', '#0000FF', [0, 0, 180])
await setApperanceAndCheck('Turquoise', '#00FFFF', [0, 180, 180])
await setApperanceAndCheck('Purple', '#FF00FF', [180, 0, 180])
await setApperanceAndCheck('Yellow', '#FFFF00', [180, 180, 0])
await setApperanceAndCheck('Black', '#000000', [0, 0, 0])
await setApperanceAndCheck('Dark Grey', '#080808', [0x33, 0x33, 0x33])
await setApperanceAndCheck('Light Grey', '#D3D3D3', [176, 176, 176])
await setApperanceAndCheck('White', '#FFFFFF', [184, 184, 184])
await setApperanceAndCheck('Red', '#FF0000', [180, 30, 30])
// Not checking the scene color every time cause that's not really deterministic. Red seems reliable though
await setApperanceAndCheck('Green', '#00FF00')
await setApperanceAndCheck('Blue', '#0000FF')
await setApperanceAndCheck('Turquoise', '#00FFFF')
await setApperanceAndCheck('Purple', '#FF00FF')
await setApperanceAndCheck('Yellow', '#FFFF00')
await setApperanceAndCheck('Black', '#000000')
await setApperanceAndCheck('Dark Grey', '#080808')
await setApperanceAndCheck('Light Grey', '#D3D3D3')
await setApperanceAndCheck('White', '#FFFFFF')
await setApperanceAndCheck(
'Default (clear appearance)',
'default',

View File

@ -83,7 +83,7 @@ test(
test(
'click help/keybindings from project page',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -95,17 +95,11 @@ test(
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
// expect to see the text bracket
await expect(page.getByText('bracket')).toBeVisible()
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
// click ? button
await page.getByTestId('help-button').click()
@ -120,7 +114,7 @@ test(
test(
'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, editor }, testInfo) => {
async ({ scene, cmdBar, context, page, editor }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -149,24 +143,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
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, [110, 110, 110]), {
timeout: 10_000,
})
.toBeLessThan(20)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -209,7 +186,7 @@ test(
test(
'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) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const bracketDir = path.join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -235,24 +212,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
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, [125, 125, 125]), {
timeout: 10_000,
})
.toBeLessThan(15)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -352,7 +312,7 @@ test(
test(
'open a file in a project works and renders, open another file in the same project with errors, it should clear the scene',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
@ -380,10 +340,7 @@ test(
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -443,10 +400,10 @@ test(
await expect(page.getByText('broken-code')).toBeVisible()
await page.getByText('broken-code').click()
// Gotcha: You can not use scene.waitForExecutionDone() since the KCL code is going to fail
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
// Gotcha: You can not use scene.settled() since the KCL code is going to fail
await expect(
page.getByTestId('model-state-indicator-playing')
).toBeAttached()
// Gotcha: Scroll to the text content in code mirror because CodeMirror lazy loads DOM content
await editor.scrollToText(
@ -469,7 +426,7 @@ test.describe('Can export from electron app', () => {
test(
`Can export using ${method}`,
{ tag: ['@electron', '@skipLocalEngine'] },
async ({ context, page, tronApp }, testInfo) => {
async ({ scene, cmdBar, context, page, tronApp }, testInfo) => {
if (!tronApp) {
fail()
}
@ -499,10 +456,7 @@ test.describe('Can export from electron app', () => {
await page.getByText('bracket').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -812,7 +766,7 @@ test.describe(`Project management commands`, () => {
test(
`Rename from project page`,
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_rename`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -821,7 +775,6 @@ test.describe(`Project management commands`, () => {
`${dir}/${projectName}/main.kcl`
)
})
const u = await getUtils(page)
// Constants and locators
const projectHomeLink = page.getByTestId('project-link')
@ -843,7 +796,7 @@ test.describe(`Project management commands`, () => {
page.on('console', console.log)
await projectHomeLink.click()
await u.waitForPageLoad()
await scene.settled(cmdBar)
})
await test.step(`Run rename command via command palette`, async () => {
@ -882,7 +835,6 @@ test.describe(`Project management commands`, () => {
`${dir}/${projectName}/main.kcl`
)
})
const u = await getUtils(page)
// Constants and locators
const projectHomeLink = page.getByTestId('project-link')
@ -900,9 +852,9 @@ test.describe(`Project management commands`, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await page.waitForTimeout(3000)
await projectHomeLink.click()
await u.waitForPageLoad()
await scene.connectionEstablished()
await scene.settled(cmdBar)
})
@ -926,7 +878,7 @@ test.describe(`Project management commands`, () => {
test(
`Rename from home page`,
{ tag: '@electron' },
async ({ context, page, homePage }, testInfo) => {
async ({ context, page, homePage, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_rename`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -982,7 +934,7 @@ test.describe(`Project management commands`, () => {
test(
`Delete from home page`,
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
const projectName = `my_project_to_delete`
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(`${dir}/${projectName}`, { recursive: true })
@ -1033,6 +985,7 @@ test.describe(`Project management commands`, () => {
homePage,
toolbar,
cmdBar,
scene,
}) => {
const projectName = 'test-project'
await test.step(`Setup`, async () => {
@ -1072,10 +1025,11 @@ test.describe(`Project management commands`, () => {
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
await scene.settled(cmdBar)
await toolbar.logoLink.click()
})
await test.step(`Check the project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
@ -1106,10 +1060,11 @@ test.describe(`Project management commands`, () => {
})
await cmdBar.argumentInput.fill(projectName)
await cmdBar.progressCmdBar()
await scene.settled(cmdBar)
await toolbar.logoLink.click()
})
await test.step(`Check the second project was created with a non-colliding name`, async () => {
await toolbar.logoLink.click()
await homePage.expectState({
projectCards: [
{
@ -1195,7 +1150,7 @@ test(
test(
'Nested directories in project without main.kcl do not create main.kcl',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
let testDir: string | undefined
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(path.join(dir, 'router-template-slate', 'nested'), {
@ -1218,10 +1173,7 @@ test(
await test.step('Open the project', async () => {
await page.getByText('router-template-slate').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
// It actually loads.
await expect(u.codeLocator).toContainText('mounting bracket')
@ -1334,7 +1286,7 @@ test(
test(
'Can load a file with CRLF line endings',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ context, page, scene, cmdBar }, testInfo) => {
if (runningOnWindows()) {
test.fixme(orRunWhenFullSuiteEnabled())
}
@ -1357,13 +1309,8 @@ test(
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
await page.getByText('router-template-slate').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await expect(u.codeLocator).toContainText('routerDiameter')
await expect(u.codeLocator).toContainText('templateGap')
@ -1578,7 +1525,7 @@ extrude001 = extrude(sketch001, length = 200)`)
test(
'Opening a project should successfully load the stream, (regression test that this also works when switching between projects)',
{ tag: '@electron' },
async ({ context, page, cmdBar, homePage }, testInfo) => {
async ({ context, page, cmdBar, homePage, scene }, testInfo) => {
await context.folderSetupFn(async (dir) => {
await fsp.mkdir(path.join(dir, 'router-template-slate'), {
recursive: true,
@ -1607,13 +1554,10 @@ test(
path.join(dir, 'bracket', 'main.kcl')
)
})
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
const pointOnModel = { x: 630, y: 280 }
await test.step('Opening the bracket project via command palette should load the stream', async () => {
await homePage.expectState({
projectCards: [
@ -1647,15 +1591,7 @@ test(
stage: 'commandBarClosed',
})
await u.waitForPageLoad()
// 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)
await scene.settled(cmdBar)
})
await test.step('Clicking the logo takes us back to the projects page / home', async () => {
@ -1672,15 +1608,7 @@ test(
await page.getByText('router-template-slate').click()
await u.waitForPageLoad()
// 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, [143, 143, 143]), {
timeout: 10_000,
})
.toBeLessThan(15)
await scene.settled(cmdBar)
})
await test.step('The projects on the home page should still be normal', async () => {
@ -1733,8 +1661,6 @@ test(
})
await page.setBodyDimensions({ width: 1200, height: 500 })
page.on('console', console.log)
// we'll grab this from the settings on screen before we switch
let originalProjectDirName: string
const newProjectDirName = testInfo.outputPath(
@ -1875,7 +1801,7 @@ test(
test(
'file pane is scrollable when there are many files',
{ tag: '@electron' },
async ({ context, page }, testInfo) => {
async ({ scene, cmdBar, context, page }, testInfo) => {
await context.folderSetupFn(async (dir) => {
const testDir = path.join(dir, 'testProject')
await fsp.mkdir(testDir, { recursive: true })
@ -1954,10 +1880,8 @@ test(
await test.step('setup, open file pane', async () => {
await page.getByText('testProject').click()
await expect(page.getByTestId('loading')).toBeAttached()
await expect(page.getByTestId('loading')).not.toBeAttached({
timeout: 20_000,
})
await scene.settled(cmdBar)
await page.getByTestId('files-pane-button').click()
})

View File

@ -63,7 +63,7 @@ test.describe('edit with AI example snapshots', () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 351 }
const [clickBody1Cap] = scene.makeMouseHelpers(

View File

@ -61,7 +61,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 }
const greenCheckCoords = { x: 565, y: 305 }
@ -156,7 +156,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const body1CapCoords = { x: 571, y: 311 }
const [clickBody1Cap] = scene.makeMouseHelpers(
@ -212,7 +212,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')
@ -281,7 +281,7 @@ test.describe('Prompt-to-edit tests', { tag: '@skipWin' }, () => {
localStorage.setItem('persistCode', file)
}, file)
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const submittingToast = page.getByText('Submitting to Text-to-CAD API...')
const successToast = page.getByText('Prompt to edit successful')

View File

@ -689,6 +689,7 @@ extrude002 = extrude(profile002, length = 150)
homePage,
scene,
toolbar,
viewport,
}) => {
await context.folderSetupFn(async (dir) => {
const legoDir = path.join(dir, 'lego')
@ -703,8 +704,8 @@ extrude002 = extrude(profile002, length = 150)
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(`Waiting for scene to settle`, async () => {
await scene.connectionEstablished()
})
await test.step(`The part should start loading quickly, not waiting until execution is complete`, async () => {
// TODO: use the viewport size to pick the center point, but the `viewport` fixture's values were wrong.
@ -762,7 +763,7 @@ plane002 = offsetPlane(XZ, offset = -2 * x)`
)
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 20_000 })
const operationButton = await toolbar.getFeatureTreeOperation(
'Offset Plane',

View File

@ -22,6 +22,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
context,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
const selectionsSnippets = {
@ -82,7 +83,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
// wait for execution done
await u.openDebugPanel()
@ -108,6 +109,7 @@ test.describe('Sketch tests', { tag: ['@skipWin'] }, () => {
page,
scene,
homePage,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -122,7 +124,7 @@ sketch001 = startSketchOn(XZ)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await scene.expectPixelColor(TEST_COLORS.WHITE, { x: 587, y: 270 }, 15)
@ -673,6 +675,7 @@ sketch001 = startSketchOn(XZ)
homePage,
scene,
editor,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async () => {
@ -689,7 +692,7 @@ sketch001 = startSketchOn(XZ)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
@ -1614,7 +1617,7 @@ profile002 = startProfileAt([117.2, 56.08], sketch001)
test(
`snapToProfile start only works for current profile`,
{ tag: ['@skipWin'] },
async ({ context, page, scene, toolbar, editor, homePage }) => {
async ({ context, page, scene, toolbar, editor, homePage, cmdBar }) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
localStorage.setItem(
@ -1630,6 +1633,8 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
})
await homePage.goToModelingScene()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
@ -1651,9 +1656,13 @@ profile003 = startProfileAt([206.63, -56.73], sketch001)
const codeFromTangentialArc = ` |> tangentialArcTo([39.49, 88.22], %)`
await test.step('check that tangential tool does not snap to other profile starts', async () => {
await toolbar.tangentialArcBtn.click()
await page.waitForTimeout(1000)
await endOfLowerSegMove()
await page.waitForTimeout(1000)
await endOfLowerSegClick()
await page.waitForTimeout(1000)
await profileStartOfHigherSegClick()
await page.waitForTimeout(1000)
await editor.expectEditor.toContain(codeFromTangentialArc)
await editor.expectEditor.not.toContain(
`[profileStartX(%), profileStartY(%)]`
@ -2242,8 +2251,9 @@ profile004 = circleThreePoint(sketch001, p1 = [13.44, -6.8], p2 = [13.39, -2.07]
await test.step('enter sketch and setup', async () => {
await moveToClearToolBarPopover()
await page.waitForTimeout(1000)
await pointOnSegment({ shouldDbClick: true })
await page.waitForTimeout(600)
await page.waitForTimeout(2000)
await toolbar.lineBtn.click()
await page.waitForTimeout(100)
@ -2359,7 +2369,7 @@ profile003 = circle(sketch001, center = [6.92, -4.2], radius = 3.16)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
@ -2965,6 +2975,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
toolbar,
editor,
homePage,
cmdBar,
}) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
@ -2982,7 +2993,7 @@ test.describe(`Click based selection don't brick the app when clicked out of ran
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await test.step(`format the code`, async () => {
// doesn't contain condensed version
@ -3047,6 +3058,7 @@ test.describe('Redirecting to home page and back to the original file should cle
toolbar,
editor,
homePage,
cmdBar,
}) => {
// We seed the scene with a single offset plane
await context.addInitScript(() => {
@ -3059,7 +3071,7 @@ test.describe('Redirecting to home page and back to the original file should cle
)
})
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
const [objClick] = scene.makeMouseHelpers(634, 274)
await objClick()

View File

@ -103,7 +103,6 @@ part001 = startSketchOn(-XZ)
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
const axisDirectionPair: Models['AxisDirectionPair_type'] = {
@ -369,7 +368,6 @@ const extrudeDefaultPlane = async (
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page).toHaveScreenshot({
@ -421,8 +419,6 @@ test(
const PUR = 400 / 37.5 //pixeltoUnitRatio
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
const startXPx = 600
const [endOfTangentClk, endOfTangentMv] = scene.makeMouseHelpers(
startXPx + PUR * 30,
@ -551,8 +547,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
// click on "Start Sketch" button
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
@ -598,8 +592,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
200
@ -650,8 +642,6 @@ test.describe(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await u.doAndWaitForImageDiff(
() => page.getByRole('button', { name: 'Start Sketch' }).click(),
200
@ -744,7 +734,6 @@ test.describe(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.doAndWaitForImageDiff(
@ -846,7 +835,6 @@ part002 = startSketchOn(part001, seg01)
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -902,7 +890,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -943,7 +930,6 @@ test(
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
// Wait for the second extrusion to appear
@ -976,7 +962,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1041,7 +1026,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1086,7 +1070,6 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
await page.goto('/')
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await u.closeKclCodePanel()
@ -1205,7 +1188,6 @@ sweepSketch = startSketchOn(XY)
await page.setViewportSize({ width: 1200, height: 1000 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page, 'expect small color widget').toHaveScreenshot({
@ -1255,7 +1237,6 @@ sweepSketch = startSketchOn(XY)
await page.setViewportSize({ width: 1200, height: 1000 })
await u.waitForAuthSkipAppStart()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await expect(page.locator('.cm-css-color-picker-wrapper')).toBeVisible()

View File

@ -80,7 +80,8 @@ export const TEST_SETTINGS_CORRUPTED = {
},
} satisfies Partial<SaveSettingsPayload>
export const TEST_CODE_GIZMO = `part001 = startSketchOn(XZ)
export const TEST_CODE_GIZMO = `@settings(defaultLengthUnit = in)
part001 = startSketchOn(XZ)
|> startProfileAt([20, 0], %)
|> line(end = [7.13, 4 + 0])
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)

View File

@ -89,7 +89,7 @@ test.describe('Test network and connection issues', () => {
test(
'Engine disconnect & reconnect in sketch mode',
{ tag: '@skipLocalEngine' },
async ({ page, homePage, toolbar }) => {
async ({ page, homePage, toolbar, scene, cmdBar }) => {
test.fixme(orRunWhenFullSuiteEnabled())
const networkToggle = page.getByTestId('network-toggle')
@ -169,7 +169,7 @@ test.describe('Test network and connection issues', () => {
// Expect the network to be up
await expect(networkToggle).toContainText('Connected')
await expect(page.getByTestId('loading-stream')).not.toBeAttached()
await scene.settled(cmdBar)
// Click off the code pane.
await page.mouse.click(100, 100)

View File

@ -74,7 +74,10 @@ async function waitForPageLoadWithRetry(page: Page) {
await expect(async () => {
await page.goto('/')
const errorMessage = 'App failed to load - 🔃 Retrying ...'
await expect(page.getByTestId('loading'), errorMessage).not.toBeAttached({
await expect(
page.getByTestId('model-state-indicator-playing'),
errorMessage
).toBeAttached({
timeout: 20_000,
})
@ -87,9 +90,10 @@ async function waitForPageLoadWithRetry(page: Page) {
}).toPass({ timeout: 70_000, intervals: [1_000] })
}
// lee: This needs to be replaced by scene.settled() eventually.
async function waitForPageLoad(page: Page) {
// wait for all spinners to be gone
await expect(page.getByTestId('loading')).not.toBeAttached({
await expect(page.getByTestId('model-state-indicator-playing')).toBeVisible({
timeout: 20_000,
})
@ -871,9 +875,10 @@ export async function tearDown(page: Page, testInfo: TestInfo) {
export async function setup(
context: BrowserContext,
page: Page,
testDir: string,
testInfo?: TestInfo
) {
await context.addInitScript(
await page.addInitScript(
async ({
token,
settingsKey,
@ -914,7 +919,7 @@ export async function setup(
},
}),
IS_PLAYWRIGHT_KEY,
PLAYWRIGHT_TEST_DIR: TEST_SETTINGS.project?.directory || '',
PLAYWRIGHT_TEST_DIR: testDir,
PERSIST_MODELING_CONTEXT,
}
)
@ -934,7 +939,7 @@ export async function setup(
await page.emulateMedia({ reducedMotion: 'reduce' })
// Trigger a navigation, since loading file:// doesn't.
// await page.reload()
await page.reload()
}
function failOnConsoleErrors(page: Page, testInfo?: TestInfo) {

View File

@ -5,12 +5,18 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing Camera Movement', { tag: ['@skipWin'] }, () => {
test('Can move camera reliably', async ({ page, context, homePage }) => {
test('Can move camera reliably', async ({
page,
context,
homePage,
scene,
}) => {
const u = await getUtils(page)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.connectionEstablished()
await u.openAndClearDebugPanel()
await u.closeKclCodePanel()

View File

@ -77,7 +77,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
})
.toBe(false)
})
test(`Remove constraints`, async ({ page, homePage }) => {
test(`Remove constraints`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -101,7 +101,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -142,7 +142,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, offset } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -166,7 +166,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4], tag = $seg01)').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -250,7 +250,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, value, constraint } of cases) {
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
test(`${constraint} - ${testName}`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -274,7 +279,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -361,7 +366,12 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${constraint} - ${testName}`, async ({ page, homePage }) => {
test(`${constraint} - ${testName}`, async ({
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -385,7 +395,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -475,7 +485,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, axisSelect } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -499,7 +509,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -578,7 +588,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${testName}`, async ({ page, homePage }) => {
test(`${testName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -602,7 +612,7 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -655,7 +665,14 @@ test.describe('Testing constraints', { tag: ['@skipWin'] }, () => {
},
] as const
for (const { testName, addVariable, value, constraint } of cases) {
test(`${testName}`, async ({ context, homePage, page, editor }) => {
test(`${testName}`, async ({
context,
homePage,
page,
editor,
scene,
cmdBar,
}) => {
// constants and locators
const cmdBarKclInput = page
.getByTestId('cmd-bar-arg-value')
@ -689,7 +706,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await editor.scrollToText('line(end = [74.36, 130.4])', true)
await page.getByText('line(end = [74.36, 130.4])').click()
@ -746,7 +763,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async (customCode) => {
localStorage.setItem(
'persistCode',
@ -770,7 +787,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -848,7 +865,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -871,7 +888,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1000, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -930,7 +947,7 @@ part002 = startSketchOn(XZ)
},
] as const
for (const { codeAfter, constraintName, axisClick } of cases) {
test(`${constraintName}`, async ({ page, homePage }) => {
test(`${constraintName}`, async ({ page, homePage, scene, cmdBar }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -953,7 +970,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [74.36, 130.4])').click()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
@ -994,6 +1011,8 @@ part002 = startSketchOn(XZ)
test('Horizontally constrained line remains selected after applying constraint', async ({
page,
homePage,
scene,
cmdBar,
}) => {
test.fixme(orRunWhenFullSuiteEnabled())
test.setTimeout(70_000)
@ -1010,7 +1029,7 @@ part002 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.settled(cmdBar)
await page.getByText('line(end = [3.79, 2.68], tag = $seg01)').click()
await expect(page.getByRole('button', { name: 'Edit Sketch' })).toBeEnabled(
@ -1129,7 +1148,7 @@ test.describe('Electron constraint tests', () => {
sortBy: 'last-modified-desc',
})
await homePage.openProject('test-sample')
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
})
async function clickOnFirstSegmentLabel() {

View File

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

View File

@ -2,7 +2,11 @@ import { getUtils, orRunWhenFullSuiteEnabled } from '@e2e/playwright/test-utils'
import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Test toggling perspective', () => {
test('via command palette and toggle', async ({ page, homePage }) => {
test('via command palette and toggle', async ({
page,
homePage,
toolbar,
}) => {
test.fixme(orRunWhenFullSuiteEnabled())
const u = await getUtils(page)
@ -14,7 +18,7 @@ test.describe('Test toggling perspective', () => {
y: screenHeight * 0.2,
}
const backgroundColor: [number, number, number] = [29, 29, 29]
const xzPlaneColor: [number, number, number] = [82, 55, 96]
const xzPlaneColor: [number, number, number] = [72, 55, 96]
const locationToHaveColor = async (color: [number, number, number]) => {
return u.getGreatestPixDiff(checkedScreenLocation, color)
}
@ -26,9 +30,29 @@ test.describe('Test toggling perspective', () => {
const commandToast = page.getByText(
`Set camera projection to "orthographic"`
)
const projectionToggle = page.getByRole('switch', {
name: 'Camera projection: ',
})
const checkSettingValue = async () => {
const settingsButton = page.getByRole('link', {
name: 'Settings',
exact: false,
})
let settingValue: string | null = null
await test.step(`Check the setting value`, async () => {
await settingsButton.click()
const userTab = page.getByRole('radio', { name: 'User' })
await userTab.click()
await expect(userTab).toBeChecked()
const setting = page.locator('#cameraProjection').first()
await expect(setting).toBeAttached()
await setting.scrollIntoViewIfNeeded()
settingValue = await setting.getByRole('combobox').inputValue()
await page.getByTestId('settings-close-button').click()
})
return settingValue
}
await test.step('Setup', async () => {
await page.setBodyDimensions({ width: screenWidth, height: screenHeight })
@ -39,8 +63,8 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('perspective')
})
// Extremely wild note: flicking between ortho and persp actually changes
@ -59,33 +83,22 @@ test.describe('Test toggling perspective', () => {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(15)
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
.toBeLessThan(30)
expect(await checkSettingValue()).toBe('orthographic')
})
await test.step(`Refresh the page and ensure the stream is loaded in ortho`, async () => {
await page.reload()
await page.waitForTimeout(1000)
await expect(toolbar.startSketchBtn).toBeEnabled({ timeout: 15_000 })
await u.closeKclCodePanel()
await expect
.poll(async () => locationToHaveColor(xzPlaneColor), {
timeout: 5000,
message: 'This spot should have the XZ plane color',
})
.toBeLessThan(15)
.toBeLessThan(30)
await expect(commandToast).not.toBeVisible()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'false')
})
await test.step(`Switch to perspective via toggle`, async () => {
await projectionToggle.click()
await expect(projectionToggle).toHaveAttribute('aria-checked', 'true')
await expect
.poll(async () => locationToHaveColor(backgroundColor), {
timeout: 5000,
message: 'This spot should have the background color',
})
.toBeLessThan(15)
expect(await checkSettingValue()).toBe('orthographic')
})
})
})

View File

@ -8,10 +8,11 @@ import { expect, test } from '@e2e/playwright/zoo-test'
test.describe('Testing in-app sample loading', () => {
/**
* 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
* Note this test implicitly depends on the KCL sample "parametric-bearing-pillow-block",
* its title, and its units settings. https://github.com/KittyCAD/kcl-samples/blob/main/parametric-bearing-pillow-block/main.kcl
*/
test('Web: should overwrite current code, cannot create new file', async ({
// We have no more web tests
test.skip('Web: should overwrite current code, cannot create new file', async ({
editor,
context,
page,
@ -29,8 +30,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const newSample = {
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
}
const commandBarButton = page.getByRole('button', { name: 'Commands' })
const samplesCommandOption = page.getByRole('option', {
@ -72,13 +73,13 @@ test.describe('Testing in-app sample loading', () => {
/**
* Note this test implicitly depends on the KCL samples:
* "a-parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/a-parametric-bearing-pillow-block/main.kcl
* "parametric-bearing-pillow-block": https://github.com/KittyCAD/kcl-samples/blob/main/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',
{ tag: '@electron' },
async ({ editor, context, page }, testInfo) => {
async ({ editor, context, page, scene, cmdBar }, testInfo) => {
const { dir } = await context.folderSetupFn(async (dir) => {
const bracketDir = join(dir, 'bracket')
await fsp.mkdir(bracketDir, { recursive: true })
@ -90,8 +91,8 @@ test.describe('Testing in-app sample loading', () => {
// Locators and constants
const sampleOne = {
file: 'a-parametric-bearing-pillow-block' + FILE_EXT,
title: 'A Parametric Bearing Pillow Block',
file: 'parametric-bearing-pillow-block' + FILE_EXT,
title: 'Parametric Bearing Pillow Block',
}
const sampleTwo = {
file: 'gear-rack' + FILE_EXT,
@ -125,7 +126,7 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Test setup`, async () => {
await page.setBodyDimensions({ width: 1200, height: 500 })
await projectCard.click()
await u.waitForPageLoad()
await scene.settled(cmdBar)
})
await test.step(`Precondition: check the initial code`, async () => {
@ -140,11 +141,14 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Load a KCL sample with the command palette`, async () => {
await commandBarButton.click()
await page.waitForTimeout(1000)
await commandOption.click()
await page.waitForTimeout(1000)
await commandSampleOption(sampleOne.title).click()
await expect(overwriteWarning).not.toBeVisible()
await expect(newFileWarning).toBeVisible()
await confirmButton.click()
await page.waitForTimeout(1000)
})
await test.step(`Ensure we made and opened a new file`, async () => {
@ -155,14 +159,20 @@ test.describe('Testing in-app sample loading', () => {
await test.step(`Now overwrite the current file`, async () => {
await commandBarButton.click()
await page.waitForTimeout(1000)
await commandOption.click()
await page.waitForTimeout(1000)
await commandSampleOption(sampleTwo.title).click()
await page.waitForTimeout(1000)
await commandMethodArgButton.click()
await page.waitForTimeout(1000)
await commandMethodOption.click()
await page.waitForTimeout(1000)
await expect(commandMethodArgButton).toContainText('overwrite')
await expect(newFileWarning).not.toBeVisible()
await expect(overwriteWarning).toBeVisible()
await confirmButton.click()
await page.waitForTimeout(1000)
})
await test.step(`Ensure we overwrote the current file without navigating`, async () => {

View File

@ -1520,6 +1520,8 @@ part001 = startSketchOn(XZ)
page,
editor,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(
async ({ lineToBeDeleted }) => {
@ -1541,7 +1543,8 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await u.waitForPageLoad()
await scene.connectionEstablished()
await scene.settled(cmdBar)
await page.waitForTimeout(300)
await page.getByText(before).click()

View File

@ -528,6 +528,8 @@ profile001 = startProfileAt([7.49, 9.96], sketch001)
test('Hovering over 3d features highlights code, clicking puts the cursor in the right place and sends selection id to engine', async ({
page,
homePage,
scene,
cmdBar,
}) => {
const u = await getUtils(page)
await page.addInitScript(async (KCL_DEFAULT_LENGTH) => {
@ -660,8 +662,8 @@ part001 = startSketchOn(XZ)
for (const rgb of RGBs) {
const [r, g, b] = rgb
const RGAverage = (r + g) / 2
const isRedGreenSameIsh = Math.abs(r - g) < 3
const isBlueLessThanRG = RGAverage - b > 45
const isRedGreenSameIsh = Math.abs(r - g) < 10
const isBlueLessThanRG = RGAverage - b > 40
const isYellowy = isRedGreenSameIsh && isBlueLessThanRG
if (isYellowy) return true
}
@ -779,11 +781,7 @@ part001 = startSketchOn(XZ)
)
`)
await expect(
page
.getByTestId('model-state-indicator-receive-reliable')
.or(page.getByTestId('model-state-indicator-execution-done'))
).toBeVisible()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({
@ -953,6 +951,7 @@ part001 = startSketchOn(XZ)
page,
homePage,
scene,
cmdBar,
}) => {
const cases = [
{
@ -989,7 +988,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({
@ -1024,6 +1023,7 @@ part001 = startSketchOn(XZ)
page,
homePage,
scene,
cmdBar,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
@ -1043,7 +1043,7 @@ part001 = startSketchOn(XZ)
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.waitForExecutionDone()
await scene.settled(cmdBar)
await u.openAndClearDebugPanel()
await u.sendCustomCmd({

View File

@ -55,7 +55,8 @@ test.describe('Testing settings', () => {
// Check that the invalid settings were changed to good defaults
expect(storedSettings.settings?.modeling?.base_unit).toBe('in')
expect(storedSettings.settings?.modeling?.mouse_controls).toBe('zoo')
expect(storedSettings.settings?.project?.directory).toBe('')
// Commenting this out because tests need this to be set to work properly.
// expect(storedSettings.settings?.app?.project_directory).toBe('')
expect(storedSettings.settings?.project?.default_project_name).toBe(
'untitled'
)
@ -865,6 +866,8 @@ test.describe('Testing settings', () => {
page,
homePage,
tronApp,
scene,
cmdBar,
}) => {
if (!tronApp) {
fail()
@ -886,6 +889,7 @@ test.describe('Testing settings', () => {
})
await page.setBodyDimensions({ width: 1200, height: 500 })
await homePage.goToModelingScene()
await scene.connectionEstablished()
// Constants and locators
const resizeHandle = page.locator('.sidebar-resize-handles > div.block')
@ -897,6 +901,7 @@ test.describe('Testing settings', () => {
async function setShowDebugPanelTo(value: 'On' | 'Off') {
await commandsButton.click()
await debugPaneOption.scrollIntoViewIfNeeded()
await debugPaneOption.click()
await page.getByRole('option', { name: value }).click()
await expect(

View File

@ -612,3 +612,12 @@ profile001 = startProfileAt([-12.34, 12.34], sketch002)
const sketch002 = extrude(sketch002, length = ${[5, 5]} + 7)`
await expect(page.locator('.cm-content')).toHaveText(result2.regExp)
})
test.fixme(
`Opening a share link in the web isn't blocked by the web warning banner`,
async () => {
// This test is not able to be run right now since we don't have a web-only setup for Playwright.
// @franknoirot can implement it when that testing infra is set up. It should be a test to cover the fix from
// modeling-app issue #6172.
}
)

View File

@ -17,7 +17,6 @@ declare module '@playwright/test' {
}
interface Page {
dir: string
TEST_SETTINGS_FILE_KEY?: string
setBodyDimensions: (dims: {
width: number
height: number

View File

@ -4,6 +4,7 @@ directories:
buildResources: assets
files:
- .vite/**
- "!node_modules/win-ca/pem/**"
mac:
category: public.app-category.developer-tools
artifactName: "${productName}-${version}-${arch}-${os}.${ext}"

1
interface.d.ts vendored
View File

@ -72,7 +72,6 @@ export interface IElectronAPI {
process: {
env: {
BASE_URL: string
TEST_SETTINGS_FILE_KEY: string
IS_PLAYWRIGHT: string
VITE_KC_DEV_TOKEN: string
VITE_KC_API_WS_MODELING_URL: string

View File

@ -4,10 +4,10 @@ $ dpdm --no-warning --no-tree -T --skip-dynamic-imports=circular src/index.tsx
02) src/lang/std/sketch.ts -> src/lang/modifyAst.ts
03) src/lang/std/sketch.ts -> src/lang/modifyAst.ts -> src/lang/std/sketchcombos.ts
04) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts
05) src/lib/singletons.ts -> src/lang/KclSingleton.ts
06) src/lib/singletons.ts -> src/lang/codeManager.ts
07) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
08) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
09) src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
05) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/engineStreamMachine.ts
06) src/lib/singletons.ts -> src/editor/manager.ts -> src/lib/selections.ts -> src/machines/appMachine.ts -> src/machines/settingsMachine.ts
07) src/machines/appMachine.ts -> src/machines/settingsMachine.ts -> src/machines/commandBarMachine.ts -> src/lib/commandBarConfigs/authCommandConfig.ts
08) src/lib/singletons.ts -> src/lang/codeManager.ts
09) src/lib/singletons.ts -> src/clientSideScene/sceneEntities.ts -> src/clientSideScene/segments.ts -> src/components/Toolbar/angleLengthInfo.ts
10) src/hooks/useModelingContext.ts -> src/components/ModelingMachineProvider.tsx -> src/components/Toolbar/Intersect.tsx -> src/components/SetHorVertDistanceModal.tsx -> src/lib/useCalculateKclExpression.ts
11) src/routes/Onboarding/index.tsx -> src/routes/Onboarding/Camera.tsx -> src/routes/Onboarding/utils.tsx

View File

@ -26,7 +26,7 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@headlessui/react": "^1.7.19",
"@headlessui/tailwindcss": "^0.2.2",
"@kittycad/lib": "2.0.26",
"@kittycad/lib": "2.0.28",
"@lezer/highlight": "^1.2.1",
"@lezer/lr": "^1.4.1",
"@react-hook/resize-observer": "^2.0.1",
@ -59,13 +59,14 @@
"react-modal-promise": "^1.0.2",
"react-router-dom": "^6.28.0",
"sketch-helpers": "^0.0.4",
"three": "^0.174.0",
"three": "^0.175.0",
"ua-parser-js": "^1.0.37",
"uuid": "^11.1.0",
"vscode-jsonrpc": "^8.2.1",
"vscode-languageserver-protocol": "^3.17.5",
"vscode-uri": "^3.1.0",
"web-vitals": "^3.5.2",
"win-ca": "^3.5.1",
"xstate": "^5.19.2",
"yargs": "^17.7.2"
},
@ -172,13 +173,13 @@
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-env": "^7.26.9",
"@electron-forge/cli": "^7.7.0",
"@electron-forge/plugin-fuses": "^7.7.0",
"@electron-forge/plugin-vite": "^7.7.0",
"@electron-forge/cli": "^7.8.0",
"@electron-forge/plugin-fuses": "^7.8.0",
"@electron-forge/plugin-vite": "^7.8.0",
"@electron/fuses": "^1.8.0",
"@electron/notarize": "^2.5.0",
"@iarna/toml": "^2.2.5",
"@lezer/generator": "^1.7.2",
"@lezer/generator": "^1.7.3",
"@nabla/vite-plugin-eslint": "^2.0.5",
"@playwright/test": "^1.51.1",
"@testing-library/jest-dom": "^5.14.1",
@ -189,17 +190,17 @@
"@types/isomorphic-fetch": "^0.0.39",
"@types/minimist": "^1.2.5",
"@types/mocha": "^10.0.10",
"@types/node": "^22.13.14",
"@types/node": "^22.14.0",
"@types/pixelmatch": "^5.2.6",
"@types/pngjs": "^6.0.4",
"@types/react": "^18.3.4",
"@types/react-dom": "^18.3.1",
"@types/react-modal": "^3.16.3",
"@types/three": "^0.174.0",
"@types/three": "^0.175.0",
"@types/ua-parser-js": "^0.7.39",
"@types/uuid": "^9.0.8",
"@types/wicg-file-system-access": "^2023.10.5",
"@types/ws": "^8.18.0",
"@types/wicg-file-system-access": "^2023.10.6",
"@types/ws": "^8.18.1",
"@vitejs/plugin-react": "^4.3.4",
"@vitest/web-worker": "^1.5.0",
"@xstate/cli": "^0.5.17",
@ -212,7 +213,7 @@
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-perf": "^3.3.3",
"eslint-plugin-suggest-no-throw": "^1.0.0",
@ -231,9 +232,9 @@
"setimmediate": "^1.0.5",
"tailwindcss": "^3.4.17",
"ts-node": "^10.0.0",
"typescript": "^5.8.2",
"typescript-eslint": "^8.26.1",
"vite": "^5.4.16",
"typescript": "^5.8.3",
"typescript-eslint": "^8.29.0",
"vite": "^5.4.17",
"vite-plugin-package-version": "^1.1.0",
"vite-plugin-top-level-await": "^1.5.0",
"vite-tsconfig-paths": "^4.3.2",

View File

@ -19,17 +19,17 @@
"types": "dist/index.d.ts",
"dependencies": {
"@codemirror/language": "^6.10.3",
"@codemirror/state": "^6.4.1",
"@codemirror/state": "^6.5.2",
"@lezer/highlight": "^1.2.1",
"typescript": "^5.7.2"
},
"devDependencies": {
"@lezer/generator": "^1.7.2",
"@lezer/generator": "^1.7.3",
"@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.9"
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.1"
},
"files": [
"dist/"

View File

@ -28,10 +28,10 @@
"@lezer/lr" "^1.0.0"
style-mod "^4.0.0"
"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.1", "@codemirror/state@^6.5.0":
version "6.5.0"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.0.tgz#e98dde85620618651543152fe1c2483300a0ccc9"
integrity sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==
"@codemirror/state@^6.0.0", "@codemirror/state@^6.5.0", "@codemirror/state@^6.5.2":
version "6.5.2"
resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6"
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
dependencies:
"@marijn/find-cluster-break" "^1.0.0"
@ -44,120 +44,130 @@
style-mod "^4.1.0"
w3c-keyname "^2.2.4"
"@esbuild/aix-ppc64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==
"@esbuild/aix-ppc64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8"
integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==
"@esbuild/android-arm64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052"
integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==
"@esbuild/android-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196"
integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==
"@esbuild/android-arm@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28"
integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==
"@esbuild/android-arm@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee"
integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==
"@esbuild/android-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e"
integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==
"@esbuild/android-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2"
integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==
"@esbuild/darwin-arm64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a"
integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
"@esbuild/darwin-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423"
integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==
"@esbuild/darwin-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22"
integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==
"@esbuild/darwin-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374"
integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==
"@esbuild/freebsd-arm64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e"
integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==
"@esbuild/freebsd-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6"
integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==
"@esbuild/freebsd-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261"
integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==
"@esbuild/freebsd-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809"
integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==
"@esbuild/linux-arm64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b"
integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==
"@esbuild/linux-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058"
integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==
"@esbuild/linux-arm@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9"
integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==
"@esbuild/linux-arm@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6"
integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==
"@esbuild/linux-ia32@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2"
integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==
"@esbuild/linux-ia32@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737"
integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==
"@esbuild/linux-loong64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df"
integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==
"@esbuild/linux-loong64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a"
integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==
"@esbuild/linux-mips64el@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe"
integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==
"@esbuild/linux-mips64el@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30"
integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==
"@esbuild/linux-ppc64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4"
integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==
"@esbuild/linux-ppc64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067"
integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==
"@esbuild/linux-riscv64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc"
integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==
"@esbuild/linux-riscv64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3"
integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==
"@esbuild/linux-s390x@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de"
integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==
"@esbuild/linux-s390x@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602"
integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==
"@esbuild/linux-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0"
integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==
"@esbuild/linux-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb"
integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==
"@esbuild/netbsd-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047"
integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==
"@esbuild/netbsd-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac"
integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==
"@esbuild/openbsd-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70"
integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==
"@esbuild/netbsd-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f"
integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==
"@esbuild/sunos-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b"
integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==
"@esbuild/openbsd-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f"
integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==
"@esbuild/win32-arm64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d"
integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==
"@esbuild/openbsd-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768"
integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==
"@esbuild/win32-ia32@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b"
integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==
"@esbuild/sunos-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb"
integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==
"@esbuild/win32-x64@0.21.5":
version "0.21.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c"
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
"@esbuild/win32-arm64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf"
integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==
"@esbuild/win32-ia32@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f"
integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==
"@esbuild/win32-x64@0.25.2":
version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz#839f72c2decd378f86b8f525e1979a97b920c67d"
integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==
"@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0"
@ -169,10 +179,10 @@
resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
"@lezer/generator@^1.7.2":
version "1.7.2"
resolved "https://registry.yarnpkg.com/@lezer/generator/-/generator-1.7.2.tgz#a491c91eb9f117ea803e748fa97574514156a2a3"
integrity sha512-CwgULPOPPmH54tv4gki18bElLCdJ1+FBC+nGVSVD08vFWDsMjS7KEjNTph9JOypDnet90ujN3LzQiW3CyVODNQ==
"@lezer/generator@^1.7.3":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@lezer/generator/-/generator-1.7.3.tgz#8bf9e99c7690dd31327425ca46706a380413f54d"
integrity sha512-vAI2O1tPF8QMMgp+bdUeeJCneJNkOZvqsrtyb4ohnFVFdboSqPwBEacnt0HH4E+5h+qsIwTHUSAhffU4hzKl1A==
dependencies:
"@lezer/common" "^1.1.0"
"@lezer/lr" "^1.3.0"
@ -218,159 +228,264 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz#9bd38df6a29afb7f0336d988bc8112af0c8816c0"
integrity sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==
"@rollup/rollup-android-arm-eabi@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz#1d8cc5dd3d8ffe569d8f7f67a45c7909828a0f66"
integrity sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==
"@rollup/rollup-android-arm64@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz#bd1a98390e15b76eeef907175a37c5f0f9e4d214"
integrity sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==
"@rollup/rollup-android-arm64@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz#9c136034d3d9ed29d0b138c74dd63c5744507fca"
integrity sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==
"@rollup/rollup-darwin-arm64@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz#bc6fa8a2cc77b5f367424e5e994e3537524e6879"
integrity sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==
"@rollup/rollup-darwin-arm64@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz#830d07794d6a407c12b484b8cf71affd4d3800a6"
integrity sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==
"@rollup/rollup-darwin-x64@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz#76059c91f06b17406347b127df10f065283b2e61"
integrity sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==
"@rollup/rollup-darwin-x64@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz#b26f0f47005c1fa5419a880f323ed509dc8d885c"
integrity sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==
"@rollup/rollup-freebsd-arm64@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz#83178315c0be4b4c8c1fd835e1952d2dc1eb4e6e"
integrity sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==
"@rollup/rollup-freebsd-arm64@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz#2b60c81ac01ff7d1bc8df66aee7808b6690c6d19"
integrity sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==
"@rollup/rollup-freebsd-x64@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz#1ef24fa0576bf7899a0a0a649156606dbd7a0d46"
integrity sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==
"@rollup/rollup-freebsd-x64@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz#4826af30f4d933d82221289068846c9629cc628c"
integrity sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==
"@rollup/rollup-linux-arm-gnueabihf@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz#443a6f5681bf4611caae42988994a6d8ee676216"
integrity sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==
"@rollup/rollup-linux-arm-gnueabihf@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz#a1f4f963d5dcc9e5575c7acf9911824806436bf7"
integrity sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==
"@rollup/rollup-linux-arm-musleabihf@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz#9738b27184102228637a683e5f35b22ea352394f"
integrity sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==
"@rollup/rollup-linux-arm-musleabihf@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz#e924b0a8b7c400089146f6278446e6b398b75a06"
integrity sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==
"@rollup/rollup-linux-arm64-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz#b5e9d5e30ff36a19bedd29c715ba18a1889ff269"
integrity sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==
"@rollup/rollup-linux-arm64-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz#cb43303274ec9a716f4440b01ab4e20c23aebe20"
integrity sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==
"@rollup/rollup-linux-arm64-musl@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz#1d8f68f0829b57f746ec03432ad046f1af014a98"
integrity sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==
"@rollup/rollup-linux-arm64-musl@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz#531c92533ce3d167f2111bfcd2aa1a2041266987"
integrity sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==
"@rollup/rollup-linux-loongarch64-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz#07027feb883408e74a3002c8e50caaedd288ae38"
integrity sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==
"@rollup/rollup-linux-loongarch64-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz#53403889755d0c37c92650aad016d5b06c1b061a"
integrity sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==
"@rollup/rollup-linux-powerpc64le-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz#544ce1b0847a9c1240425e86f33daceac7ec4e12"
integrity sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==
"@rollup/rollup-linux-powerpc64le-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz#f669f162e29094c819c509e99dbeced58fc708f9"
integrity sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==
"@rollup/rollup-linux-riscv64-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz#64be13d51852ec1e2dfbd25d997ed5f42f35ea6d"
integrity sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==
"@rollup/rollup-linux-riscv64-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz#4bab37353b11bcda5a74ca11b99dea929657fd5f"
integrity sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==
"@rollup/rollup-linux-riscv64-musl@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz#4d66be1ce3cfd40a7910eb34dddc7cbd4c2dd2a5"
integrity sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==
"@rollup/rollup-linux-s390x-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz#31f51e1e05c6264552d03875d9e2e673f0fd86e3"
integrity sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==
"@rollup/rollup-linux-s390x-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz#7181c329395ed53340a0c59678ad304a99627f6d"
integrity sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==
"@rollup/rollup-linux-x64-gnu@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz#f4c95b26f4ad69ebdb64b42f0ae4da2a0f617958"
integrity sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==
"@rollup/rollup-linux-x64-gnu@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz#00825b3458094d5c27cb4ed66e88bfe9f1e65f90"
integrity sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==
"@rollup/rollup-linux-x64-musl@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz#ab7be89192f72beb9ea6e2386186fefde4f69d82"
integrity sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==
"@rollup/rollup-linux-x64-musl@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz#81caac2a31b8754186f3acc142953a178fcd6fba"
integrity sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==
"@rollup/rollup-win32-arm64-msvc@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz#7f12efb8240b238346951559998802722944421e"
integrity sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==
"@rollup/rollup-win32-arm64-msvc@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz#3a3f421f5ce9bd99ed20ce1660cce7cee3e9f199"
integrity sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==
"@rollup/rollup-win32-ia32-msvc@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz#353d14d6eee943004d129796e4feddd3aa260921"
integrity sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==
"@rollup/rollup-win32-ia32-msvc@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz#a44972d5cdd484dfd9cf3705a884bf0c2b7785a7"
integrity sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==
"@rollup/rollup-win32-x64-msvc@4.29.1":
version "4.29.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz#c82f04a09ba481e13857d6f2516e072aaa51b7f4"
integrity sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==
"@rollup/rollup-win32-x64-msvc@4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz#bfe0214e163f70c4fec1c8f7bb8ce266f4c05b7e"
integrity sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==
"@types/estree@1.0.6", "@types/estree@^1.0.0":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
"@vitest/expect@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.9.tgz#b566ea20d58ea6578d8dc37040d6c1a47ebe5ff8"
integrity sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==
dependencies:
"@vitest/spy" "2.1.9"
"@vitest/utils" "2.1.9"
chai "^5.1.2"
tinyrainbow "^1.2.0"
"@types/estree@1.0.7":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8"
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
"@vitest/mocker@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.9.tgz#36243b27351ca8f4d0bbc4ef91594ffd2dc25ef5"
integrity sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==
"@vitest/expect@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.1.1.tgz#d64ddfdcf9e877d805e1eee67bd845bf0708c6c2"
integrity sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==
dependencies:
"@vitest/spy" "2.1.9"
"@vitest/spy" "3.1.1"
"@vitest/utils" "3.1.1"
chai "^5.2.0"
tinyrainbow "^2.0.0"
"@vitest/mocker@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.1.1.tgz#7689d99f87498684c71e9fe9defdbd13ffb7f1ac"
integrity sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==
dependencies:
"@vitest/spy" "3.1.1"
estree-walker "^3.0.3"
magic-string "^0.30.12"
magic-string "^0.30.17"
"@vitest/pretty-format@2.1.9", "@vitest/pretty-format@^2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.9.tgz#434ff2f7611689f9ce70cd7d567eceb883653fdf"
integrity sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==
"@vitest/pretty-format@3.1.1", "@vitest/pretty-format@^3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.1.1.tgz#5b4d577771daccfced47baf3bf026ad59b52c283"
integrity sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==
dependencies:
tinyrainbow "^1.2.0"
tinyrainbow "^2.0.0"
"@vitest/runner@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.9.tgz#cc18148d2d797fd1fd5908d1f1851d01459be2f6"
integrity sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==
"@vitest/runner@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.1.1.tgz#76b598700737089d66c74272b2e1c94ca2891a49"
integrity sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==
dependencies:
"@vitest/utils" "2.1.9"
pathe "^1.1.2"
"@vitest/utils" "3.1.1"
pathe "^2.0.3"
"@vitest/snapshot@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.9.tgz#24260b93f798afb102e2dcbd7e61c6dfa118df91"
integrity sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==
"@vitest/snapshot@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.1.1.tgz#42b6aa0d0e2b3b48b95a5c76efdcc66a44cb11f3"
integrity sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==
dependencies:
"@vitest/pretty-format" "2.1.9"
magic-string "^0.30.12"
pathe "^1.1.2"
"@vitest/pretty-format" "3.1.1"
magic-string "^0.30.17"
pathe "^2.0.3"
"@vitest/spy@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.9.tgz#cb28538c5039d09818b8bfa8edb4043c94727c60"
integrity sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==
"@vitest/spy@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.1.1.tgz#deca0b025e151302ab514f38390fd7777e294837"
integrity sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==
dependencies:
tinyspy "^3.0.2"
"@vitest/utils@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.9.tgz#4f2486de8a54acf7ecbf2c5c24ad7994a680a6c1"
integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==
"@vitest/utils@3.1.1":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.1.1.tgz#2893c30219ab6bdf109f07ce5cd287fe8058438d"
integrity sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==
dependencies:
"@vitest/pretty-format" "2.1.9"
loupe "^3.1.2"
tinyrainbow "^1.2.0"
"@vitest/pretty-format" "3.1.1"
loupe "^3.1.3"
tinyrainbow "^2.0.0"
assertion-error@^2.0.1:
version "2.0.1"
@ -382,10 +497,10 @@ cac@^6.7.14:
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
chai@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.2.tgz#3afbc340b994ae3610ca519a6c70ace77ad4378d"
integrity sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==
chai@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05"
integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==
dependencies:
assertion-error "^2.0.1"
check-error "^2.1.1"
@ -398,7 +513,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.1.1, debug@^4.3.7:
debug@^4.1.1, debug@^4.4.0:
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==
@ -410,39 +525,41 @@ deep-eql@^5.0.1:
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341"
integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==
es-module-lexer@^1.5.4:
es-module-lexer@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21"
integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==
esbuild@^0.21.3:
version "0.21.5"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d"
integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==
esbuild@^0.25.0:
version "0.25.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.2.tgz#55a1d9ebcb3aa2f95e8bba9e900c1a5061bc168b"
integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==
optionalDependencies:
"@esbuild/aix-ppc64" "0.21.5"
"@esbuild/android-arm" "0.21.5"
"@esbuild/android-arm64" "0.21.5"
"@esbuild/android-x64" "0.21.5"
"@esbuild/darwin-arm64" "0.21.5"
"@esbuild/darwin-x64" "0.21.5"
"@esbuild/freebsd-arm64" "0.21.5"
"@esbuild/freebsd-x64" "0.21.5"
"@esbuild/linux-arm" "0.21.5"
"@esbuild/linux-arm64" "0.21.5"
"@esbuild/linux-ia32" "0.21.5"
"@esbuild/linux-loong64" "0.21.5"
"@esbuild/linux-mips64el" "0.21.5"
"@esbuild/linux-ppc64" "0.21.5"
"@esbuild/linux-riscv64" "0.21.5"
"@esbuild/linux-s390x" "0.21.5"
"@esbuild/linux-x64" "0.21.5"
"@esbuild/netbsd-x64" "0.21.5"
"@esbuild/openbsd-x64" "0.21.5"
"@esbuild/sunos-x64" "0.21.5"
"@esbuild/win32-arm64" "0.21.5"
"@esbuild/win32-ia32" "0.21.5"
"@esbuild/win32-x64" "0.21.5"
"@esbuild/aix-ppc64" "0.25.2"
"@esbuild/android-arm" "0.25.2"
"@esbuild/android-arm64" "0.25.2"
"@esbuild/android-x64" "0.25.2"
"@esbuild/darwin-arm64" "0.25.2"
"@esbuild/darwin-x64" "0.25.2"
"@esbuild/freebsd-arm64" "0.25.2"
"@esbuild/freebsd-x64" "0.25.2"
"@esbuild/linux-arm" "0.25.2"
"@esbuild/linux-arm64" "0.25.2"
"@esbuild/linux-ia32" "0.25.2"
"@esbuild/linux-loong64" "0.25.2"
"@esbuild/linux-mips64el" "0.25.2"
"@esbuild/linux-ppc64" "0.25.2"
"@esbuild/linux-riscv64" "0.25.2"
"@esbuild/linux-s390x" "0.25.2"
"@esbuild/linux-x64" "0.25.2"
"@esbuild/netbsd-arm64" "0.25.2"
"@esbuild/netbsd-x64" "0.25.2"
"@esbuild/openbsd-arm64" "0.25.2"
"@esbuild/openbsd-x64" "0.25.2"
"@esbuild/sunos-x64" "0.25.2"
"@esbuild/win32-arm64" "0.25.2"
"@esbuild/win32-ia32" "0.25.2"
"@esbuild/win32-x64" "0.25.2"
estree-walker@^2.0.2:
version "2.0.2"
@ -456,10 +573,10 @@ estree-walker@^3.0.3:
dependencies:
"@types/estree" "^1.0.0"
expect-type@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75"
integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==
expect-type@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.1.tgz#af76d8b357cf5fa76c41c09dafb79c549e75f71f"
integrity sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
@ -495,12 +612,17 @@ js-tokens@^4.0.0:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
loupe@^3.1.0, loupe@^3.1.2:
loupe@^3.1.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.2.tgz#c86e0696804a02218f2206124c45d8b15291a240"
integrity sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==
magic-string@^0.30.10, magic-string@^0.30.12:
loupe@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2"
integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==
magic-string@^0.30.10, magic-string@^0.30.17:
version "0.30.17"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==
@ -512,20 +634,20 @@ ms@^2.1.3:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@^3.3.7:
version "3.3.8"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
nanoid@^3.3.8:
version "3.3.11"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
pathe@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
pathe@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716"
integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==
pathval@^2.0.0:
version "2.0.0"
@ -542,12 +664,12 @@ picomatch@^4.0.2:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
postcss@^8.4.43:
version "8.4.49"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19"
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
postcss@^8.5.3:
version "8.5.3"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb"
integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==
dependencies:
nanoid "^3.3.7"
nanoid "^3.3.8"
picocolors "^1.1.1"
source-map-js "^1.2.1"
@ -569,7 +691,7 @@ rollup-plugin-dts@^6.1.1:
optionalDependencies:
"@babel/code-frame" "^7.24.2"
rollup@^4.20.0, rollup@^4.29.1:
rollup@^4.29.1:
version "4.29.1"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.29.1.tgz#a9aaaece817e5f778489e5bf82e379cc8a5c05bc"
integrity sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==
@ -597,6 +719,35 @@ rollup@^4.20.0, rollup@^4.29.1:
"@rollup/rollup-win32-x64-msvc" "4.29.1"
fsevents "~2.3.2"
rollup@^4.30.1:
version "4.39.0"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.39.0.tgz#9dc1013b70c0e2cb70ef28350142e9b81b3f640c"
integrity sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==
dependencies:
"@types/estree" "1.0.7"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.39.0"
"@rollup/rollup-android-arm64" "4.39.0"
"@rollup/rollup-darwin-arm64" "4.39.0"
"@rollup/rollup-darwin-x64" "4.39.0"
"@rollup/rollup-freebsd-arm64" "4.39.0"
"@rollup/rollup-freebsd-x64" "4.39.0"
"@rollup/rollup-linux-arm-gnueabihf" "4.39.0"
"@rollup/rollup-linux-arm-musleabihf" "4.39.0"
"@rollup/rollup-linux-arm64-gnu" "4.39.0"
"@rollup/rollup-linux-arm64-musl" "4.39.0"
"@rollup/rollup-linux-loongarch64-gnu" "4.39.0"
"@rollup/rollup-linux-powerpc64le-gnu" "4.39.0"
"@rollup/rollup-linux-riscv64-gnu" "4.39.0"
"@rollup/rollup-linux-riscv64-musl" "4.39.0"
"@rollup/rollup-linux-s390x-gnu" "4.39.0"
"@rollup/rollup-linux-x64-gnu" "4.39.0"
"@rollup/rollup-linux-x64-musl" "4.39.0"
"@rollup/rollup-win32-arm64-msvc" "4.39.0"
"@rollup/rollup-win32-ia32-msvc" "4.39.0"
"@rollup/rollup-win32-x64-msvc" "4.39.0"
fsevents "~2.3.2"
siginfo@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
@ -612,10 +763,10 @@ stackback@0.0.2:
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
std-env@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5"
integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
std-env@^3.8.1:
version "3.9.0"
resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.9.0.tgz#1a6f7243b339dca4c9fd55e1c7504c77ef23e8f1"
integrity sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==
style-mod@^4.0.0, style-mod@^4.1.0:
version "4.1.2"
@ -632,20 +783,20 @@ tinybench@^2.9.0:
resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
tinyexec@^0.3.1:
tinyexec@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2"
integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==
tinypool@^1.0.1:
tinypool@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2"
integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==
tinyrainbow@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5"
integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==
tinyrainbow@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294"
integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==
tinyspy@^3.0.2:
version "3.0.2"
@ -662,61 +813,61 @@ typescript@^5.7.2:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6"
integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==
vite-node@2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.9.tgz#549710f76a643f1c39ef34bdb5493a944e4f895f"
integrity sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==
vite-node@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.1.1.tgz#ad186c07859a6e5fca7c7f563e55fb11b16557bc"
integrity sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==
dependencies:
cac "^6.7.14"
debug "^4.3.7"
es-module-lexer "^1.5.4"
pathe "^1.1.2"
vite "^5.0.0"
debug "^4.4.0"
es-module-lexer "^1.6.0"
pathe "^2.0.3"
vite "^5.0.0 || ^6.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==
vite-tsconfig-paths@^5.1.4:
version "5.1.4"
resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-5.1.4.tgz#d9a71106a7ff2c1c840c6f1708042f76a9212ed4"
integrity sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==
dependencies:
debug "^4.1.1"
globrex "^0.1.2"
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.16"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.16.tgz#471983257a890ef33f2700cbbbc2134f2d08abf1"
integrity sha512-Y5gnfp4NemVfgOTDQAunSD4346fal44L9mszGGY/e+qxsRT5y1sMlS/8tiQ8AFAp+MFgYNSINdfEchJiPm41vQ==
"vite@^5.0.0 || ^6.0.0":
version "6.2.5"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.5.tgz#d093b5fe8eb96e594761584a966ab13f24457820"
integrity sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.43"
rollup "^4.20.0"
esbuild "^0.25.0"
postcss "^8.5.3"
rollup "^4.30.1"
optionalDependencies:
fsevents "~2.3.3"
vitest@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.9.tgz#7d01ffd07a553a51c87170b5e80fea3da7fb41e7"
integrity sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==
vitest@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.1.1.tgz#39fa2356e510513fccdc5d16465a9fc066ef1fc6"
integrity sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==
dependencies:
"@vitest/expect" "2.1.9"
"@vitest/mocker" "2.1.9"
"@vitest/pretty-format" "^2.1.9"
"@vitest/runner" "2.1.9"
"@vitest/snapshot" "2.1.9"
"@vitest/spy" "2.1.9"
"@vitest/utils" "2.1.9"
chai "^5.1.2"
debug "^4.3.7"
expect-type "^1.1.0"
magic-string "^0.30.12"
pathe "^1.1.2"
std-env "^3.8.0"
"@vitest/expect" "3.1.1"
"@vitest/mocker" "3.1.1"
"@vitest/pretty-format" "^3.1.1"
"@vitest/runner" "3.1.1"
"@vitest/snapshot" "3.1.1"
"@vitest/spy" "3.1.1"
"@vitest/utils" "3.1.1"
chai "^5.2.0"
debug "^4.4.0"
expect-type "^1.2.0"
magic-string "^0.30.17"
pathe "^2.0.3"
std-env "^3.8.1"
tinybench "^2.9.0"
tinyexec "^0.3.1"
tinypool "^1.0.1"
tinyrainbow "^1.2.0"
vite "^5.0.0"
vite-node "2.1.9"
tinyexec "^0.3.2"
tinypool "^1.0.2"
tinyrainbow "^2.0.0"
vite "^5.0.0 || ^6.0.0"
vite-node "3.1.1"
why-is-node-running "^2.3.0"
w3c-keyname@^2.2.4:

View File

@ -24,12 +24,12 @@
"@lezer/highlight": "^1.2.1",
"@ts-stack/markdown": "^1.5.0",
"json-rpc-2.0": "^1.7.0",
"typescript": "^5.8.2",
"typescript": "^5.8.3",
"vscode-languageserver-protocol": "^3.17.5",
"vscode-uri": "^3.1.0"
},
"devDependencies": {
"@types/node": "^22.13.13",
"@types/node": "^22.14.0",
"ts-node": "^10.9.2"
}
}

View File

@ -116,12 +116,12 @@
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@types/node@^22.13.13":
version "22.13.13"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.13.tgz#5e7d110fb509b0d4a43fbf48fa9d6e0f83e1b1e7"
integrity sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==
"@types/node@^22.14.0":
version "22.14.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.0.tgz#d3bfa3936fef0dbacd79ea3eb17d521c628bb47e"
integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==
dependencies:
undici-types "~6.20.0"
undici-types "~6.21.0"
acorn-walk@^8.1.1:
version "8.3.3"
@ -189,15 +189,15 @@ tslib@^2.3.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
typescript@^5.8.2:
version "5.8.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4"
integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==
typescript@^5.8.3:
version "5.8.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
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==
undici-types@~6.21.0:
version "6.21.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb"
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
v8-compile-cache-lib@^3.0.1:
version "3.0.1"

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define function
// Create a function to make the 80-20 rail
fn rail8020(originStart, railHeight, railLength) {
// Sketch side 1 of profile
sketch001 = startSketchOn(-XZ)

View File

@ -25,8 +25,6 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
---
#### [80-20-rail](80-20-rail/main.kcl) ([screenshot](screenshots/80-20-rail.png))
[![80-20-rail](screenshots/80-20-rail.png)](80-20-rail/main.kcl)
#### [a-parametric-bearing-pillow-block](a-parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/a-parametric-bearing-pillow-block.png))
[![a-parametric-bearing-pillow-block](screenshots/a-parametric-bearing-pillow-block.png)](a-parametric-bearing-pillow-block/main.kcl)
#### [ball-bearing](ball-bearing/main.kcl) ([screenshot](screenshots/ball-bearing.png))
[![ball-bearing](screenshots/ball-bearing.png)](ball-bearing/main.kcl)
#### [bench](bench/main.kcl) ([screenshot](screenshots/bench.png))
@ -83,6 +81,8 @@ When you submit a PR to add or modify KCL samples, images and STEP files will be
[![mounting-plate](screenshots/mounting-plate.png)](mounting-plate/main.kcl)
#### [multi-axis-robot](multi-axis-robot/main.kcl) ([screenshot](screenshots/multi-axis-robot.png))
[![multi-axis-robot](screenshots/multi-axis-robot.png)](multi-axis-robot/main.kcl)
#### [parametric-bearing-pillow-block](parametric-bearing-pillow-block/main.kcl) ([screenshot](screenshots/parametric-bearing-pillow-block.png))
[![parametric-bearing-pillow-block](screenshots/parametric-bearing-pillow-block.png)](parametric-bearing-pillow-block/main.kcl)
#### [pipe](pipe/main.kcl) ([screenshot](screenshots/pipe.png))
[![pipe](screenshots/pipe.png)](pipe/main.kcl)
#### [pipe-flange-assembly](pipe-flange-assembly/main.kcl) ([screenshot](screenshots/pipe-flange-assembly.png))

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants like ball diameter, inside diamter, overhange length, and thickness
// Define parameters
outsideDiameter = 1.625
sphereDia = 0.25
shaftDia = 0.75
@ -95,5 +95,3 @@ outsideWallSketch = startSketchOn(offsetPlane(XY, offset = -overallThickness / 2
|> hole(circle(center = [0, 0], radius = shaftDia / 2 + wallThickness + sphereDia), %)
outsideWall = extrude(outsideWallSketch, length = overallThickness)
// https://www.mcmaster.com/60355K185/

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "globals.kcl"
// Import parameters
import caliperTolerance, caliperPadLength, caliperThickness, caliperOuterEdgeRadius, caliperInnerEdgeRadius, rotorDiameter, rotorTotalThickness, yAxisOffset from "parameters.kcl"
// Sketch the brake caliper profile
brakeCaliperSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "globals.kcl"
// Import parameters
import rotorDiameter, rotorInnerDiameter, rotorSinglePlateThickness, rotorInnerDiameterThickness, lugHolePatternDia, lugSpacing, rotorTotalThickness, spacerPatternDiameter, spacerDiameter, spacerLength, spacerCount, wheelDiameter, lugCount, yAxisOffset, drillAndSlotCount from "parameters.kcl"
rotorSketch = startSketchOn(XZ)
|> circle(center = [0, 0], radius = rotorDiameter / 2)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "globals.kcl"
// Import parameters
import tireInnerDiameter, tireOuterDiameter, tireDepth, bendRadius, tireTreadWidth, tireTreadDepth, tireTreadOffset from "parameters.kcl"
// Create the sketch of the tire
tireSketch = startSketchOn(XY)

View File

@ -4,8 +4,8 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "globals.kcl"
// Import parameters
import lugCount, lugSpacing, offset, backSpacing, wheelWidth, wheelDiameter, spokeCount, spokeGap, spokeAngle, spokeThickness from "parameters.kcl"
// Create the wheel center
lugBase = startSketchOn(XZ)
@ -32,7 +32,7 @@ lugClearance = startSketchOn(lugExtrusion, 'END')
// Create the circular pattern for the lug holes
lugHoles = startSketchOn(lugBase, 'END')
|> circle(center = [lugSpacing / 2, 0], radius = 16 * mm() / 2)
|> circle(center = [lugSpacing / 2, 0], radius = fromMm(16) / 2)
|> patternCircular2d(
arcDegrees = 360,
center = [0, 0],

View File

@ -4,14 +4,14 @@
// Set units
@settings(defaultLengthUnit = in)
// Import Constants
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "globals.kcl"
// Import parameters
import lugDiameter, lugHeadLength, lugThreadDiameter, lugLength, lugThreadDepth, lugSpacing from "parameters.kcl"
customPlane = {
plane = {
origin = {
x = lugSpacing / 2,
y = -30 * mm(),
y = fromMm(-30),
z = 0
},
xAxis = { x = 1, y = 0, z = 0 },
@ -26,7 +26,7 @@ fn lug(plane, length, diameter) {
|> angledLineOfYLength({ angle = 70, length = lugHeadLength }, %)
|> xLine(endAbsolute = lugDiameter / 2)
|> yLine(endAbsolute = lugLength)
|> tangentialArc({ offset = 90, radius = 3 * mm() }, %)
|> tangentialArc({ offset = 90, radius = fromMm(3) }, %)
|> xLine(endAbsolute = 0 + .001, tag = $c1)
|> yLine(endAbsolute = lugThreadDepth)
|> xLine(endAbsolute = lugThreadDiameter)

View File

@ -4,16 +4,24 @@
// Set units
@settings(defaultLengthUnit = in)
// Import parts
import "car-wheel.kcl" as carWheel
import "car-rotor.kcl" as carRotor
import "brake-caliper.kcl" as brakeCaliper
import "lug-nut.kcl" as lugNut
import "car-tire.kcl" as carTire
import lugCount from "globals.kcl"
// Import parameters
import * from "parameters.kcl"
// Place the car rotor
carRotor
|> translate(x = 0, y = 0.5, z = 0)
// Place the car wheel
carWheel
// Place the lug nuts
lugNut
|> patternCircular3d(
arcDegrees = 360,
@ -22,6 +30,10 @@ lugNut
instances = lugCount,
rotateDuplicates = false,
)
// Place the brake caliper
brakeCaliper
|> translate(x = 0, y = 0.5, z = 0)
// Place the car tire
carTire

View File

@ -1,12 +1,12 @@
// Car wheel assembly global constants
// Car wheel assembly parameters
// Set units
@settings(defaultLengthUnit = in)
// Car Wheel
// Car wheel
export lugCount = 5
export lugSpacing = 114.3 * mm()
export offset = -35 * mm()
export lugSpacing = fromMm(114.3)
export offset = fromMm(-35)
export backSpacing = 6.38
export wheelWidth = 9.5
export wheelDiameter = 19
@ -16,13 +16,13 @@ export spokeAngle = 0.02
export spokeThickness = 0.95
// Lug Nut
export lugDiameter = 24 * mm()
export lugDiameter = fromMm(24)
export lugHeadLength = lugDiameter * .5
export lugThreadDiameter = lugDiameter / 2 * .85
export lugLength = 30 * mm()
export lugThreadDepth = lugLength - (12.7 * mm())
export lugLength = fromMm(30)
export lugThreadDepth = lugLength - fromMm(12.7)
// Car Rotor
// Car rotor
export rotorDiameter = 12
export rotorInnerDiameter = 6
export rotorSinglePlateThickness = 0.25
@ -36,7 +36,7 @@ export spacerCount = 16
export yAxisOffset = 0.5
export drillAndSlotCount = 5
// Car Tire
// Car tire
export tireInnerDiameter = 19
export tireOuterDiameter = 24
export tireDepth = 11.02
@ -45,7 +45,7 @@ export tireTreadWidth = 0.39
export tireTreadDepth = 0.39
export tireTreadOffset = 3.15
// Brake Caliper
// Brake caliper
export caliperTolerance = 0.050
export caliperPadLength = 1.6
export caliperThickness = 0.39

View File

@ -1,10 +1,10 @@
// Color Cube
// This is a color cube centered about the origin. It is used to help determine orientation in the scene.
// Set unit
// Set units
@settings(defaultLengthUnit = mm)
// Globals referenced in drawRectangle
// Parameters referenced in drawRectangle
size = 100
halfSize = size / 2
extrudeLength = 1.0

View File

@ -1,9 +1,10 @@
// Cycloidal Gear
// A cycloidal gear is a gear with a continuous, curved tooth profile. They are used in watchmaking and high precision robotics actuation
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Create a function for the cycloidal gear
fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
// Create a function to draw the gear profile as a sketch. Rotate each profile about the gear's axis by an helix angle proportional to the total gear height
fn gearSketch(gHeight) {
@ -44,4 +45,5 @@ fn cycloidalGear(gearPitch, gearHeight, holeDiameter, helixAngle) {
return gearLoft
}
// Call the cycloidal gear function
cycloidalGear(.3, 1.5, 0.297, -80)

View File

@ -9,19 +9,19 @@
circR = 25
// Calculated parameters
// thickness of the dodecahedron
// Thickness of the dodecahedron
wallThickness = circR * 0.2
// angle between faces in radians
// Angle between faces in radians
dihedral = acos(-(sqrt(5) / 5))
// inscribed radius
// Inscribed radius
inscR = circR / 15 * sqrt(75 + 30 * sqrt(5))
// pentagon edge length
// Pentagon edge length
edgeL = 4 * circR / (sqrt(3) * (1 + sqrt(5)))
// pentagon radius
// Pentagon radius
pentR = edgeL / 2 / sin(toRadians(36))
// Define a plane for the bottom angled face
@ -69,7 +69,7 @@ bottomBowl = patternCircular3d(
rotateDuplicates = true,
)
// pattern the bottom to create the top face
// Pattern the bottom to create the top face
patternCircular3d(
bottom,
instances = 2,
@ -79,7 +79,7 @@ patternCircular3d(
rotateDuplicates = true,
)
// pattern the bottom angled faces to create the top
// Pattern the bottom angled faces to create the top
patternCircular3d(
bottomBowl,
instances = 2,

View File

@ -1,10 +1,10 @@
// Dual-Basin Utility Sink
// A stainless steel sink unit with dual rectangular basins and six under-counter storage compartments.
// set units
// Set units
@settings(defaultLengthUnit = mm)
// globals
// Define parameters
tableHeight = 850
tableWidth = 3400
tableDepth = 400

View File

@ -4,6 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define parameters
length = 175
width = 125
height = 70

View File

@ -1,10 +1,10 @@
// Exhaust Manifold
// A welded exhaust header for an inline 4-cylinder engine
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define Constants
// Define parameters
primaryTubeDiameter = 1.625
wallThickness = 0.080
plateHeight = 0.125

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
mountingHoleDia = .625
baseDia = 4.625
pipeDia = 1.25

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// define constants in mm
// define parameters
radius = 6.0
width = 144.0
length = 80.0
@ -15,7 +15,7 @@ tabLength = 25
tabWidth = 12
tabThk = 4
// define a rectangular shape func
// Define a rectangular shape func
fn rectShape(pos, w, l) {
rr = startSketchOn('xy')
|> startProfileAt([pos[0] - (w / 2), pos[1] - (l / 2)], %)
@ -26,7 +26,7 @@ fn rectShape(pos, w, l) {
return rr
}
// define the bracket plane
// Define the bracket plane
bracketPlane = {
plane = {
origin = { x = 0, y = length / 2 + thk, z = 0 },
@ -36,7 +36,7 @@ bracketPlane = {
}
}
// build the bracket sketch around the body
// Build the bracket sketch around the body
fn bracketSketch(w, d, t) {
s = startSketchOn(bracketPlane)
|> startProfileAt([-w / 2 - t, d + t], %)
@ -51,7 +51,7 @@ fn bracketSketch(w, d, t) {
return s
}
// build the body of the bracket
// Build the body of the bracket
bs = bracketSketch(width, depth, thk)
bracketBody = bs
|> extrude(length = length + 2 * thk)
@ -65,7 +65,7 @@ bracketBody = bs
],
)
// define the tab plane
// Define the tab plane
tabPlane = {
plane = {
origin = { x = 0, y = 0, z = depth + thk },
@ -75,7 +75,7 @@ tabPlane = {
}
}
// build the tabs of the mounting bracket (right side)
// Build the tabs of the mounting bracket (right side)
tabsR = startSketchOn(tabPlane)
|> startProfileAt([width / 2 + thk, length / 2 + thk], %)
|> line(end = [tabWidth, -tabLength / 3], tag = $edge11)
@ -99,7 +99,7 @@ tabsR = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// build the tabs of the mounting bracket (left side)
// Build the tabs of the mounting bracket (left side)
tabsL = startSketchOn(tabPlane)
|> startProfileAt([-width / 2 - thk, length / 2 + thk], %)
|> line(end = [-tabWidth, -tabLength / 3], tag = $edge21)
@ -123,7 +123,7 @@ tabsL = startSketchOn(tabPlane)
)
|> patternLinear3d(axis = [0, -1, 0], instances = 2, distance = length + 2 * thk - (tabLength * 4 / 3))
// define a plane for retention bumps
// Define a plane for retention bumps
retPlane = {
plane = {
origin = { x = -width / 2 + 20, y = 0, z = 0 },
@ -133,7 +133,7 @@ retPlane = {
}
}
// build the retention bump in the front
// Build the retention bump in the front
retFront = startSketchOn(retPlane)
|> startProfileAt([-length / 2 - thk, 0], %)
|> line(end = [0, thk])
@ -141,7 +141,7 @@ retFront = startSketchOn(retPlane)
|> close()
|> extrude(length = width - 40)
// build the retention bump in the back
// Build the retention bump in the back
retBack = startSketchOn(retPlane)
|> startProfileAt([length / 2 + thk, 0], %)
|> line(end = [0, thk])

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = mm)
// Define constants in millimeters (mm)
// Define parameters
flipperThickness = 3.5
flipperLength = 70.0
handleWidth = 15.0
@ -16,7 +16,7 @@ gripHeight = 20.0
gripFilletRadius = 3.0
gripSlotWidth = 8.0
// function for drawing slots on a sketch given the start and end points as well as a width
// Function for drawing slots on a sketch given the start and end points as well as a width
fn slot(sketch1, start, end, width) {
angle = if start[0] == end[0] {
if end[1] > start[1] {
@ -43,10 +43,10 @@ fn slot(sketch1, start, end, width) {
return slotSketch
}
// create a sketch on the "XY" plane
// Create a sketch on the "XY" plane
sketch000 = startSketchOn(XY)
// create a profile of the flipper
// Create a profile of the flipper
flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
|> line(end = [flipperLength, 2.0])
|> yLine(length = 60.0, tag = $backEdge)
@ -58,25 +58,25 @@ flipperProfile = startProfileAt([-flipperLength, -32.0], sketch000)
}, %)
|> close()
// create a profile of the middle
// Create a profile of the middle
slotProfile000 = slot(sketch000, [-25, 0], [-55, 0], flipperSlotWidth)
// create a profile of the top slot
// Create a profile of the top slot
slotProfile001 = slot(sketch000, [-25, 18], [-55, 19], flipperSlotWidth)
// create a profile of the bottom slot
// Create a profile of the bottom slot
slotProfile002 = slot(sketch000, [-25, -18], [-55, -19], flipperSlotWidth)
// create a profile with slots for the spatula
// Create a profile with slots for the spatula
spatulaProfile = flipperProfile
|> hole(slotProfile000, %)
|> hole(slotProfile001, %)
|> hole(slotProfile002, %)
// extrude the profile to create the spatula flipper
// Extrude the profile to create the spatula flipper
flipper = extrude(spatulaProfile, length = flipperThickness)
// fillet the edges of the flipper
// Fillet the edges of the flipper
fillet(
flipper,
radius = flipperFilletRadius,
@ -86,10 +86,10 @@ fillet(
],
)
// create a sketch on the "XZ" plane offset by half the thickness
// Create a sketch on the "XZ" plane offset by half the thickness
sketch001 = startSketchOn(offsetPlane(XZ, offset = -handleWidth / 2))
// create a profile of the spatula handle
// Create a profile of the spatula handle
handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> line(end = [31.819805, 31.819805], tag = $handleBottomEdge)
|> line(end = [140.953893, 51.303021])
@ -99,10 +99,10 @@ handleProfile = startProfileAt([0.0, flipperThickness], sketch001)
|> xLine(length = 7.071068)
|> close()
// create an extrusion extrude001
// Create an extrusion extrude001
handle = extrude(handleProfile, length = handleWidth)
// fillet the bend of the spatula handle
// Fillet the bend of the spatula handle
fillet(
handle,
radius = 4,
@ -112,7 +112,7 @@ fillet(
],
)
// define a plane which is at the end of the handle
// Define a plane which is at the end of the handle
handlePlane = {
plane = {
origin = [208.593833, 0.0, 75.921946],
@ -122,10 +122,10 @@ handlePlane = {
}
}
// create a sketch on the handle plane
// Create a sketch on the handle plane
sketch002 = startSketchOn(handlePlane)
// create a profile of the grip
// Create a profile of the grip
gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
|> xLine(length = gripWidth - (2 * gripFilletRadius))
|> arc({
@ -153,14 +153,14 @@ gripProfile = startProfileAt([-26.806746, -10.0], sketch002)
}, %)
|> close()
// extrude the grip profile to create the grip
// Extrude the grip profile to create the grip
grip = extrude(gripProfile, length = -gripLength)
// create a sketch on the grip for the hole
// Create a sketch on the grip for the hole
sketch003 = startSketchOn(grip, gripEdgeTop)
// create a profile for the grip hole
// Create a profile for the grip hole
gripHoleProfile = slot(sketch003, [0, 200], [0, 210], gripSlotWidth)
// cut a hole in the grip
// Cut a hole in the grip
extrude(gripHoleProfile, length = -gripWidth - 20)

View File

@ -4,7 +4,7 @@
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
carafeDiameter = 4.41
carafeHeight = 7.32
handleThickness = 0.65

View File

@ -1,10 +1,10 @@
// 100mm Gear Rack
// 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.
// Set Units
// Set units
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
length = 100
pitchHeight = 11.5
width = 5

View File

@ -1,10 +1,10 @@
// Spur Gear
// 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.
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
nTeeth = 21
module = 0.5
pitchDiameter = module * nTeeth
@ -97,11 +97,11 @@ keyWay = startSketchOn(body, 'END')
|> xLine(length = -keywayDepth)
|> arc({
angleEnd = 180,
angleStart = -1 * 180 / PI * startAngle + 360,
angleStart = -1 * toDegrees(startAngle) + 360,
radius = holeRadius
}, %)
|> arc({
angleEnd = 180 / PI * startAngle,
angleEnd = toDegrees(startAngle),
angleStart = 180,
radius = holeRadius
}, %)

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -21,7 +21,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -33,10 +33,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -46,16 +46,16 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -65,7 +65,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -74,7 +74,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -83,7 +83,7 @@ basePlateCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the center cutout for the magnet profile
// Create the center cutout for the magnet profile
fn magnetCenterCutout(plane) {
magnetSketch = startSketchOn(plane)
|> startProfileAt([
@ -126,7 +126,7 @@ fn magnetCenterCutout(plane) {
return magnetSketch
}
// create the outside profile of the magnets
// Create the outside profile of the magnets
fn magnetBase(plane) {
magnetBaseSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -138,7 +138,7 @@ fn magnetBase(plane) {
return magnetBaseSketch
}
// create sketch profile sketch000Profile002
// Create sketch profile sketch000Profile002
magnetsSketch = startSketchOn(XY)
|> circle(center = [cornerRadius * 2, cornerRadius * 2], radius = magOuterDiam / 2)
|> patternCircular2d(
@ -148,14 +148,14 @@ magnetsSketch = startSketchOn(XY)
rotateDuplicates = true,
)
// create a profile with holes for the magnets
// Create a profile with holes for the magnets
magnetProfile = magnetBase(XY)
|> hole(magnetsSketch, %)
// create an extrusion of the magnet cutout with holes
// Create an extrusion of the magnet cutout with holes
magnetHolesExtrude = extrude(magnetProfile, length = -magDepth)
// add a fillet to the extrusion
// Add a fillet to the extrusion
magnetHolesExtrudeFillets = fillet(
magnetHolesExtrude,
radius = cornerRadius,
@ -167,13 +167,13 @@ magnetHolesExtrudeFillets = fillet(
],
)
// create a profile without the holes for the magnets
// Create a profile without the holes for the magnets
magnetProfileNoMagnets = magnetBase(offsetPlane(XY, offset = -magDepth))
// create an extrusion of the magnet cutout without holes
// Create an extrusion of the magnet cutout without holes
magnetCutoutExtrude = extrude(magnetProfileNoMagnets, length = -magDepth)
// add a fillet to the extrusion
// Add a fillet to the extrusion
magnetCutoutExtrudeFillets = fillet(
magnetCutoutExtrude,
radius = cornerRadius,
@ -185,7 +185,7 @@ magnetCutoutExtrudeFillets = fillet(
],
)
// pattern the magnet cutouts with holes
// Pattern the magnet cutouts with holes
patternLinear3d(
magnetHolesExtrudeFillets,
axis = [1.0, 0.0, 0.0],
@ -194,7 +194,7 @@ patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// pattern the magnet cutouts without holes
// Pattern the magnet cutouts without holes
patternLinear3d(
magnetCutoutExtrudeFillets,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 42.0
cornerRadius = 4.0
firstStep = 0.7
@ -18,7 +18,7 @@ countBinLength = 3
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -30,10 +30,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -43,16 +43,16 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -62,7 +62,7 @@ corners = patternCircular3d(
rotateDuplicates = true,
)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
basePlateSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -71,7 +71,7 @@ basePlateSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
basePlateCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -33,7 +33,7 @@ countBinHeight = 1
height = firstStep + secondStep + thirdStep
lipHeight = lipStep1 + lipStep2 + lipStep3 + lipStep4 + lipStep5
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -46,10 +46,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -63,7 +63,7 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
@ -72,10 +72,10 @@ axis000 = {
]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -128,7 +128,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -137,7 +137,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -146,7 +146,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the fill of the bin by patterning the corners
// Create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -155,7 +155,6 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
//
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)
@ -174,7 +173,7 @@ binTop = startSketchOn(offsetPlane(XY, offset = height))
)
|> shell(faces = ["end"], thickness = binThk)
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn lipFace(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([0, 0], %)
@ -234,13 +233,13 @@ plane002 = {
}
}
// extrude a single side of the lip of the bin
// Extrude a single side of the lip of the bin
lipSingleLength = extrude(lipFace(plane000), length = binLength * countBinWidth - (2 * cornerRadius) + 2 * binTol * countBinWidth)
// extrude a single side of the lip of the bin
// Extrude a single side of the lip of the bin
lipSingleWidth = extrude(lipFace(plane001), length = binLength * countBinLength - (2 * cornerRadius) + 2 * binTol * countBinLength)
// create the other sides of the lips by using a circular pattern
// Create the other sides of the lips by using a circular pattern
lipLengths = patternCircular3d(
lipSingleLength,
arcDegrees = 360,
@ -254,7 +253,7 @@ lipLengths = patternCircular3d(
rotateDuplicates = true,
)
// create the other sides of the lips by using a circular pattern
// Create the other sides of the lips by using a circular pattern
lipWidths = patternCircular3d(
lipSingleWidth,
arcDegrees = 360,
@ -268,19 +267,19 @@ lipWidths = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis001 = {
direction = [0.0, 1.0],
origin = [cornerRadius, cornerRadius]
}
// create a single corner of the bin
// Create a single corner of the bin
lipSingleLengthCorner = revolve(lipFace(plane000), angle = -90, axis = axis001)
// create a single corner of the bin
// Create a single corner of the bin
lipSingleWidthCorner = revolve(lipFace(plane002), angle = 90, axis = axis001)
// create the corners of the bin
// Create the corners of the bin
lipCorners000 = patternCircular3d(
lipSingleLengthCorner,
arcDegrees = 360,
@ -294,7 +293,7 @@ lipCorners000 = patternCircular3d(
rotateDuplicates = true,
)
// create the corners of the bin
// Create the corners of the bin
lipCorners001 = patternCircular3d(
lipSingleWidthCorner,
arcDegrees = 360,

View File

@ -4,7 +4,7 @@
// Set units in millimeters (mm)
@settings(defaultLengthUnit = mm)
// Define constants
// Define parameters
binLength = 41.5
binHeight = 7.0
binBaseLength = 2.95
@ -26,7 +26,7 @@ countBinHeight = 2
// The total height of the baseplate is a summation of the vertical heights of the baseplate steps
height = firstStep + secondStep + thirdStep
// define a function which builds the profile of the baseplate bin
// Define a function which builds the profile of the baseplate bin
fn face(plane) {
faceSketch = startSketchOn(plane)
|> startProfileAt([binBaseLength + binTol, 0], %)
@ -39,10 +39,10 @@ fn face(plane) {
return faceSketch
}
// extrude a single side of the bin
// Extrude a single side of the bin
singleSide = extrude(face(offsetPlane(YZ, offset = cornerRadius + binTol)), length = binLength - (cornerRadius * 2))
// create the other sides of the bin by using a circular pattern
// Create the other sides of the bin by using a circular pattern
sides = patternCircular3d(
singleSide,
arcDegrees = 360,
@ -56,7 +56,7 @@ sides = patternCircular3d(
rotateDuplicates = true,
)
// define an axis axis000
// Define an axis axis000
axis000 = {
direction = [0.0, 1.0],
origin = [
@ -65,10 +65,10 @@ axis000 = {
]
}
// create a single corner of the bin
// Create a single corner of the bin
singleCorner = revolve(face(offsetPlane(YZ, offset = cornerRadius + binTol)), angle = -90, axis = axis000)
// create the corners of the bin
// Create the corners of the bin
corners = patternCircular3d(
singleCorner,
arcDegrees = 360,
@ -121,7 +121,7 @@ magCutout000 = startSketchOn(singleBinFill, "start")
)
|> extrude(length = -magDepth)
// create the baseplate by patterning sides
// Create the baseplate by patterning sides
binSides = patternLinear3d(
sides,
axis = [1.0, 0.0, 0.0],
@ -130,7 +130,7 @@ binSides = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the corners of the baseplate by patterning the corners
// Create the corners of the baseplate by patterning the corners
binCorners = patternLinear3d(
corners,
axis = [1.0, 0.0, 0.0],
@ -139,7 +139,7 @@ binCorners = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the fill of the bin by patterning the corners
// Create the fill of the bin by patterning the corners
binFill = patternLinear3d(
singleBinFill,
axis = [1.0, 0.0, 0.0],
@ -148,7 +148,7 @@ binFill = patternLinear3d(
)
|> patternLinear3d(axis = [0.0, 1.0, 0.0], instances = countBinLength, distance = binLength + binTol * 2)
// create the top of the bin
// Create the top of the bin
binTop = startSketchOn(offsetPlane(XY, offset = height))
|> startProfileAt([0, 0], %)
|> xLine(length = (binLength + 2 * binTol) * countBinWidth, tag = $line010)

View File

@ -1,10 +1,10 @@
// Hex nut
// Hex Nut
// 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.
// Set Units
@settings(defaultLengthUnit = in)
// Define constants (5/16" - 24 thread size)
// Define parameters (5/16" - 24 thread size)
wallToWallLength = 0.5
thickness = 0.266
diameter = 0.3125

View File

@ -1,11 +1,11 @@
// I-beam
// A structural metal beam with an I shaped cross section. Often used in construction and architecture
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define Beam Dimensions
beamLength = 6 * ft()
// Define parameters
beamLength = fromFt(6)
beamHeight = 4
flangeWidth = 2.663
flangeThickness = 0.293
@ -13,7 +13,7 @@ webThickness = 0.193
rootRadius = 0.457
// Sketch a quadrant of the beam cross section, then mirror for symmetry across each axis. Extrude to the appropriate length
sketch001 = startSketchOn(-XZ)
iBeam = startSketchOn(-XZ)
|> startProfileAt([0, beamHeight / 2], %)
|> xLine(length = flangeWidth / 2)
|> yLine(length = -flangeThickness)

View File

@ -1,10 +1,10 @@
// Zoo Keyboard
// A custom keyboard with Zoo brand lettering
// Set Units
// Set units
@settings(defaultLengthUnit = in)
// Define constants
// Define parameters
baseColor = "#0f0f0f"
highlightColor1 = "#b0b0b0"
highlightColor2 = "#23af93"

View File

@ -1,7 +1,7 @@
// Kitt
// The beloved KittyCAD mascot in a voxelized style.
// pixel box function
// Pixel box function
fn pixelBox(kitExtrude, extrudeTag, positionY, positionZ, width, height, depth) {
pixelBoxBody = startSketchOn(kitExtrude, extrudeTag)
|> startProfileAt([positionY, positionZ], %)

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