Compare commits
45 Commits
v0.22.7
...
kurt-skip-
Author | SHA1 | Date | |
---|---|---|---|
0d7049d90f | |||
8ebe78c664 | |||
a85c1a9375 | |||
5701616f3e | |||
846acaba2f | |||
0a524d42f6 | |||
fe28527ef9 | |||
0e8d0083c4 | |||
4f4167b247 | |||
fbc2e9d02c | |||
33b15e818b | |||
6cebb84ae0 | |||
85403e47e4 | |||
0dfee64e3b | |||
6370d45f94 | |||
fb3e922180 | |||
1257ec0327 | |||
08e9fe2e52 | |||
7cec1d45fe | |||
93710bc8f2 | |||
87e7e9447f | |||
8be113d284 | |||
7cfc927d5c | |||
c0f04d5f86 | |||
3dbc701f26 | |||
16e7ae38e3 | |||
24c7260327 | |||
72cfc4a471 | |||
2d128ed32e | |||
cd6749ba02 | |||
7243405e1b | |||
c8da057ec2 | |||
220fe5b2b8 | |||
4e6429de49 | |||
5391a65b18 | |||
592628917a | |||
4c6e8633f7 | |||
c5150468a2 | |||
39126dbff1 | |||
f86a69f12a | |||
de354ee5d3 | |||
dfef7338ee | |||
ee08948f54 | |||
832f6b65e2 | |||
68efd77c5d |
3
.github/workflows/ci.yml
vendored
@ -138,6 +138,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
|
if: github.event_name == 'schedule'
|
||||||
|
|
||||||
- name: Copy updated .json files
|
- name: Copy updated .json files
|
||||||
if: github.event_name == 'schedule'
|
if: github.event_name == 'schedule'
|
||||||
@ -377,6 +378,8 @@ jobs:
|
|||||||
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
|
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
|
||||||
|
|
||||||
publish-apps-release:
|
publish-apps-release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
|
||||||
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
|
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
|
||||||
|
26
README.md
@ -124,36 +124,20 @@ Before you submit a contribution PR to this repo, please ensure that:
|
|||||||
|
|
||||||
## Release a new version
|
## Release a new version
|
||||||
|
|
||||||
1. Bump the versions in the .json files by creating a `Cut release v{x}.{y}.{z}` PR, committing the changes from
|
1. Bump the versions by running `./make-realease.sh` while on a fresh pull of main
|
||||||
|
|
||||||
```bash
|
That will create the branch with the updated json files for you.
|
||||||
VERSION=x.y.z yarn run bump-jsons
|
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively you can try the experimental `make-release.sh` bash script that will create the branch with the updated json files for you.
|
|
||||||
run `./make-release.sh` for a patch update
|
run `./make-release.sh` for a patch update
|
||||||
run `./make-release.sh "minor"` for minor
|
run `./make-release.sh "minor"` for minor
|
||||||
run `./make-release.sh "major"` for major
|
run `./make-release.sh "major"` for major
|
||||||
|
|
||||||
The PR may serve as a place to discuss the human-readable changelog and extra QA. A quick way of getting PR's merged since the last bump is to [use this PR filter](https://github.com/KittyCAD/modeling-app/pulls?q=is%3Apr+sort%3Aupdated-desc+is%3Amerged+), open up the browser console and paste in the following
|
After it runs you should just need to push the push the branch and open a PR (it will suggest a changelog for you too, delete any that are not user facing)
|
||||||
|
|
||||||
```typescript
|
The PR may serve as a place to discuss the human-readable changelog and extra QA.
|
||||||
console.log(
|
|
||||||
'- ' +
|
|
||||||
Array.from(
|
|
||||||
document.querySelectorAll('[data-hovercard-type="pull_request"]')
|
|
||||||
).map((a) => `[${a.innerText}](${a.href})`).join(`
|
|
||||||
- `)
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
grab the md list and delete any that are older than the last bump
|
|
||||||
|
|
||||||
2. Merge the PR
|
2. Merge the PR
|
||||||
|
|
||||||
3. Create a new release and tag pointing to the bump version commit using semantic versioning `v{x}.{y}.{z}`
|
3. Profit (A new Action kicks in at https://github.com/KittyCAD/modeling-app/actions if the PR was correctly named)
|
||||||
|
|
||||||
4. A new Action kicks in at https://github.com/KittyCAD/modeling-app/actions, uploading artifacts to the release
|
|
||||||
|
|
||||||
## Fuzzing the parser
|
## Fuzzing the parser
|
||||||
|
|
||||||
|
@ -121,6 +121,9 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -282,6 +285,9 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,6 +125,9 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -286,6 +289,9 @@ const extrusion = extrude(5, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -126,6 +126,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -287,6 +290,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -476,6 +482,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -637,6 +646,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,6 +125,9 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -286,6 +289,9 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -475,6 +481,9 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -636,6 +645,9 @@ const extrusion = extrude(10, sketch001)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -133,6 +133,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -294,6 +297,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -483,6 +489,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -644,6 +653,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,6 +124,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -285,6 +288,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -474,6 +480,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -635,6 +644,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -135,6 +135,9 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -296,6 +299,9 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -485,6 +491,9 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -646,6 +655,9 @@ const exampleSketch = startSketchOn('XZ')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -130,6 +130,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -291,6 +294,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -480,6 +486,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -641,6 +650,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -532,6 +535,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -410,6 +413,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -599,6 +605,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -760,6 +769,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -150,6 +150,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -311,6 +314,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
@ -580,6 +586,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -225,6 +225,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -524,6 +527,9 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -215,6 +215,9 @@ const revolution = startSketchOn(box, "revolveAxis")
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -211,6 +211,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,6 +213,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,6 +213,9 @@ const part001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -512,6 +515,9 @@ const part001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -136,6 +136,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -297,6 +300,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
@ -479,6 +485,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -640,6 +649,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -821,6 +833,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -982,6 +997,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -129,6 +129,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -290,6 +293,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -479,6 +485,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -640,6 +649,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,6 +116,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -277,6 +280,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -466,6 +472,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -627,6 +636,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -134,6 +134,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -295,6 +298,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
|
@ -217,6 +217,9 @@ const example = extrude(-5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -127,6 +127,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -288,6 +291,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
type: "sketchGroup",
|
type: "sketchGroup",
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
|
@ -215,6 +215,9 @@ const example = extrude(1, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -217,6 +217,9 @@ let vase = layer()
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -117,6 +117,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -278,6 +281,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -112,6 +112,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -273,6 +276,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -111,6 +111,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -272,6 +275,9 @@ const sketch001 = startSketchOn('XY')
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -247,6 +247,9 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -408,6 +411,9 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -673,6 +679,9 @@ uuid |
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -124,6 +124,9 @@ const example = extrude(4, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -285,6 +288,9 @@ const example = extrude(4, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -122,6 +122,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -283,6 +286,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -123,6 +123,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -284,6 +287,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -121,6 +121,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -282,6 +285,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -213,6 +213,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -512,6 +515,9 @@ shell({ faces: ['end'], thickness: 0.25 }, firstSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -195,6 +195,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -442,6 +445,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -603,6 +609,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -142,6 +142,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -303,6 +306,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -264,6 +264,9 @@ const a1 = startSketchOn({
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -539,6 +542,9 @@ const a1 = startSketchOn({
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
5655
docs/kcl/std.json
@ -125,6 +125,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -286,6 +289,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -475,6 +481,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -636,6 +645,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -116,6 +116,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -277,6 +280,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -466,6 +472,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -627,6 +636,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -74,6 +74,107 @@ You can nest expressions in parenthesis as well:
|
|||||||
let myMathExpression = 3 + (1 * 2 / (3 - 7))
|
let myMathExpression = 3 + (1 * 2 / (3 - 7))
|
||||||
```
|
```
|
||||||
|
|
||||||
Please if you find any issues using any of the above expressions or syntax
|
## Tags
|
||||||
|
|
||||||
|
Tags are used to give a name (tag) to a specific path.
|
||||||
|
|
||||||
|
### Tag Declaration
|
||||||
|
|
||||||
|
The syntax for declaring a tag is `$myTag` you would use it in the following
|
||||||
|
way:
|
||||||
|
|
||||||
|
```
|
||||||
|
startSketchOn('XZ')
|
||||||
|
|> startProfileAt(origin, %)
|
||||||
|
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %) - 90,
|
||||||
|
196.99
|
||||||
|
], %, $rectangleSegmentB001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %),
|
||||||
|
-segLen(rectangleSegmentA001, %)
|
||||||
|
], %, $rectangleSegmentC001)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tag Identifier
|
||||||
|
|
||||||
|
As per the example above you can use the tag identifier to get a reference to the
|
||||||
|
tagged object. The syntax for this is `myTag`.
|
||||||
|
|
||||||
|
In the example above we use the tag identifier to get the angle of the segment
|
||||||
|
`segAng(rectangleSegmentA001, %)`.
|
||||||
|
|
||||||
|
|
||||||
|
### Tag Scope
|
||||||
|
|
||||||
|
Tags are scoped globally if in the root context meaning in this example you can
|
||||||
|
use the tag `rectangleSegmentA001` in any function or expression in the file.
|
||||||
|
|
||||||
|
However if the code was written like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn rect = (origin) => {
|
||||||
|
return startSketchOn('XZ')
|
||||||
|
|> startProfileAt(origin, %)
|
||||||
|
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %) - 90,
|
||||||
|
196.99
|
||||||
|
], %, $rectangleSegmentB001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %),
|
||||||
|
-segLen(rectangleSegmentA001, %)
|
||||||
|
], %, $rectangleSegmentC001)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
}
|
||||||
|
|
||||||
|
rect([0, 0])
|
||||||
|
rect([20, 0])
|
||||||
|
```
|
||||||
|
|
||||||
|
Those tags would only be available in the `rect` function and not globally.
|
||||||
|
|
||||||
|
However you likely want to use those tags somewhere outside the `rect` function.
|
||||||
|
|
||||||
|
Tags are accessible through the sketch group they are declared in.
|
||||||
|
For example the following code works.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn rect = (origin) => {
|
||||||
|
return startSketchOn('XZ')
|
||||||
|
|> startProfileAt(origin, %)
|
||||||
|
|> angledLine([0, 191.26], %, $rectangleSegmentA001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %) - 90,
|
||||||
|
196.99
|
||||||
|
], %, $rectangleSegmentB001)
|
||||||
|
|> angledLine([
|
||||||
|
segAng(rectangleSegmentA001, %),
|
||||||
|
-segLen(rectangleSegmentA001, %)
|
||||||
|
], %, $rectangleSegmentC001)
|
||||||
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||||
|
|> close(%)
|
||||||
|
}
|
||||||
|
|
||||||
|
rect([0, 0])
|
||||||
|
const myRect = rect([20, 0])
|
||||||
|
|
||||||
|
myRect
|
||||||
|
|> extrude(10, %)
|
||||||
|
|> fillet({radius: 0.5, tags: [myRect.tags.rectangleSegmentA001]}, %)
|
||||||
|
```
|
||||||
|
|
||||||
|
See how we use the tag `rectangleSegmentA001` in the `fillet` function outside
|
||||||
|
the `rect` function. This is because the `rect` function is returning the
|
||||||
|
sketch group that contains the tags.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
If you find any issues using any of the above expressions or syntax,
|
||||||
please file an issue with the `ast` label on the [modeling-app
|
please file an issue with the `ast` label on the [modeling-app
|
||||||
repo](https://github.com/KittyCAD/modeling-app/issues/new).
|
repo](https://github.com/KittyCAD/modeling-app/issues/new).
|
||||||
|
@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -119,6 +119,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -280,6 +283,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -469,6 +475,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -630,6 +639,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -117,6 +117,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -278,6 +281,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -467,6 +473,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -628,6 +637,9 @@ const example = extrude(10, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
@ -115,6 +115,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -276,6 +279,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -465,6 +471,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
@ -626,6 +635,9 @@ const example = extrude(5, exampleSketch)
|
|||||||
},
|
},
|
||||||
// The to point.
|
// The to point.
|
||||||
to: [number, number],
|
to: [number, number],
|
||||||
|
},
|
||||||
|
// Tag identifiers that have been declared in this sketch group.
|
||||||
|
tags: {
|
||||||
},
|
},
|
||||||
// The paths in the sketch group.
|
// The paths in the sketch group.
|
||||||
value: [{
|
value: [{
|
||||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
@ -232,6 +232,7 @@ export async function getUtils(page: Page) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
||||||
|
waitForPageLoad: () => waitForPageLoad(page),
|
||||||
removeCurrentCode: () => removeCurrentCode(page),
|
removeCurrentCode: () => removeCurrentCode(page),
|
||||||
sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd),
|
sendCustomCmd: (cmd: EngineCommand) => sendCustomCmd(page, cmd),
|
||||||
updateCamPosition: async (xyz: [number, number, number]) => {
|
updateCamPosition: async (xyz: [number, number, number]) => {
|
||||||
@ -311,9 +312,9 @@ export async function getUtils(page: Page) {
|
|||||||
fullPage: true,
|
fullPage: true,
|
||||||
})
|
})
|
||||||
const screenshot = await PNG.sync.read(buffer)
|
const screenshot = await PNG.sync.read(buffer)
|
||||||
// most likely related to pixel density but the screenshots for webkit are 2x the size
|
const pixMultiplier: number = await page.evaluate(
|
||||||
// there might be a more robust way of doing this.
|
'window.devicePixelRatio'
|
||||||
const pixMultiplier = browserType === 'webkit' ? 2 : 1
|
)
|
||||||
const index =
|
const index =
|
||||||
(screenshot.width * coords.y * pixMultiplier +
|
(screenshot.width * coords.y * pixMultiplier +
|
||||||
coords.x * pixMultiplier) *
|
coords.x * pixMultiplier) *
|
||||||
@ -376,11 +377,13 @@ export async function getUtils(page: Page) {
|
|||||||
emulateNetworkConditions: async (
|
emulateNetworkConditions: async (
|
||||||
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
|
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
|
||||||
) => {
|
) => {
|
||||||
// Skip on non-Chromium browsers, since we need to use the CDP.
|
if (browserType !== 'chromium') {
|
||||||
test.skip(
|
console.warn('emulateNetworkConditions will not work on this browser')
|
||||||
cdpSession === null,
|
}
|
||||||
'Network emulation is only supported in Chromium'
|
if (cdpSession === null) {
|
||||||
)
|
// Use a fail safe if we can't simulate disconnect (on Safari)
|
||||||
|
return page.evaluate('window.tearDown()')
|
||||||
|
}
|
||||||
|
|
||||||
cdpSession?.send('Network.emulateNetworkConditions', networkOptions)
|
cdpSession?.send('Network.emulateNetworkConditions', networkOptions)
|
||||||
},
|
},
|
||||||
|
33
package.json
@ -1,14 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "untitled-app",
|
"name": "untitled-app",
|
||||||
"version": "0.22.7",
|
"version": "0.23.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/autocomplete": "^6.16.3",
|
"@codemirror/autocomplete": "^6.17.0",
|
||||||
"@codemirror/commands": "^6.6.0",
|
"@codemirror/commands": "^6.6.0",
|
||||||
"@codemirror/language": "^6.10.2",
|
"@codemirror/language": "^6.10.2",
|
||||||
"@codemirror/lint": "^6.8.1",
|
"@codemirror/lint": "^6.8.1",
|
||||||
"@codemirror/search": "^6.5.6",
|
"@codemirror/search": "^6.5.6",
|
||||||
"@codemirror/state": "^6.4.1",
|
"@codemirror/state": "^6.4.1",
|
||||||
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
"@csstools/postcss-oklab-function": "^3.0.16",
|
"@csstools/postcss-oklab-function": "^3.0.16",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
||||||
@ -19,23 +20,22 @@
|
|||||||
"@kittycad/lib": "^0.0.69",
|
"@kittycad/lib": "^0.0.69",
|
||||||
"@react-hook/resize-observer": "^2.0.1",
|
"@react-hook/resize-observer": "^2.0.1",
|
||||||
"@replit/codemirror-interact": "^6.3.1",
|
"@replit/codemirror-interact": "^6.3.1",
|
||||||
"@tauri-apps/api": "2.0.0-beta.12",
|
"@tauri-apps/api": "^2.0.0-beta.14",
|
||||||
"@tauri-apps/plugin-dialog": "^2.0.0-beta.2",
|
"@tauri-apps/plugin-dialog": "^2.0.0-beta.6",
|
||||||
"@tauri-apps/plugin-fs": "^2.0.0-beta.5",
|
"@tauri-apps/plugin-fs": "^2.0.0-beta.6",
|
||||||
"@tauri-apps/plugin-http": "^2.0.0-beta.2",
|
"@tauri-apps/plugin-http": "^2.0.0-beta.7",
|
||||||
"@tauri-apps/plugin-os": "^2.0.0-beta.3",
|
"@tauri-apps/plugin-os": "^2.0.0-beta.6",
|
||||||
"@tauri-apps/plugin-process": "^2.0.0-beta.2",
|
"@tauri-apps/plugin-process": "^2.0.0-beta.6",
|
||||||
"@tauri-apps/plugin-shell": "^2.0.0-beta.2",
|
"@tauri-apps/plugin-shell": "^2.0.0-beta.7",
|
||||||
"@tauri-apps/plugin-updater": "^2.0.0-beta.3",
|
"@tauri-apps/plugin-updater": "^2.0.0-beta.6",
|
||||||
"@ts-stack/markdown": "^1.5.0",
|
"@ts-stack/markdown": "^1.5.0",
|
||||||
"@tweenjs/tween.js": "^23.1.1",
|
"@tweenjs/tween.js": "^23.1.1",
|
||||||
"@uiw/react-codemirror": "^4.21.25",
|
|
||||||
"@xstate/inspect": "^0.8.0",
|
"@xstate/inspect": "^0.8.0",
|
||||||
"@xstate/react": "^3.2.2",
|
"@xstate/react": "^3.2.2",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"decamelize": "^6.0.0",
|
"decamelize": "^6.0.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"html2canvas-pro": "^1.5.0",
|
"html2canvas-pro": "^1.5.2",
|
||||||
"json-rpc-2.0": "^1.6.0",
|
"json-rpc-2.0": "^1.6.0",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"re-resizable": "^6.9.11",
|
"re-resizable": "^6.9.11",
|
||||||
@ -48,7 +48,7 @@
|
|||||||
"react-modal-promise": "^1.0.2",
|
"react-modal-promise": "^1.0.2",
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"sketch-helpers": "^0.0.4",
|
"sketch-helpers": "^0.0.4",
|
||||||
"three": "^0.164.1",
|
"three": "^0.166.1",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"ua-parser-js": "^1.0.37",
|
"ua-parser-js": "^1.0.37",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
@ -56,8 +56,7 @@
|
|||||||
"vscode-languageserver-protocol": "^3.17.5",
|
"vscode-languageserver-protocol": "^3.17.5",
|
||||||
"vscode-uri": "^3.0.8",
|
"vscode-uri": "^3.0.8",
|
||||||
"web-vitals": "^3.5.2",
|
"web-vitals": "^3.5.2",
|
||||||
"xstate": "^4.38.2",
|
"xstate": "^4.38.2"
|
||||||
"zustand": "^4.5.2"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "vite",
|
"start": "vite",
|
||||||
@ -110,7 +109,7 @@
|
|||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||||
"@babel/preset-env": "^7.24.3",
|
"@babel/preset-env": "^7.24.3",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iarna/toml": "^2.2.5",
|
||||||
"@playwright/test": "^1.44.1",
|
"@playwright/test": "^1.45.1",
|
||||||
"@tauri-apps/cli": "==2.0.0-beta.13",
|
"@tauri-apps/cli": "==2.0.0-beta.13",
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/react": "^15.0.2",
|
"@testing-library/react": "^15.0.2",
|
||||||
@ -158,7 +157,7 @@
|
|||||||
"vitest": "^1.6.0",
|
"vitest": "^1.6.0",
|
||||||
"vitest-webgl-canvas-mock": "^1.1.0",
|
"vitest-webgl-canvas-mock": "^1.1.0",
|
||||||
"wait-on": "^7.2.0",
|
"wait-on": "^7.2.0",
|
||||||
"wasm-pack": "^0.12.1",
|
"wasm-pack": "^0.13.0",
|
||||||
"ws": "^8.17.0",
|
"ws": "^8.17.0",
|
||||||
"yarn": "^1.22.22"
|
"yarn": "^1.22.22"
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { autocompletion } from '@codemirror/autocomplete'
|
import { foldService } from '@codemirror/language'
|
||||||
import { foldService, syntaxTree } from '@codemirror/language'
|
|
||||||
import { Extension, EditorState } from '@codemirror/state'
|
import { Extension, EditorState } from '@codemirror/state'
|
||||||
import { ViewPlugin } from '@codemirror/view'
|
import { ViewPlugin } from '@codemirror/view'
|
||||||
|
|
||||||
import { CompletionTriggerKind } from 'vscode-languageserver-protocol'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
docPathFacet,
|
docPathFacet,
|
||||||
LanguageServerPlugin,
|
LanguageServerPlugin,
|
||||||
@ -13,7 +10,6 @@ import {
|
|||||||
workspaceFolders,
|
workspaceFolders,
|
||||||
LanguageServerOptions,
|
LanguageServerOptions,
|
||||||
} from './plugin/lsp'
|
} from './plugin/lsp'
|
||||||
import { offsetToPos } from './plugin/util'
|
|
||||||
|
|
||||||
export type { LanguageServerClientOptions } from './client'
|
export type { LanguageServerClientOptions } from './client'
|
||||||
export { LanguageServerClient } from './client'
|
export { LanguageServerClient } from './client'
|
||||||
@ -24,14 +20,15 @@ export {
|
|||||||
LspWorkerEventType,
|
LspWorkerEventType,
|
||||||
} from './client/codec'
|
} from './client/codec'
|
||||||
export type { LanguageServerOptions } from './plugin/lsp'
|
export type { LanguageServerOptions } from './plugin/lsp'
|
||||||
export type { TransactionInfo, RelevantUpdate } from './plugin/annotations'
|
|
||||||
export { updateInfo, TransactionAnnotation } from './plugin/annotations'
|
|
||||||
export {
|
export {
|
||||||
LanguageServerPlugin,
|
LanguageServerPlugin,
|
||||||
LanguageServerPluginSpec,
|
LanguageServerPluginSpec,
|
||||||
docPathFacet,
|
docPathFacet,
|
||||||
languageId,
|
languageId,
|
||||||
workspaceFolders,
|
workspaceFolders,
|
||||||
|
lspSemanticTokensEvent,
|
||||||
|
lspDiagnosticsEvent,
|
||||||
|
lspFormatCodeEvent,
|
||||||
} from './plugin/lsp'
|
} from './plugin/lsp'
|
||||||
export { posToOffset, offsetToPos } from './plugin/util'
|
export { posToOffset, offsetToPos } from './plugin/util'
|
||||||
|
|
||||||
@ -51,63 +48,10 @@ export function lspPlugin(options: LanguageServerOptions): Extension {
|
|||||||
if (plugin == null) return null
|
if (plugin == null) return null
|
||||||
// Get the folding ranges from the language server.
|
// Get the folding ranges from the language server.
|
||||||
// Since this is async we directly need to update the folding ranges after.
|
// Since this is async we directly need to update the folding ranges after.
|
||||||
return plugin?.foldingRange(lineStart, lineEnd)
|
const range = plugin?.foldingRange(lineStart, lineEnd)
|
||||||
|
return range
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
|
|
||||||
if (options.client.getServerCapabilities().completionProvider) {
|
|
||||||
ext.push(
|
|
||||||
autocompletion({
|
|
||||||
defaultKeymap: false,
|
|
||||||
override: [
|
|
||||||
async (context) => {
|
|
||||||
if (plugin === null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const { state, pos, explicit } = context
|
|
||||||
|
|
||||||
let nodeBefore = syntaxTree(state).resolveInner(pos, -1)
|
|
||||||
if (
|
|
||||||
nodeBefore.name === 'BlockComment' ||
|
|
||||||
nodeBefore.name === 'LineComment'
|
|
||||||
)
|
|
||||||
return null
|
|
||||||
|
|
||||||
const line = state.doc.lineAt(pos)
|
|
||||||
let trigKind: CompletionTriggerKind = CompletionTriggerKind.Invoked
|
|
||||||
let trigChar: string | undefined
|
|
||||||
if (
|
|
||||||
!explicit &&
|
|
||||||
plugin.client
|
|
||||||
.getServerCapabilities()
|
|
||||||
.completionProvider?.triggerCharacters?.includes(
|
|
||||||
line.text[pos - line.from - 1]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
trigKind = CompletionTriggerKind.TriggerCharacter
|
|
||||||
trigChar = line.text[pos - line.from - 1]
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
trigKind === CompletionTriggerKind.Invoked &&
|
|
||||||
!context.matchBefore(/\w+$/)
|
|
||||||
) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return await plugin.requestCompletion(
|
|
||||||
context,
|
|
||||||
offsetToPos(state.doc, pos),
|
|
||||||
{
|
|
||||||
triggerKind: trigKind,
|
|
||||||
triggerCharacter: trigChar,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ext
|
return ext
|
||||||
}
|
}
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
import { hasNextSnippetField, pickedCompletion } from '@codemirror/autocomplete'
|
|
||||||
import { Annotation, Transaction } from '@codemirror/state'
|
|
||||||
import type { ViewUpdate } from '@codemirror/view'
|
|
||||||
|
|
||||||
export enum LspAnnotation {
|
|
||||||
SemanticTokens = 'semantic-tokens',
|
|
||||||
FormatCode = 'format-code',
|
|
||||||
Diagnostics = 'diagnostics',
|
|
||||||
}
|
|
||||||
|
|
||||||
const lspEvent = Annotation.define<LspAnnotation>()
|
|
||||||
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
|
|
||||||
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
|
|
||||||
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
|
|
||||||
|
|
||||||
export enum TransactionAnnotation {
|
|
||||||
Remote = 'remote',
|
|
||||||
UserSelect = 'user.select',
|
|
||||||
UserInput = 'user.input',
|
|
||||||
UserMove = 'user.move',
|
|
||||||
UserDelete = 'user.delete',
|
|
||||||
UserUndo = 'user.undo',
|
|
||||||
UserRedo = 'user.redo',
|
|
||||||
|
|
||||||
SemanticTokens = 'SemanticTokens',
|
|
||||||
FormatCode = 'FormatCode',
|
|
||||||
Diagnostics = 'Diagnostics',
|
|
||||||
|
|
||||||
PickedCompletion = 'PickedCompletion',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TransactionInfo {
|
|
||||||
annotations: TransactionAnnotation[]
|
|
||||||
time: number | null
|
|
||||||
docChanged: boolean
|
|
||||||
addToHistory: boolean
|
|
||||||
inSnippet: boolean
|
|
||||||
transaction: Transaction
|
|
||||||
}
|
|
||||||
|
|
||||||
export const updateInfo = (update: ViewUpdate): TransactionInfo[] => {
|
|
||||||
let transactionInfos: TransactionInfo[] = []
|
|
||||||
|
|
||||||
for (const tr of update.transactions) {
|
|
||||||
let annotations: TransactionAnnotation[] = []
|
|
||||||
|
|
||||||
if (tr.isUserEvent('select')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserSelect)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.isUserEvent('input')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserInput)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('delete')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserDelete)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('undo')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserUndo)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('redo')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserRedo)
|
|
||||||
}
|
|
||||||
if (tr.isUserEvent('move')) {
|
|
||||||
annotations.push(TransactionAnnotation.UserMove)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(pickedCompletion) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.PickedCompletion)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspSemanticTokensEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.SemanticTokens)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspFormatCodeEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.FormatCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(lspDiagnosticsEvent.type) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.Diagnostics)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tr.annotation(Transaction.remote) !== undefined) {
|
|
||||||
annotations.push(TransactionAnnotation.Remote)
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionInfos.push({
|
|
||||||
annotations,
|
|
||||||
time: tr.annotation(Transaction.time) || null,
|
|
||||||
docChanged: tr.docChanged,
|
|
||||||
addToHistory: tr.annotation(Transaction.addToHistory) || false,
|
|
||||||
inSnippet: hasNextSnippetField(update.state),
|
|
||||||
transaction: tr,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return transactionInfos
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RelevantUpdate {
|
|
||||||
overall: boolean
|
|
||||||
userSelect: boolean
|
|
||||||
time: number | null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const relevantUpdate = (update: ViewUpdate): RelevantUpdate => {
|
|
||||||
const infos = updateInfo(update)
|
|
||||||
// Make sure we are not in a snippet
|
|
||||||
if (infos.some((info) => info.inSnippet)) {
|
|
||||||
return {
|
|
||||||
overall: false,
|
|
||||||
userSelect: false,
|
|
||||||
time: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
overall: infos.some(
|
|
||||||
(info) =>
|
|
||||||
info.docChanged ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserInput) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserDelete) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserUndo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserRedo) ||
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserMove)
|
|
||||||
),
|
|
||||||
userSelect: infos.some((info) =>
|
|
||||||
info.annotations.includes(TransactionAnnotation.UserSelect)
|
|
||||||
),
|
|
||||||
time: infos.length ? infos[0].time : null,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
acceptCompletion,
|
acceptCompletion,
|
||||||
|
autocompletion,
|
||||||
clearSnippet,
|
clearSnippet,
|
||||||
closeCompletion,
|
closeCompletion,
|
||||||
hasNextSnippetField,
|
hasNextSnippetField,
|
||||||
@ -8,10 +9,17 @@ import {
|
|||||||
prevSnippetField,
|
prevSnippetField,
|
||||||
startCompletion,
|
startCompletion,
|
||||||
} from '@codemirror/autocomplete'
|
} from '@codemirror/autocomplete'
|
||||||
import { Prec } from '@codemirror/state'
|
import { Prec, Extension } from '@codemirror/state'
|
||||||
import { EditorView, keymap, KeyBinding } from '@codemirror/view'
|
import { EditorView, keymap, KeyBinding, ViewPlugin } from '@codemirror/view'
|
||||||
|
|
||||||
import { CompletionItemKind } from 'vscode-languageserver-protocol'
|
import {
|
||||||
|
CompletionItemKind,
|
||||||
|
CompletionTriggerKind,
|
||||||
|
} from 'vscode-languageserver-protocol'
|
||||||
|
|
||||||
|
import { LanguageServerPlugin } from './lsp'
|
||||||
|
import { offsetToPos } from './util'
|
||||||
|
import { syntaxTree } from '@codemirror/language'
|
||||||
|
|
||||||
export const CompletionItemKindMap = Object.fromEntries(
|
export const CompletionItemKindMap = Object.fromEntries(
|
||||||
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])
|
Object.entries(CompletionItemKind).map(([key, value]) => [value, key])
|
||||||
@ -46,6 +54,59 @@ const lspAutocompleteKeymap: readonly KeyBinding[] = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export const lspAutocompleteKeymapExt = Prec.highest(
|
const lspAutocompleteKeymapExt = Prec.highest(keymap.of(lspAutocompleteKeymap))
|
||||||
keymap.computeN([], () => [lspAutocompleteKeymap])
|
|
||||||
)
|
export default function lspAutocompleteExt(
|
||||||
|
plugin: ViewPlugin<LanguageServerPlugin>
|
||||||
|
): Extension {
|
||||||
|
return [
|
||||||
|
lspAutocompleteKeymapExt,
|
||||||
|
autocompletion({
|
||||||
|
defaultKeymap: false,
|
||||||
|
override: [
|
||||||
|
async (context) => {
|
||||||
|
const { state, pos, explicit, view } = context
|
||||||
|
let value = view?.plugin(plugin)
|
||||||
|
if (!value) return null
|
||||||
|
|
||||||
|
let nodeBefore = syntaxTree(state).resolveInner(pos, -1)
|
||||||
|
if (
|
||||||
|
nodeBefore.name === 'BlockComment' ||
|
||||||
|
nodeBefore.name === 'LineComment'
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const line = state.doc.lineAt(pos)
|
||||||
|
let trigKind: CompletionTriggerKind = CompletionTriggerKind.Invoked
|
||||||
|
let trigChar: string | undefined
|
||||||
|
if (
|
||||||
|
!explicit &&
|
||||||
|
value.client
|
||||||
|
.getServerCapabilities()
|
||||||
|
.completionProvider?.triggerCharacters?.includes(
|
||||||
|
line.text[pos - line.from - 1]
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
trigKind = CompletionTriggerKind.TriggerCharacter
|
||||||
|
trigChar = line.text[pos - line.from - 1]
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
trigKind === CompletionTriggerKind.Invoked &&
|
||||||
|
!context.matchBefore(/\w+$/)
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return await value.requestCompletion(
|
||||||
|
context,
|
||||||
|
offsetToPos(state.doc, pos),
|
||||||
|
{
|
||||||
|
triggerKind: trigKind,
|
||||||
|
triggerCharacter: trigChar,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -4,7 +4,13 @@ import type {
|
|||||||
CompletionResult,
|
CompletionResult,
|
||||||
} from '@codemirror/autocomplete'
|
} from '@codemirror/autocomplete'
|
||||||
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
|
import { completeFromList, snippetCompletion } from '@codemirror/autocomplete'
|
||||||
import { Facet, StateEffect, Extension, Transaction } from '@codemirror/state'
|
import {
|
||||||
|
Facet,
|
||||||
|
StateEffect,
|
||||||
|
Extension,
|
||||||
|
Transaction,
|
||||||
|
Annotation,
|
||||||
|
} from '@codemirror/state'
|
||||||
import type {
|
import type {
|
||||||
ViewUpdate,
|
ViewUpdate,
|
||||||
PluginValue,
|
PluginValue,
|
||||||
@ -22,15 +28,10 @@ import {
|
|||||||
import { URI } from 'vscode-uri'
|
import { URI } from 'vscode-uri'
|
||||||
|
|
||||||
import { LanguageServerClient } from '../client'
|
import { LanguageServerClient } from '../client'
|
||||||
import {
|
|
||||||
lspSemanticTokensEvent,
|
|
||||||
lspFormatCodeEvent,
|
|
||||||
relevantUpdate,
|
|
||||||
} from './annotations'
|
|
||||||
import { CompletionItemKindMap } from './autocomplete'
|
import { CompletionItemKindMap } from './autocomplete'
|
||||||
import { addToken, SemanticToken } from './semantic-tokens'
|
import { addToken, SemanticToken } from './semantic-tokens'
|
||||||
import { deferExecution, posToOffset, formatMarkdownContents } from './util'
|
import { deferExecution, posToOffset, formatMarkdownContents } from './util'
|
||||||
import { lspAutocompleteKeymapExt } from './autocomplete'
|
import lspAutocompleteExt from './autocomplete'
|
||||||
import lspHoverExt from './hover'
|
import lspHoverExt from './hover'
|
||||||
import lspFormatExt from './format'
|
import lspFormatExt from './format'
|
||||||
import lspIndentExt from './indent'
|
import lspIndentExt from './indent'
|
||||||
@ -47,6 +48,17 @@ export const workspaceFolders = Facet.define<
|
|||||||
LSP.WorkspaceFolder[]
|
LSP.WorkspaceFolder[]
|
||||||
>({ combine: useLast })
|
>({ combine: useLast })
|
||||||
|
|
||||||
|
export enum LspAnnotation {
|
||||||
|
SemanticTokens = 'semantic-tokens',
|
||||||
|
FormatCode = 'format-code',
|
||||||
|
Diagnostics = 'diagnostics',
|
||||||
|
}
|
||||||
|
|
||||||
|
const lspEvent = Annotation.define<LspAnnotation>()
|
||||||
|
export const lspSemanticTokensEvent = lspEvent.of(LspAnnotation.SemanticTokens)
|
||||||
|
export const lspFormatCodeEvent = lspEvent.of(LspAnnotation.FormatCode)
|
||||||
|
export const lspDiagnosticsEvent = lspEvent.of(LspAnnotation.Diagnostics)
|
||||||
|
|
||||||
export interface LanguageServerOptions {
|
export interface LanguageServerOptions {
|
||||||
// We assume this is the main project directory, we are currently working in.
|
// We assume this is the main project directory, we are currently working in.
|
||||||
workspaceFolders: LSP.WorkspaceFolder[]
|
workspaceFolders: LSP.WorkspaceFolder[]
|
||||||
@ -131,11 +143,6 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update(viewUpdate: ViewUpdate) {
|
update(viewUpdate: ViewUpdate) {
|
||||||
const isRelevant = relevantUpdate(viewUpdate)
|
|
||||||
if (!isRelevant.overall) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the doc didn't change we can return early.
|
// If the doc didn't change we can return early.
|
||||||
if (!viewUpdate.docChanged) {
|
if (!viewUpdate.docChanged) {
|
||||||
return
|
return
|
||||||
@ -284,19 +291,16 @@ export class LanguageServerPlugin implements PluginValue {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!result) return null
|
if (!result || !result.length) return null
|
||||||
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
this.view.dispatch({
|
||||||
const { range, newText } = result[i]
|
changes: result.map(({ range, newText }) => ({
|
||||||
this.view.dispatch({
|
from: posToOffset(this.view.state.doc, range.start)!,
|
||||||
changes: {
|
to: posToOffset(this.view.state.doc, range.end)!,
|
||||||
from: posToOffset(this.view.state.doc, range.start)!,
|
insert: newText,
|
||||||
to: posToOffset(this.view.state.doc, range.end)!,
|
})),
|
||||||
insert: newText,
|
annotations: lspFormatCodeEvent,
|
||||||
},
|
})
|
||||||
annotations: [lspFormatCodeEvent, Transaction.addToHistory.of(true)],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestCompletion(
|
async requestCompletion(
|
||||||
@ -552,7 +556,7 @@ export class LanguageServerPluginSpec
|
|||||||
{
|
{
|
||||||
provide(plugin: ViewPlugin<LanguageServerPlugin>): Extension {
|
provide(plugin: ViewPlugin<LanguageServerPlugin>): Extension {
|
||||||
return [
|
return [
|
||||||
lspAutocompleteKeymapExt,
|
lspAutocompleteExt(plugin),
|
||||||
lspFormatExt(plugin),
|
lspFormatExt(plugin),
|
||||||
lspHoverExt(plugin),
|
lspHoverExt(plugin),
|
||||||
lspIndentExt(),
|
lspIndentExt(),
|
||||||
|
@ -4,7 +4,7 @@ import { EditorView, Decoration, DecorationSet } from '@codemirror/view'
|
|||||||
|
|
||||||
import { Tag, tags } from '@lezer/highlight'
|
import { Tag, tags } from '@lezer/highlight'
|
||||||
|
|
||||||
import { lspSemanticTokensEvent } from './annotations'
|
import { lspSemanticTokensEvent } from './lsp'
|
||||||
|
|
||||||
export interface SemanticToken {
|
export interface SemanticToken {
|
||||||
from: number
|
from: number
|
||||||
|
541
src-tauri/Cargo.lock
generated
@ -11,27 +11,27 @@ rust-version = "1.70"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.0.0-beta.13", features = [] }
|
tauri-build = { version = "2.0.0-beta.18", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
kcl-lib = { version = "0.1.53", path = "../src/wasm-lib/kcl" }
|
kcl-lib = { version = "0.1.53", path = "../src/wasm-lib/kcl" }
|
||||||
kittycad = "0.3.5"
|
kittycad = "0.3.7"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
oauth2 = "4.4.2"
|
oauth2 = "4.4.2"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tauri = { version = "2.0.0-beta.15", features = [ "devtools", "unstable"] }
|
tauri = { version = "2.0.0-beta.23", features = [ "devtools", "unstable"] }
|
||||||
tauri-plugin-cli = { version = "2.0.0-beta.3" }
|
tauri-plugin-cli = { version = "2.0.0-beta.7" }
|
||||||
tauri-plugin-deep-link = { version = "2.0.0-beta.3" }
|
tauri-plugin-deep-link = { version = "2.0.0-beta.8" }
|
||||||
tauri-plugin-dialog = { version = "2.0.0-beta.6" }
|
tauri-plugin-dialog = { version = "2.0.0-beta.6" }
|
||||||
tauri-plugin-fs = { version = "2.0.0-beta.9" }
|
tauri-plugin-fs = { version = "2.0.0-beta.10" }
|
||||||
tauri-plugin-http = { version = "2.0.0-beta.6" }
|
tauri-plugin-http = { version = "2.0.0-beta.11" }
|
||||||
tauri-plugin-log = { version = "2.0.0-beta.4" }
|
tauri-plugin-log = { version = "2.0.0-beta.7" }
|
||||||
tauri-plugin-os = { version = "2.0.0-beta.2" }
|
tauri-plugin-os = { version = "2.0.0-beta.7" }
|
||||||
tauri-plugin-persisted-scope = { version = "2.0.0-beta.7" }
|
tauri-plugin-persisted-scope = { version = "2.0.0-beta.10" }
|
||||||
tauri-plugin-process = { version = "2.0.0-beta.2" }
|
tauri-plugin-process = { version = "2.0.0-beta.7" }
|
||||||
tauri-plugin-shell = { version = "2.0.0-beta.2" }
|
tauri-plugin-shell = { version = "2.0.0-beta.8" }
|
||||||
tauri-plugin-updater = { version = "2.0.0-beta.4" }
|
tauri-plugin-updater = { version = "2.0.0-beta.9" }
|
||||||
tokio = { version = "1.37.0", features = ["time", "fs", "process"] }
|
tokio = { version = "1.37.0", features = ["time", "fs", "process"] }
|
||||||
toml = "0.8.2"
|
toml = "0.8.2"
|
||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
|
@ -63,16 +63,22 @@
|
|||||||
"subcommands": {}
|
"subcommands": {}
|
||||||
},
|
},
|
||||||
"deep-link": {
|
"deep-link": {
|
||||||
"domains": [
|
"mobile": [
|
||||||
{
|
{
|
||||||
"host": "app.zoo.dev"
|
"host": "app.zoo.dev"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"desktop": {
|
||||||
|
"schemes": [
|
||||||
|
"zoo",
|
||||||
|
"zoo-modeling-app"
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"shell": {
|
"shell": {
|
||||||
"open": true
|
"open": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"productName": "Zoo Modeling App",
|
"productName": "Zoo Modeling App",
|
||||||
"version": "0.22.7"
|
"version": "0.23.1"
|
||||||
}
|
}
|
||||||
|
30
src/App.tsx
@ -1,6 +1,5 @@
|
|||||||
import { MouseEventHandler, useEffect, useRef } from 'react'
|
import { MouseEventHandler, useEffect, useMemo, useRef } from 'react'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { useStore } from './useStore'
|
|
||||||
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
||||||
import { Stream } from './components/Stream'
|
import { Stream } from './components/Stream'
|
||||||
import { EngineCommand } from './lang/std/engineConnection'
|
import { EngineCommand } from './lang/std/engineConnection'
|
||||||
@ -26,6 +25,7 @@ import ModalContainer from 'react-modal-promise'
|
|||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
import Gizmo from 'components/Gizmo'
|
import Gizmo from 'components/Gizmo'
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
import { CoreDumpManager } from 'lib/coredump'
|
||||||
|
import { UnitsMenu } from 'components/UnitsMenu'
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
useRefreshSettings(paths.FILE + 'SETTINGS')
|
useRefreshSettings(paths.FILE + 'SETTINGS')
|
||||||
@ -44,22 +44,15 @@ export function App() {
|
|||||||
}, [projectName, projectPath])
|
}, [projectName, projectPath])
|
||||||
|
|
||||||
useHotKeyListener()
|
useHotKeyListener()
|
||||||
const { buttonDownInStream, didDragInStream, streamDimensions, setHtmlRef } =
|
const { context } = useModelingContext()
|
||||||
useStore((s) => ({
|
|
||||||
buttonDownInStream: s.buttonDownInStream,
|
|
||||||
didDragInStream: s.didDragInStream,
|
|
||||||
streamDimensions: s.streamDimensions,
|
|
||||||
setHtmlRef: s.setHtmlRef,
|
|
||||||
}))
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setHtmlRef(ref)
|
|
||||||
}, [ref])
|
|
||||||
|
|
||||||
const { auth, settings } = useSettingsAuthContext()
|
const { auth, settings } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
|
|
||||||
const coreDumpManager = new CoreDumpManager(engineCommandManager, ref, token)
|
const coreDumpManager = useMemo(
|
||||||
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
app: { onboardingStatus },
|
app: { onboardingStatus },
|
||||||
@ -81,7 +74,7 @@ export function App() {
|
|||||||
(p) => p === onboardingStatus.current
|
(p) => p === onboardingStatus.current
|
||||||
)
|
)
|
||||||
? 'opacity-20'
|
? 'opacity-20'
|
||||||
: didDragInStream
|
: context.store?.didDragInStream
|
||||||
? 'opacity-40'
|
? 'opacity-40'
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
@ -99,11 +92,11 @@ export function App() {
|
|||||||
clientX: e.clientX,
|
clientX: e.clientX,
|
||||||
clientY: e.clientY,
|
clientY: e.clientY,
|
||||||
el: e.currentTarget,
|
el: e.currentTarget,
|
||||||
...streamDimensions,
|
...context.store?.streamDimensions,
|
||||||
})
|
})
|
||||||
|
|
||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
if (buttonDownInStream === undefined) {
|
if (context.store?.buttonDownInStream === undefined) {
|
||||||
debounceSocketSend({
|
debounceSocketSend({
|
||||||
type: 'modeling_cmd_req',
|
type: 'modeling_cmd_req',
|
||||||
cmd: {
|
cmd: {
|
||||||
@ -125,7 +118,7 @@ export function App() {
|
|||||||
className={
|
className={
|
||||||
'transition-opacity transition-duration-75 ' +
|
'transition-opacity transition-duration-75 ' +
|
||||||
paneOpacity +
|
paneOpacity +
|
||||||
(buttonDownInStream ? ' pointer-events-none' : '')
|
(context.store?.buttonDownInStream ? ' pointer-events-none' : '')
|
||||||
}
|
}
|
||||||
project={{ project, file }}
|
project={{ project, file }}
|
||||||
enableMenu={true}
|
enableMenu={true}
|
||||||
@ -135,6 +128,7 @@ export function App() {
|
|||||||
<Stream />
|
<Stream />
|
||||||
{/* <CamToggle /> */}
|
{/* <CamToggle /> */}
|
||||||
<LowerRightControls coreDumpManager={coreDumpManager}>
|
<LowerRightControls coreDumpManager={coreDumpManager}>
|
||||||
|
<UnitsMenu />
|
||||||
<Gizmo />
|
<Gizmo />
|
||||||
</LowerRightControls>
|
</LowerRightControls>
|
||||||
</div>
|
</div>
|
||||||
|
41
src/AppState.tsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { createContext, useContext, useState, ReactNode } from 'react'
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is for a very small handful of global state we need that doesn't fit into
|
||||||
|
any of the Xstate machines.
|
||||||
|
Please do not fill this up with junk.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface AppState {
|
||||||
|
isStreamReady: boolean
|
||||||
|
setAppState: (newAppState: Partial<AppState>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppStateContext = createContext<AppState>({
|
||||||
|
isStreamReady: false,
|
||||||
|
setAppState: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const useAppState = () => useContext(AppStateContext)
|
||||||
|
|
||||||
|
export const AppStateProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [appState, _setAppState] = useState<AppState>({
|
||||||
|
isStreamReady: false,
|
||||||
|
setAppState: () => {},
|
||||||
|
})
|
||||||
|
const setAppState = (newAppState: Partial<AppState>) =>
|
||||||
|
_setAppState({ ...appState, ...newAppState })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppStateContext.Provider
|
||||||
|
value={{
|
||||||
|
isStreamReady: appState.isStreamReady,
|
||||||
|
setAppState,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AppStateContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
@ -33,6 +33,14 @@ import LspProvider from 'components/LspProvider'
|
|||||||
import { KclContextProvider } from 'lang/KclProvider'
|
import { KclContextProvider } from 'lang/KclProvider'
|
||||||
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
||||||
import { getState, setState } from 'lib/tauri'
|
import { getState, setState } from 'lib/tauri'
|
||||||
|
import { CoreDumpManager } from 'lib/coredump'
|
||||||
|
import { engineCommandManager } from 'lib/singletons'
|
||||||
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
|
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||||
|
import toast from 'react-hot-toast'
|
||||||
|
import { coreDump } from 'lang/wasm'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
import { AppStateProvider } from 'AppState'
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
@ -45,7 +53,9 @@ const router = createBrowserRouter([
|
|||||||
<SettingsAuthProvider>
|
<SettingsAuthProvider>
|
||||||
<LspProvider>
|
<LspProvider>
|
||||||
<KclContextProvider>
|
<KclContextProvider>
|
||||||
<Outlet />
|
<AppStateProvider>
|
||||||
|
<Outlet />
|
||||||
|
</AppStateProvider>
|
||||||
</KclContextProvider>
|
</KclContextProvider>
|
||||||
</LspProvider>
|
</LspProvider>
|
||||||
</SettingsAuthProvider>
|
</SettingsAuthProvider>
|
||||||
@ -87,6 +97,7 @@ const router = createBrowserRouter([
|
|||||||
<Auth>
|
<Auth>
|
||||||
<FileMachineProvider>
|
<FileMachineProvider>
|
||||||
<ModelingMachineProvider>
|
<ModelingMachineProvider>
|
||||||
|
<CoreDump />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
<App />
|
<App />
|
||||||
<CommandBar />
|
<CommandBar />
|
||||||
@ -165,3 +176,30 @@ export const Router = () => {
|
|||||||
</NetworkContext.Provider>
|
</NetworkContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CoreDump() {
|
||||||
|
const { auth } = useSettingsAuthContext()
|
||||||
|
const token = auth?.context?.token
|
||||||
|
const coreDumpManager = useMemo(
|
||||||
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
useHotkeyWrapper(['meta + shift + .'], () => {
|
||||||
|
toast.promise(
|
||||||
|
coreDump(coreDumpManager, true),
|
||||||
|
{
|
||||||
|
loading: 'Starting core dump...',
|
||||||
|
success: 'Core dump completed successfully',
|
||||||
|
error: 'Error while exporting core dump',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
success: {
|
||||||
|
// Note: this extended duration is especially important for Playwright e2e testing
|
||||||
|
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
|
||||||
|
duration: 6000,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
@ -8,10 +8,14 @@ import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
|||||||
import { ActionButton } from 'components/ActionButton'
|
import { ActionButton } from 'components/ActionButton'
|
||||||
import { isSingleCursorInPipe } from 'lang/queryAst'
|
import { isSingleCursorInPipe } from 'lang/queryAst'
|
||||||
import { useKclContext } from 'lang/KclProvider'
|
import { useKclContext } from 'lang/KclProvider'
|
||||||
import { useStore } from 'useStore'
|
|
||||||
import { ActionButtonDropdown } from 'components/ActionButtonDropdown'
|
import { ActionButtonDropdown } from 'components/ActionButtonDropdown'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import Tooltip from 'components/Tooltip'
|
import Tooltip from 'components/Tooltip'
|
||||||
|
import { useAppState } from 'AppState'
|
||||||
|
import {
|
||||||
|
canRectangleTool,
|
||||||
|
isEditingExistingSketch,
|
||||||
|
} from 'machines/modelingMachine'
|
||||||
|
|
||||||
export function Toolbar({
|
export function Toolbar({
|
||||||
className = '',
|
className = '',
|
||||||
@ -38,38 +42,56 @@ export function Toolbar({
|
|||||||
const toolbarButtonsRef = useRef<HTMLUListElement>(null)
|
const toolbarButtonsRef = useRef<HTMLUListElement>(null)
|
||||||
const { overallState } = useNetworkContext()
|
const { overallState } = useNetworkContext()
|
||||||
const { isExecuting } = useKclContext()
|
const { isExecuting } = useKclContext()
|
||||||
const { isStreamReady } = useStore((s) => ({
|
const { isStreamReady } = useAppState()
|
||||||
isStreamReady: s.isStreamReady,
|
|
||||||
}))
|
|
||||||
const disableAllButtons =
|
const disableAllButtons =
|
||||||
(overallState !== NetworkHealthState.Ok &&
|
(overallState !== NetworkHealthState.Ok &&
|
||||||
overallState !== NetworkHealthState.Weak) ||
|
overallState !== NetworkHealthState.Weak) ||
|
||||||
isExecuting ||
|
isExecuting ||
|
||||||
!isStreamReady
|
!isStreamReady
|
||||||
|
|
||||||
|
const disableLineButton =
|
||||||
|
state.matches('Sketch.Rectangle tool.Awaiting second corner') ||
|
||||||
|
disableAllButtons
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'l',
|
'l',
|
||||||
() =>
|
() =>
|
||||||
state.matches('Sketch.Line tool')
|
state.matches('Sketch.Line tool')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip Line tool'),
|
: send({
|
||||||
{ enabled: !disableAllButtons, scopes: ['sketch'] }
|
type: 'change tool',
|
||||||
|
data: 'line',
|
||||||
|
}),
|
||||||
|
{ enabled: !disableLineButton, scopes: ['sketch'] }
|
||||||
)
|
)
|
||||||
|
const disableTangentialArc =
|
||||||
|
(!isEditingExistingSketch(context) &&
|
||||||
|
!state.matches('Sketch.Tangential arc to')) ||
|
||||||
|
disableAllButtons
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'a',
|
'a',
|
||||||
() =>
|
() =>
|
||||||
state.matches('Sketch.Tangential arc to')
|
state.matches('Sketch.Tangential arc to')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip tangential arc to'),
|
: send({
|
||||||
{ enabled: !disableAllButtons, scopes: ['sketch'] }
|
type: 'change tool',
|
||||||
|
data: 'tangentialArc',
|
||||||
|
}),
|
||||||
|
{ enabled: !disableTangentialArc, scopes: ['sketch'] }
|
||||||
)
|
)
|
||||||
|
const disableRectangle =
|
||||||
|
(!canRectangleTool(context) && !state.matches('Sketch.Rectangle tool')) ||
|
||||||
|
disableAllButtons
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'r',
|
'r',
|
||||||
() =>
|
() =>
|
||||||
state.matches('Sketch.Rectangle tool')
|
state.matches('Sketch.Rectangle tool')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip rectangle tool'),
|
: send({
|
||||||
{ enabled: !disableAllButtons, scopes: ['sketch'] }
|
type: 'change tool',
|
||||||
|
data: 'rectangle',
|
||||||
|
}),
|
||||||
|
{ enabled: !disableRectangle, scopes: ['sketch'] }
|
||||||
)
|
)
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
's',
|
's',
|
||||||
@ -82,7 +104,7 @@ export function Toolbar({
|
|||||||
useHotkeys(
|
useHotkeys(
|
||||||
'esc',
|
'esc',
|
||||||
() =>
|
() =>
|
||||||
state.matches('Sketch.SketchIdle')
|
['Sketch no face', 'Sketch.SketchIdle'].some(state.matches)
|
||||||
? send('Cancel')
|
? send('Cancel')
|
||||||
: send('CancelSketch'),
|
: send('CancelSketch'),
|
||||||
{ enabled: !disableAllButtons, scopes: ['sketch'] }
|
{ enabled: !disableAllButtons, scopes: ['sketch'] }
|
||||||
@ -225,6 +247,11 @@ export function Toolbar({
|
|||||||
</ActionButton>
|
</ActionButton>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
{state.matches('Sketch no face') && (
|
||||||
|
<li className="contents">
|
||||||
|
<div className="mx-2 text-sm">click plane or face to sketch on</div>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
{state.matches('Sketch') && !state.matches('idle') && (
|
{state.matches('Sketch') && !state.matches('idle') && (
|
||||||
<>
|
<>
|
||||||
<li className="contents" key="line-button">
|
<li className="contents" key="line-button">
|
||||||
@ -234,7 +261,10 @@ export function Toolbar({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
state?.matches('Sketch.Line tool')
|
state?.matches('Sketch.Line tool')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip Line tool')
|
: send({
|
||||||
|
type: 'change tool',
|
||||||
|
data: 'line',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
aria-pressed={state?.matches('Sketch.Line tool')}
|
aria-pressed={state?.matches('Sketch.Line tool')}
|
||||||
iconStart={{
|
iconStart={{
|
||||||
@ -242,7 +272,7 @@ export function Toolbar({
|
|||||||
iconClassName,
|
iconClassName,
|
||||||
bgClassName,
|
bgClassName,
|
||||||
}}
|
}}
|
||||||
disabled={disableAllButtons}
|
disabled={disableLineButton}
|
||||||
>
|
>
|
||||||
Line
|
Line
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -261,7 +291,10 @@ export function Toolbar({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
state.matches('Sketch.Tangential arc to')
|
state.matches('Sketch.Tangential arc to')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip tangential arc to')
|
: send({
|
||||||
|
type: 'change tool',
|
||||||
|
data: 'tangentialArc',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
aria-pressed={state.matches('Sketch.Tangential arc to')}
|
aria-pressed={state.matches('Sketch.Tangential arc to')}
|
||||||
iconStart={{
|
iconStart={{
|
||||||
@ -269,11 +302,7 @@ export function Toolbar({
|
|||||||
iconClassName,
|
iconClassName,
|
||||||
bgClassName,
|
bgClassName,
|
||||||
}}
|
}}
|
||||||
disabled={
|
disabled={disableTangentialArc}
|
||||||
(!state.can('Equip tangential arc to') &&
|
|
||||||
!state.matches('Sketch.Tangential arc to')) ||
|
|
||||||
disableAllButtons
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
Tangential Arc
|
Tangential Arc
|
||||||
<Tooltip
|
<Tooltip
|
||||||
@ -292,7 +321,10 @@ export function Toolbar({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
state.matches('Sketch.Rectangle tool')
|
state.matches('Sketch.Rectangle tool')
|
||||||
? send('CancelSketch')
|
? send('CancelSketch')
|
||||||
: send('Equip rectangle tool')
|
: send({
|
||||||
|
type: 'change tool',
|
||||||
|
data: 'rectangle',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
aria-pressed={state.matches('Sketch.Rectangle tool')}
|
aria-pressed={state.matches('Sketch.Rectangle tool')}
|
||||||
iconStart={{
|
iconStart={{
|
||||||
@ -300,13 +332,9 @@ export function Toolbar({
|
|||||||
iconClassName,
|
iconClassName,
|
||||||
bgClassName,
|
bgClassName,
|
||||||
}}
|
}}
|
||||||
disabled={
|
disabled={disableRectangle}
|
||||||
(!state.can('Equip rectangle tool') &&
|
|
||||||
!state.matches('Sketch.Rectangle tool')) ||
|
|
||||||
disableAllButtons
|
|
||||||
}
|
|
||||||
title={
|
title={
|
||||||
state.can('Equip rectangle tool')
|
canRectangleTool(context)
|
||||||
? 'Rectangle'
|
? 'Rectangle'
|
||||||
: 'Can only be used when a sketch is empty currently'
|
: 'Can only be used when a sketch is empty currently'
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import { Dialog, Popover, Transition } from '@headlessui/react'
|
|||||||
import { LineInputsType } from 'lang/std/sketchcombos'
|
import { LineInputsType } from 'lang/std/sketchcombos'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { InstanceProps, create } from 'react-modal-promise'
|
import { InstanceProps, create } from 'react-modal-promise'
|
||||||
import { executeAst } from 'useStore'
|
import { executeAst } from 'lang/langHelpers'
|
||||||
import {
|
import {
|
||||||
deleteSegmentFromPipeExpression,
|
deleteSegmentFromPipeExpression,
|
||||||
makeRemoveSingleConstraintInput,
|
makeRemoveSingleConstraintInput,
|
||||||
|
@ -58,7 +58,7 @@ import {
|
|||||||
editorManager,
|
editorManager,
|
||||||
} from 'lib/singletons'
|
} from 'lib/singletons'
|
||||||
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
|
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
|
||||||
import { executeAst, useStore } from 'useStore'
|
import { executeAst } from 'lang/langHelpers'
|
||||||
import {
|
import {
|
||||||
createArcGeometry,
|
createArcGeometry,
|
||||||
dashedStraight,
|
dashedStraight,
|
||||||
@ -804,7 +804,7 @@ export class SceneEntities {
|
|||||||
|
|
||||||
// Update the primary AST and unequip the rectangle tool
|
// Update the primary AST and unequip the rectangle tool
|
||||||
await kclManager.executeAstMock(_ast)
|
await kclManager.executeAstMock(_ast)
|
||||||
sceneInfra.modelingSend({ type: 'CancelSketch' })
|
sceneInfra.modelingSend({ type: 'Finish rectangle' })
|
||||||
|
|
||||||
const { programMemory } = await executeAst({
|
const { programMemory } = await executeAst({
|
||||||
ast: _ast,
|
ast: _ast,
|
||||||
@ -1444,11 +1444,10 @@ export class SceneEntities {
|
|||||||
selected.material.color = defaultPlaneColor(type)
|
selected.material.color = defaultPlaneColor(type)
|
||||||
},
|
},
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
const { streamDimensions } = useStore.getState()
|
|
||||||
const { entity_id } = await sendSelectEventToEngine(
|
const { entity_id } = await sendSelectEventToEngine(
|
||||||
args?.mouseEvent,
|
args?.mouseEvent,
|
||||||
document.getElementById('video-stream') as HTMLVideoElement,
|
document.getElementById('video-stream') as HTMLVideoElement,
|
||||||
streamDimensions
|
sceneInfra._streamDimensions
|
||||||
)
|
)
|
||||||
|
|
||||||
let _entity_id = entity_id
|
let _entity_id = entity_id
|
||||||
|
@ -103,6 +103,10 @@ export class SceneInfra {
|
|||||||
_baseUnit: BaseUnit = 'mm'
|
_baseUnit: BaseUnit = 'mm'
|
||||||
_baseUnitMultiplier = 1
|
_baseUnitMultiplier = 1
|
||||||
_theme: Themes = Themes.System
|
_theme: Themes = Themes.System
|
||||||
|
_streamDimensions: { streamWidth: number; streamHeight: number } = {
|
||||||
|
streamWidth: 1280,
|
||||||
|
streamHeight: 720,
|
||||||
|
}
|
||||||
extraSegmentTexture: Texture
|
extraSegmentTexture: Texture
|
||||||
lastMouseState: MouseState = { type: 'idle' }
|
lastMouseState: MouseState = { type: 'idle' }
|
||||||
onDragStartCallback: (arg: OnDragCallbackArgs) => void = () => {}
|
onDragStartCallback: (arg: OnDragCallbackArgs) => void = () => {}
|
||||||
|
@ -10,7 +10,7 @@ import { findAllPreviousVariables, PrevVariable } from '../lang/queryAst'
|
|||||||
import { engineCommandManager, kclManager } from 'lib/singletons'
|
import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||||
import { useKclContext } from 'lang/KclProvider'
|
import { useKclContext } from 'lang/KclProvider'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
import { executeAst } from 'useStore'
|
import { executeAst } from 'lang/langHelpers'
|
||||||
import { trap } from 'lib/trap'
|
import { trap } from 'lib/trap'
|
||||||
|
|
||||||
export const AvailableVars = ({
|
export const AvailableVars = ({
|
||||||
|
@ -24,7 +24,7 @@ export const CommandBar = () => {
|
|||||||
}, [pathname])
|
}, [pathname])
|
||||||
|
|
||||||
// Hook up keyboard shortcuts
|
// Hook up keyboard shortcuts
|
||||||
useHotkeyWrapper(['mod+k', 'ctrl+c'], () => {
|
useHotkeyWrapper(['mod+k'], () => {
|
||||||
if (commandBarState.context.commands.length === 0) return
|
if (commandBarState.context.commands.length === 0) return
|
||||||
if (commandBarState.matches('Closed')) {
|
if (commandBarState.matches('Closed')) {
|
||||||
commandBarSend({ type: 'Open' })
|
commandBarSend({ type: 'Open' })
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Completion } from '@codemirror/autocomplete'
|
import { Completion } from '@codemirror/autocomplete'
|
||||||
import { EditorState, EditorView, useCodeMirror } from '@uiw/react-codemirror'
|
import { EditorView, ViewUpdate } from '@codemirror/view'
|
||||||
|
import { EditorState } from '@codemirror/state'
|
||||||
import { CustomIcon } from 'components/CustomIcon'
|
import { CustomIcon } from 'components/CustomIcon'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
@ -12,6 +13,7 @@ import { useEffect, useRef, useState } from 'react'
|
|||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import styles from './CommandBarKclInput.module.css'
|
import styles from './CommandBarKclInput.module.css'
|
||||||
import { createIdentifier, createVariableDeclaration } from 'lang/modifyAst'
|
import { createIdentifier, createVariableDeclaration } from 'lang/modifyAst'
|
||||||
|
import { useCodeMirror } from 'components/ModelingSidebar/ModelingPanes/CodeEditor'
|
||||||
|
|
||||||
function CommandBarKclInput({
|
function CommandBarKclInput({
|
||||||
arg,
|
arg,
|
||||||
@ -63,9 +65,7 @@ function CommandBarKclInput({
|
|||||||
|
|
||||||
const { setContainer } = useCodeMirror({
|
const { setContainer } = useCodeMirror({
|
||||||
container: editorRef.current,
|
container: editorRef.current,
|
||||||
value,
|
initialDocValue: value,
|
||||||
indentWithTab: false,
|
|
||||||
basicSetup: false,
|
|
||||||
autoFocus: true,
|
autoFocus: true,
|
||||||
selection: {
|
selection: {
|
||||||
anchor: 0,
|
anchor: 0,
|
||||||
@ -74,7 +74,6 @@ function CommandBarKclInput({
|
|||||||
? previouslySetValue.valueText.length
|
? previouslySetValue.valueText.length
|
||||||
: defaultValue.length,
|
: defaultValue.length,
|
||||||
},
|
},
|
||||||
accessKey: 'command-bar',
|
|
||||||
theme:
|
theme:
|
||||||
settings.context.app.theme.current === 'system'
|
settings.context.app.theme.current === 'system'
|
||||||
? getSystemTheme()
|
? getSystemTheme()
|
||||||
@ -96,8 +95,12 @@ function CommandBarKclInput({
|
|||||||
}
|
}
|
||||||
return tr
|
return tr
|
||||||
}),
|
}),
|
||||||
|
EditorView.updateListener.of((vu: ViewUpdate) => {
|
||||||
|
if (vu.docChanged) {
|
||||||
|
setValue(vu.state.doc.toString())
|
||||||
|
}
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
onChange: (newValue) => setValue(newValue),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -175,7 +175,11 @@ const FileTreeItem = ({
|
|||||||
codeManager.code
|
codeManager.code
|
||||||
)
|
)
|
||||||
codeManager.writeToFile()
|
codeManager.writeToFile()
|
||||||
kclManager.executeCode(true, true)
|
|
||||||
|
kclManager.isFirstRender = true
|
||||||
|
kclManager.executeCode(true, true).then(() => {
|
||||||
|
kclManager.isFirstRender = false
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// Let the lsp servers know we closed a file.
|
// Let the lsp servers know we closed a file.
|
||||||
onFileClose(currentFile?.path || null, project?.path || null)
|
onFileClose(currentFile?.path || null, project?.path || null)
|
||||||
|
@ -119,7 +119,7 @@ export default function Gizmo() {
|
|||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
aria-label="View orientation gizmo"
|
aria-label="View orientation gizmo"
|
||||||
className="grid place-content-center rounded-full overflow-hidden border border-solid border-primary/50 pointer-events-auto"
|
className="grid place-content-center rounded-full overflow-hidden border border-solid border-primary/50 pointer-events-auto bg-chalkboard-10/70 dark:bg-chalkboard-100/80 backdrop-blur-sm"
|
||||||
>
|
>
|
||||||
<canvas ref={canvasRef} />
|
<canvas ref={canvasRef} />
|
||||||
<ContextMenu
|
<ContextMenu
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
import type * as LSP from 'vscode-languageserver-protocol'
|
import type * as LSP from 'vscode-languageserver-protocol'
|
||||||
import React, {
|
import React, { createContext, useMemo, useContext, useState } from 'react'
|
||||||
createContext,
|
|
||||||
useMemo,
|
|
||||||
useEffect,
|
|
||||||
useContext,
|
|
||||||
useState,
|
|
||||||
} from 'react'
|
|
||||||
import {
|
import {
|
||||||
LanguageServerClient,
|
LanguageServerClient,
|
||||||
FromServer,
|
FromServer,
|
||||||
@ -16,7 +10,6 @@ import {
|
|||||||
import { TEST, VITE_KC_API_BASE_URL } from 'env'
|
import { TEST, VITE_KC_API_BASE_URL } from 'env'
|
||||||
import KclLanguageSupport from 'editor/plugins/lsp/kcl/language'
|
import KclLanguageSupport from 'editor/plugins/lsp/kcl/language'
|
||||||
import { copilotPlugin } from 'editor/plugins/lsp/copilot'
|
import { copilotPlugin } from 'editor/plugins/lsp/copilot'
|
||||||
import { useStore } from 'useStore'
|
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
import { Extension } from '@codemirror/state'
|
import { Extension } from '@codemirror/state'
|
||||||
import { LanguageSupport } from '@codemirror/language'
|
import { LanguageSupport } from '@codemirror/language'
|
||||||
@ -73,19 +66,8 @@ type LspContext = {
|
|||||||
|
|
||||||
export const LspStateContext = createContext({} as LspContext)
|
export const LspStateContext = createContext({} as LspContext)
|
||||||
export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
const {
|
const [isKclLspReady, setIsKclLspReady] = useState(false)
|
||||||
isKclLspServerReady,
|
const [isCopilotLspReady, setIsCopilotLspReady] = useState(false)
|
||||||
isCopilotLspServerReady,
|
|
||||||
setIsKclLspServerReady,
|
|
||||||
setIsCopilotLspServerReady,
|
|
||||||
} = useStore((s) => ({
|
|
||||||
isKclLspServerReady: s.isKclLspServerReady,
|
|
||||||
isCopilotLspServerReady: s.isCopilotLspServerReady,
|
|
||||||
setIsKclLspServerReady: s.setIsKclLspServerReady,
|
|
||||||
setIsCopilotLspServerReady: s.setIsCopilotLspServerReady,
|
|
||||||
}))
|
|
||||||
const [isLspReady, setIsLspReady] = useState(false)
|
|
||||||
const [isCopilotReady, setIsCopilotReady] = useState(false)
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
auth,
|
auth,
|
||||||
@ -132,7 +114,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
fromServer,
|
fromServer,
|
||||||
intoServer,
|
intoServer,
|
||||||
initializedCallback: () => {
|
initializedCallback: () => {
|
||||||
setIsLspReady(true)
|
setIsKclLspReady(true)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -143,7 +125,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
])
|
])
|
||||||
|
|
||||||
useMemo(() => {
|
useMemo(() => {
|
||||||
if (!isTauri() && isKclLspServerReady && kclLspClient && codeManager.code) {
|
if (!isTauri() && isKclLspReady && kclLspClient && codeManager.code) {
|
||||||
kclLspClient.textDocumentDidOpen({
|
kclLspClient.textDocumentDidOpen({
|
||||||
textDocument: {
|
textDocument: {
|
||||||
uri: `file:///${PROJECT_ENTRYPOINT}`,
|
uri: `file:///${PROJECT_ENTRYPOINT}`,
|
||||||
@ -153,7 +135,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [kclLspClient, isKclLspServerReady])
|
}, [kclLspClient, isKclLspReady])
|
||||||
|
|
||||||
// Here we initialize the plugin which will start the client.
|
// Here we initialize the plugin which will start the client.
|
||||||
// Now that we have multi-file support the name of the file is a dep of
|
// Now that we have multi-file support the name of the file is a dep of
|
||||||
@ -162,7 +144,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
// We do not want to restart the server, its just wasteful.
|
// We do not want to restart the server, its just wasteful.
|
||||||
const kclLSP = useMemo(() => {
|
const kclLSP = useMemo(() => {
|
||||||
let plugin = null
|
let plugin = null
|
||||||
if (isKclLspServerReady && !TEST && kclLspClient) {
|
if (isKclLspReady && !TEST && kclLspClient) {
|
||||||
// Set up the lsp plugin.
|
// Set up the lsp plugin.
|
||||||
const lsp = new KclLanguageSupport({
|
const lsp = new KclLanguageSupport({
|
||||||
documentUri: `file:///${PROJECT_ENTRYPOINT}`,
|
documentUri: `file:///${PROJECT_ENTRYPOINT}`,
|
||||||
@ -193,7 +175,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
plugin = lsp
|
plugin = lsp
|
||||||
}
|
}
|
||||||
return plugin
|
return plugin
|
||||||
}, [kclLspClient, isKclLspServerReady])
|
}, [kclLspClient, isKclLspReady])
|
||||||
|
|
||||||
const { lspClient: copilotLspClient } = useMemo(() => {
|
const { lspClient: copilotLspClient } = useMemo(() => {
|
||||||
if (!token || token === '' || TEST) {
|
if (!token || token === '' || TEST) {
|
||||||
@ -225,7 +207,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
fromServer,
|
fromServer,
|
||||||
intoServer,
|
intoServer,
|
||||||
initializedCallback: () => {
|
initializedCallback: () => {
|
||||||
setIsCopilotReady(true)
|
setIsCopilotLspReady(true)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return { lspClient }
|
return { lspClient }
|
||||||
@ -238,7 +220,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
// We do not want to restart the server, its just wasteful.
|
// We do not want to restart the server, its just wasteful.
|
||||||
const copilotLSP = useMemo(() => {
|
const copilotLSP = useMemo(() => {
|
||||||
let plugin = null
|
let plugin = null
|
||||||
if (isCopilotLspServerReady && !TEST && copilotLspClient) {
|
if (isCopilotLspReady && !TEST && copilotLspClient) {
|
||||||
// Set up the lsp plugin.
|
// Set up the lsp plugin.
|
||||||
const lsp = copilotPlugin({
|
const lsp = copilotPlugin({
|
||||||
documentUri: `file:///${PROJECT_ENTRYPOINT}`,
|
documentUri: `file:///${PROJECT_ENTRYPOINT}`,
|
||||||
@ -250,7 +232,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
plugin = lsp
|
plugin = lsp
|
||||||
}
|
}
|
||||||
return plugin
|
return plugin
|
||||||
}, [copilotLspClient, isCopilotLspServerReady])
|
}, [copilotLspClient, isCopilotLspReady])
|
||||||
|
|
||||||
let lspClients: LanguageServerClient[] = []
|
let lspClients: LanguageServerClient[] = []
|
||||||
if (kclLspClient) {
|
if (kclLspClient) {
|
||||||
@ -260,13 +242,6 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
lspClients.push(copilotLspClient)
|
lspClients.push(copilotLspClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsKclLspServerReady(isLspReady)
|
|
||||||
}, [isLspReady])
|
|
||||||
useEffect(() => {
|
|
||||||
setIsCopilotLspServerReady(isCopilotReady)
|
|
||||||
}, [isCopilotReady])
|
|
||||||
|
|
||||||
const onProjectClose = (
|
const onProjectClose = (
|
||||||
file: FileEntry | null,
|
file: FileEntry | null,
|
||||||
projectPath: string | null,
|
projectPath: string | null,
|
||||||
|
@ -30,7 +30,6 @@ import {
|
|||||||
applyConstraintAngleBetween,
|
applyConstraintAngleBetween,
|
||||||
} from './Toolbar/SetAngleBetween'
|
} from './Toolbar/SetAngleBetween'
|
||||||
import { applyConstraintAngleLength } from './Toolbar/setAngleLength'
|
import { applyConstraintAngleLength } from './Toolbar/setAngleLength'
|
||||||
import { useStore } from 'useStore'
|
|
||||||
import {
|
import {
|
||||||
Selections,
|
Selections,
|
||||||
canExtrudeSelection,
|
canExtrudeSelection,
|
||||||
@ -54,15 +53,8 @@ import {
|
|||||||
sketchOnExtrudedFace,
|
sketchOnExtrudedFace,
|
||||||
startSketchOnDefault,
|
startSketchOnDefault,
|
||||||
} from 'lang/modifyAst'
|
} from 'lang/modifyAst'
|
||||||
|
import { Program, parse, recast } from 'lang/wasm'
|
||||||
import {
|
import {
|
||||||
Program,
|
|
||||||
VariableDeclaration,
|
|
||||||
coreDump,
|
|
||||||
parse,
|
|
||||||
recast,
|
|
||||||
} from 'lang/wasm'
|
|
||||||
import {
|
|
||||||
getNodeFromPath,
|
|
||||||
getNodePathFromSourceRange,
|
getNodePathFromSourceRange,
|
||||||
hasExtrudableGeometry,
|
hasExtrudableGeometry,
|
||||||
isSingleCursorInPipe,
|
isSingleCursorInPipe,
|
||||||
@ -71,12 +63,10 @@ import { TEST } from 'env'
|
|||||||
import { exportFromEngine } from 'lib/exportFromEngine'
|
import { exportFromEngine } from 'lib/exportFromEngine'
|
||||||
import { Models } from '@kittycad/lib/dist/types/src'
|
import { Models } from '@kittycad/lib/dist/types/src'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { EditorSelection, Transaction } from '@uiw/react-codemirror'
|
import { EditorSelection, Transaction } from '@codemirror/state'
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
|
||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import { letEngineAnimateAndSyncCamAfter } from 'clientSideScene/CameraControls'
|
import { letEngineAnimateAndSyncCamAfter } from 'clientSideScene/CameraControls'
|
||||||
import { getVarNameModal } from 'hooks/useToolbarGuards'
|
import { getVarNameModal } from 'hooks/useToolbarGuards'
|
||||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
import { err, trap } from 'lib/trap'
|
import { err, trap } from 'lib/trap'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
@ -112,38 +102,6 @@ export const ModelingMachineProvider = ({
|
|||||||
let [searchParams] = useSearchParams()
|
let [searchParams] = useSearchParams()
|
||||||
const pool = searchParams.get('pool')
|
const pool = searchParams.get('pool')
|
||||||
|
|
||||||
useSetupEngineManager(streamRef, token, {
|
|
||||||
pool: pool,
|
|
||||||
theme: theme.current,
|
|
||||||
highlightEdges: highlightEdges.current,
|
|
||||||
enableSSAO: enableSSAO.current,
|
|
||||||
showScaleGrid: showScaleGrid.current,
|
|
||||||
})
|
|
||||||
const { htmlRef } = useStore((s) => ({
|
|
||||||
htmlRef: s.htmlRef,
|
|
||||||
}))
|
|
||||||
const coreDumpManager = new CoreDumpManager(
|
|
||||||
engineCommandManager,
|
|
||||||
htmlRef,
|
|
||||||
token
|
|
||||||
)
|
|
||||||
useHotkeyWrapper(['meta + shift + .'], () => {
|
|
||||||
toast.promise(
|
|
||||||
coreDump(coreDumpManager, true),
|
|
||||||
{
|
|
||||||
loading: 'Starting core dump...',
|
|
||||||
success: 'Core dump completed successfully',
|
|
||||||
error: 'Error while exporting core dump',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
success: {
|
|
||||||
// Note: this extended duration is especially important for Playwright e2e testing
|
|
||||||
// default duration is 2000 - https://react-hot-toast.com/docs/toast#default-durations
|
|
||||||
duration: 6000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const { commandBarState } = useCommandsContext()
|
const { commandBarState } = useCommandsContext()
|
||||||
|
|
||||||
// Settings machine setup
|
// Settings machine setup
|
||||||
@ -163,7 +121,13 @@ export const ModelingMachineProvider = ({
|
|||||||
modelingMachine,
|
modelingMachine,
|
||||||
{
|
{
|
||||||
actions: {
|
actions: {
|
||||||
'sketch exit execute': () => {
|
'disable copilot': () => {
|
||||||
|
editorManager.setCopilotEnabled(false)
|
||||||
|
},
|
||||||
|
'enable copilot': () => {
|
||||||
|
editorManager.setCopilotEnabled(true)
|
||||||
|
},
|
||||||
|
'sketch exit execute': ({ store }) => {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await sceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine()
|
await sceneInfra.camControls.snapToPerspectiveBeforeHandingBackControlToEngine()
|
||||||
|
|
||||||
@ -197,7 +161,12 @@ export const ModelingMachineProvider = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
kclManager.executeCode(true)
|
store.videoElement?.pause()
|
||||||
|
kclManager.executeCode(true).then(() => {
|
||||||
|
if (engineCommandManager.engineConnection?.freezeFrame) return
|
||||||
|
|
||||||
|
store.videoElement?.play()
|
||||||
|
})
|
||||||
})()
|
})()
|
||||||
},
|
},
|
||||||
'Set mouse state': assign({
|
'Set mouse state': assign({
|
||||||
@ -473,17 +442,6 @@ export const ModelingMachineProvider = ({
|
|||||||
if (selectionRanges.codeBasedSelections.length <= 0) return false
|
if (selectionRanges.codeBasedSelections.length <= 0) return false
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
'Sketch is empty': ({ sketchDetails }) => {
|
|
||||||
const node = getNodeFromPath<VariableDeclaration>(
|
|
||||||
kclManager.ast,
|
|
||||||
sketchDetails?.sketchPathToNode || [],
|
|
||||||
'VariableDeclaration'
|
|
||||||
)
|
|
||||||
// This should not be returning false, and it should be caught
|
|
||||||
// but we need to simulate old behavior to move on.
|
|
||||||
if (err(node)) return false
|
|
||||||
return node.node?.declarations?.[0]?.init.type !== 'PipeExpression'
|
|
||||||
},
|
|
||||||
'Selection is on face': ({ selectionRanges }, { data }) => {
|
'Selection is on face': ({ selectionRanges }, { data }) => {
|
||||||
if (data?.forceNewSketch) return false
|
if (data?.forceNewSketch) return false
|
||||||
if (!isSingleCursorInPipe(selectionRanges, kclManager.ast))
|
if (!isSingleCursorInPipe(selectionRanges, kclManager.ast))
|
||||||
@ -514,11 +472,15 @@ export const ModelingMachineProvider = ({
|
|||||||
services: {
|
services: {
|
||||||
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
|
'AST-undo-startSketchOn': async ({ sketchDetails }) => {
|
||||||
if (!sketchDetails) return
|
if (!sketchDetails) return
|
||||||
const newAst: Program = JSON.parse(JSON.stringify(kclManager.ast))
|
if (kclManager.ast.body.length) {
|
||||||
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
|
// this assumes no changes have been made to the sketch besides what we did when entering the sketch
|
||||||
// remove body item at varDecIndex
|
// i.e. doesn't account for user's adding code themselves, maybe we need store a flag userEditedSinceSketchMode?
|
||||||
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
|
const newAst: Program = JSON.parse(JSON.stringify(kclManager.ast))
|
||||||
await kclManager.executeAstMock(newAst)
|
const varDecIndex = sketchDetails.sketchPathToNode[1][0]
|
||||||
|
// remove body item at varDecIndex
|
||||||
|
newAst.body = newAst.body.filter((_, i) => i !== varDecIndex)
|
||||||
|
await kclManager.executeAstMock(newAst)
|
||||||
|
}
|
||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
onClick: () => {},
|
onClick: () => {},
|
||||||
onDrag: () => {},
|
onDrag: () => {},
|
||||||
@ -898,6 +860,16 @@ export const ModelingMachineProvider = ({
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
useSetupEngineManager(streamRef, token, {
|
||||||
|
pool: pool,
|
||||||
|
theme: theme.current,
|
||||||
|
highlightEdges: highlightEdges.current,
|
||||||
|
enableSSAO: enableSSAO.current,
|
||||||
|
modelingSend,
|
||||||
|
modelingContext: modelingState.context,
|
||||||
|
showScaleGrid: showScaleGrid.current,
|
||||||
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
kclManager.registerExecuteCallback(() => {
|
kclManager.registerExecuteCallback(() => {
|
||||||
modelingSend({ type: 'Re-execute' })
|
modelingSend({ type: 'Re-execute' })
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useStore } from 'useStore'
|
|
||||||
import styles from './ModelingPane.module.css'
|
import styles from './ModelingPane.module.css'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
|
||||||
export interface ModelingPaneProps
|
export interface ModelingPaneProps
|
||||||
extends React.PropsWithChildren,
|
extends React.PropsWithChildren,
|
||||||
@ -33,11 +33,9 @@ export const ModelingPane = ({
|
|||||||
}: ModelingPaneProps) => {
|
}: ModelingPaneProps) => {
|
||||||
const { settings } = useSettingsAuthContext()
|
const { settings } = useSettingsAuthContext()
|
||||||
const onboardingStatus = settings.context.app.onboardingStatus
|
const onboardingStatus = settings.context.app.onboardingStatus
|
||||||
const { buttonDownInStream } = useStore((s) => ({
|
const { context } = useModelingContext()
|
||||||
buttonDownInStream: s.buttonDownInStream,
|
|
||||||
}))
|
|
||||||
const pointerEventsCssClass =
|
const pointerEventsCssClass =
|
||||||
buttonDownInStream || onboardingStatus.current === 'camera'
|
context.store?.buttonDownInStream || onboardingStatus.current === 'camera'
|
||||||
? 'pointer-events-none '
|
? 'pointer-events-none '
|
||||||
: 'pointer-events-auto '
|
: 'pointer-events-auto '
|
||||||
return (
|
return (
|
||||||
|
171
src/components/ModelingSidebar/ModelingPanes/CodeEditor.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import React, {
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
forwardRef,
|
||||||
|
useImperativeHandle,
|
||||||
|
} from 'react'
|
||||||
|
import {
|
||||||
|
EditorState,
|
||||||
|
EditorStateConfig,
|
||||||
|
Extension,
|
||||||
|
StateEffect,
|
||||||
|
} from '@codemirror/state'
|
||||||
|
import { EditorView } from '@codemirror/view'
|
||||||
|
import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
|
||||||
|
//reference: https://github.com/sachinraja/rodemirror/blob/main/src/use-first-render.ts
|
||||||
|
const useFirstRender = () => {
|
||||||
|
const firstRender = useRef(true)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
firstRender.current = false
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return firstRender.current
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultLightThemeOption = EditorView.theme(
|
||||||
|
{
|
||||||
|
'&': {
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dark: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
interface CodeEditorRef {
|
||||||
|
editor?: HTMLDivElement | null
|
||||||
|
view?: EditorView
|
||||||
|
state?: EditorState
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CodeEditorProps {
|
||||||
|
onCreateEditor?: (view: EditorView | null) => void
|
||||||
|
initialDocValue?: EditorStateConfig['doc']
|
||||||
|
extensions?: Extension
|
||||||
|
theme: 'light' | 'dark'
|
||||||
|
autoFocus?: boolean
|
||||||
|
selection?: EditorStateConfig['selection']
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UseCodeMirror extends CodeEditorProps {
|
||||||
|
container?: HTMLDivElement | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const CodeEditor = forwardRef<CodeEditorRef, CodeEditorProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
onCreateEditor,
|
||||||
|
extensions = [],
|
||||||
|
initialDocValue,
|
||||||
|
theme,
|
||||||
|
autoFocus = false,
|
||||||
|
selection,
|
||||||
|
} = props
|
||||||
|
const editor = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
const { view, state, container } = useCodeMirror({
|
||||||
|
container: editor.current,
|
||||||
|
onCreateEditor,
|
||||||
|
extensions,
|
||||||
|
initialDocValue,
|
||||||
|
theme,
|
||||||
|
autoFocus,
|
||||||
|
selection,
|
||||||
|
})
|
||||||
|
|
||||||
|
useImperativeHandle(
|
||||||
|
ref,
|
||||||
|
() => ({ editor: editor.current, view: view, state: state }),
|
||||||
|
[editor, container, view, state]
|
||||||
|
)
|
||||||
|
|
||||||
|
return <div ref={editor}></div>
|
||||||
|
})
|
||||||
|
|
||||||
|
export function useCodeMirror(props: UseCodeMirror) {
|
||||||
|
const {
|
||||||
|
onCreateEditor,
|
||||||
|
extensions = [],
|
||||||
|
initialDocValue,
|
||||||
|
theme,
|
||||||
|
autoFocus = false,
|
||||||
|
selection,
|
||||||
|
} = props
|
||||||
|
|
||||||
|
const [container, setContainer] = useState<HTMLDivElement | null>()
|
||||||
|
const [view, setView] = useState<EditorView>()
|
||||||
|
const [state, setState] = useState<EditorState>()
|
||||||
|
|
||||||
|
const isFirstRender = useFirstRender()
|
||||||
|
|
||||||
|
const targetExtensions = useMemo(() => {
|
||||||
|
let exts = Array.isArray(extensions) ? extensions : []
|
||||||
|
if (theme === 'dark') {
|
||||||
|
exts = [...exts, oneDark]
|
||||||
|
} else if (theme === 'light') {
|
||||||
|
exts = [...exts, defaultLightThemeOption]
|
||||||
|
}
|
||||||
|
|
||||||
|
return exts
|
||||||
|
}, [extensions, theme])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (container && !state) {
|
||||||
|
const config = {
|
||||||
|
doc: initialDocValue,
|
||||||
|
selection,
|
||||||
|
extensions: [...Array.of(extensions)],
|
||||||
|
}
|
||||||
|
const stateCurrent = EditorState.create(config)
|
||||||
|
setState(stateCurrent)
|
||||||
|
if (!view) {
|
||||||
|
const viewCurrent = new EditorView({
|
||||||
|
state: stateCurrent,
|
||||||
|
parent: container,
|
||||||
|
})
|
||||||
|
setView(viewCurrent)
|
||||||
|
onCreateEditor && onCreateEditor(viewCurrent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (view) {
|
||||||
|
setState(undefined)
|
||||||
|
setView(undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [container, state])
|
||||||
|
|
||||||
|
useEffect(() => setContainer(props.container), [props.container])
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => () => {
|
||||||
|
if (view) {
|
||||||
|
view.destroy()
|
||||||
|
setView(undefined)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[view]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (autoFocus && view) {
|
||||||
|
view.focus()
|
||||||
|
}
|
||||||
|
}, [autoFocus, view])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (view && !isFirstRender) {
|
||||||
|
view.dispatch({
|
||||||
|
effects: StateEffect.reconfigure.of(targetExtensions),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [targetExtensions])
|
||||||
|
|
||||||
|
return { view, setView, container, setContainer, state, setState }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CodeEditor
|
@ -1,4 +1,3 @@
|
|||||||
import ReactCodeMirror from '@uiw/react-codemirror'
|
|
||||||
import { TEST } from 'env'
|
import { TEST } from 'env'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
import { Themes, getSystemTheme } from 'lib/theme'
|
import { Themes, getSystemTheme } from 'lib/theme'
|
||||||
@ -43,6 +42,7 @@ import {
|
|||||||
closeBracketsKeymap,
|
closeBracketsKeymap,
|
||||||
completionKeymap,
|
completionKeymap,
|
||||||
} from '@codemirror/autocomplete'
|
} from '@codemirror/autocomplete'
|
||||||
|
import CodeEditor from './CodeEditor'
|
||||||
|
|
||||||
export const editorShortcutMeta = {
|
export const editorShortcutMeta = {
|
||||||
formatCode: {
|
formatCode: {
|
||||||
@ -185,15 +185,15 @@ export const KclEditorPane = () => {
|
|||||||
id="code-mirror-override"
|
id="code-mirror-override"
|
||||||
className={'absolute inset-0 ' + (cursorBlinking.current ? 'blink' : '')}
|
className={'absolute inset-0 ' + (cursorBlinking.current ? 'blink' : '')}
|
||||||
>
|
>
|
||||||
<ReactCodeMirror
|
<CodeEditor
|
||||||
value={initialCode.current}
|
initialDocValue={initialCode.current}
|
||||||
extensions={editorExtensions}
|
extensions={editorExtensions}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
onCreateEditor={(_editorView) => {
|
onCreateEditor={(_editorView) => {
|
||||||
|
if (_editorView === null) return
|
||||||
|
|
||||||
editorManager.setEditorView(_editorView)
|
editorManager.setEditorView(_editorView)
|
||||||
}}
|
}}
|
||||||
indentWithTab={false}
|
|
||||||
basicSetup={false}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -2,7 +2,6 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
|||||||
import { Resizable } from 're-resizable'
|
import { Resizable } from 're-resizable'
|
||||||
import { HTMLAttributes, useCallback, useEffect, useState } from 'react'
|
import { HTMLAttributes, useCallback, useEffect, useState } from 'react'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { useStore } from 'useStore'
|
|
||||||
import { Tab } from '@headlessui/react'
|
import { Tab } from '@headlessui/react'
|
||||||
import {
|
import {
|
||||||
SidebarPane,
|
SidebarPane,
|
||||||
@ -15,6 +14,7 @@ import { ActionIcon } from 'components/ActionIcon'
|
|||||||
import styles from './ModelingSidebar.module.css'
|
import styles from './ModelingSidebar.module.css'
|
||||||
import { ModelingPane } from './ModelingPane'
|
import { ModelingPane } from './ModelingPane'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isTauri } from 'lib/isTauri'
|
||||||
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
|
||||||
interface ModelingSidebarProps {
|
interface ModelingSidebarProps {
|
||||||
paneOpacity: '' | 'opacity-20' | 'opacity-40'
|
paneOpacity: '' | 'opacity-20' | 'opacity-40'
|
||||||
@ -23,14 +23,11 @@ interface ModelingSidebarProps {
|
|||||||
export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
||||||
const { settings } = useSettingsAuthContext()
|
const { settings } = useSettingsAuthContext()
|
||||||
const onboardingStatus = settings.context.app.onboardingStatus
|
const onboardingStatus = settings.context.app.onboardingStatus
|
||||||
const { openPanes, buttonDownInStream } = useStore((s) => ({
|
const { context } = useModelingContext()
|
||||||
buttonDownInStream: s.buttonDownInStream,
|
|
||||||
openPanes: s.openPanes,
|
|
||||||
}))
|
|
||||||
const pointerEventsCssClass =
|
const pointerEventsCssClass =
|
||||||
buttonDownInStream ||
|
context.store?.buttonDownInStream ||
|
||||||
onboardingStatus.current === 'camera' ||
|
onboardingStatus.current === 'camera' ||
|
||||||
openPanes.length === 0
|
context.store?.openPanes.length === 0
|
||||||
? 'pointer-events-none '
|
? 'pointer-events-none '
|
||||||
: 'pointer-events-auto '
|
: 'pointer-events-auto '
|
||||||
|
|
||||||
@ -45,7 +42,7 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
|||||||
maxWidth={800}
|
maxWidth={800}
|
||||||
handleClasses={{
|
handleClasses={{
|
||||||
right:
|
right:
|
||||||
(openPanes.length === 0 ? 'hidden ' : 'block ') +
|
(context.store?.openPanes.length === 0 ? 'hidden ' : 'block ') +
|
||||||
'translate-x-1/2 hover:bg-chalkboard-10 hover:dark:bg-chalkboard-110 bg-transparent transition-colors duration-75 transition-ease-out delay-100 ',
|
'translate-x-1/2 hover:bg-chalkboard-10 hover:dark:bg-chalkboard-110 bg-transparent transition-colors duration-75 transition-ease-out delay-100 ',
|
||||||
left: 'hidden',
|
left: 'hidden',
|
||||||
top: 'hidden',
|
top: 'hidden',
|
||||||
@ -82,11 +79,10 @@ function ModelingSidebarSection({
|
|||||||
const { settings } = useSettingsAuthContext()
|
const { settings } = useSettingsAuthContext()
|
||||||
const showDebugPanel = settings.context.modeling.showDebugPanel
|
const showDebugPanel = settings.context.modeling.showDebugPanel
|
||||||
const paneIds = panes.map((pane) => pane.id)
|
const paneIds = panes.map((pane) => pane.id)
|
||||||
const { openPanes, setOpenPanes } = useStore((s) => ({
|
const { send, context } = useModelingContext()
|
||||||
openPanes: s.openPanes,
|
const foundOpenPane = context.store?.openPanes.find((pane) =>
|
||||||
setOpenPanes: s.setOpenPanes,
|
paneIds.includes(pane)
|
||||||
}))
|
)
|
||||||
const foundOpenPane = openPanes.find((pane) => paneIds.includes(pane))
|
|
||||||
const [currentPane, setCurrentPane] = useState(
|
const [currentPane, setCurrentPane] = useState(
|
||||||
foundOpenPane || ('none' as SidebarType | 'none')
|
foundOpenPane || ('none' as SidebarType | 'none')
|
||||||
)
|
)
|
||||||
@ -94,17 +90,37 @@ function ModelingSidebarSection({
|
|||||||
const togglePane = useCallback(
|
const togglePane = useCallback(
|
||||||
(newPane: SidebarType | 'none') => {
|
(newPane: SidebarType | 'none') => {
|
||||||
if (newPane === 'none') {
|
if (newPane === 'none') {
|
||||||
setOpenPanes(openPanes.filter((p) => p !== currentPane))
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: context.store?.openPanes.filter(
|
||||||
|
(p) => p !== currentPane
|
||||||
|
),
|
||||||
|
},
|
||||||
|
})
|
||||||
setCurrentPane('none')
|
setCurrentPane('none')
|
||||||
} else if (newPane === currentPane) {
|
} else if (newPane === currentPane) {
|
||||||
setCurrentPane('none')
|
setCurrentPane('none')
|
||||||
setOpenPanes(openPanes.filter((p) => p !== newPane))
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: context.store?.openPanes.filter((p) => p !== newPane),
|
||||||
|
},
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
setOpenPanes([...openPanes.filter((p) => p !== currentPane), newPane])
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: [
|
||||||
|
...context.store?.openPanes.filter((p) => p !== currentPane),
|
||||||
|
newPane,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
setCurrentPane(newPane)
|
setCurrentPane(newPane)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[openPanes, setOpenPanes, currentPane, setCurrentPane]
|
[context.store?.openPanes, send, currentPane, setCurrentPane]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filter out the debug panel if it's not supposed to be shown
|
// Filter out the debug panel if it's not supposed to be shown
|
||||||
@ -122,11 +138,11 @@ function ModelingSidebarSection({
|
|||||||
if (
|
if (
|
||||||
!showDebugPanel.current &&
|
!showDebugPanel.current &&
|
||||||
currentPane === 'debug' &&
|
currentPane === 'debug' &&
|
||||||
openPanes.includes('debug')
|
context.store?.openPanes.includes('debug')
|
||||||
) {
|
) {
|
||||||
togglePane('debug')
|
togglePane('debug')
|
||||||
}
|
}
|
||||||
}, [showDebugPanel.current, togglePane, openPanes])
|
}, [showDebugPanel.current, togglePane, context.store?.openPanes])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'group contents ' + className} {...props}>
|
<div className={'group contents ' + className} {...props}>
|
||||||
@ -152,7 +168,9 @@ function ModelingSidebarSection({
|
|||||||
: ' border-r-0') +
|
: ' border-r-0') +
|
||||||
' p-2 col-start-1 col-span-1 h-fit w-fit flex flex-col items-start gap-2 ' +
|
' p-2 col-start-1 col-span-1 h-fit w-fit flex flex-col items-start gap-2 ' +
|
||||||
'bg-chalkboard-10 border border-solid border-chalkboard-20 dark:bg-chalkboard-90 dark:border-chalkboard-80 group-focus-within:border-primary dark:group-focus-within:border-chalkboard-50 ' +
|
'bg-chalkboard-10 border border-solid border-chalkboard-20 dark:bg-chalkboard-90 dark:border-chalkboard-80 group-focus-within:border-primary dark:group-focus-within:border-chalkboard-50 ' +
|
||||||
(openPanes.length === 1 && currentPane === 'none' ? 'pr-0.5' : '')
|
(context.store?.openPanes.length === 1 && currentPane === 'none'
|
||||||
|
? 'pr-0.5'
|
||||||
|
: '')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Tab key="none" className="sr-only">
|
<Tab key="none" className="sr-only">
|
||||||
@ -172,7 +190,7 @@ function ModelingSidebarSection({
|
|||||||
as="article"
|
as="article"
|
||||||
className={
|
className={
|
||||||
'col-start-2 col-span-1 ' +
|
'col-start-2 col-span-1 ' +
|
||||||
(openPanes.length === 1
|
(context.store?.openPanes.length === 1
|
||||||
? currentPane !== 'none'
|
? currentPane !== 'none'
|
||||||
? `row-start-1 row-end-3`
|
? `row-start-1 row-end-3`
|
||||||
: `hidden`
|
: `hidden`
|
||||||
|
@ -2,22 +2,17 @@ import { coreDump } from 'lang/wasm'
|
|||||||
import { CoreDumpManager } from 'lib/coredump'
|
import { CoreDumpManager } from 'lib/coredump'
|
||||||
import { CustomIcon } from './CustomIcon'
|
import { CustomIcon } from './CustomIcon'
|
||||||
import { engineCommandManager } from 'lib/singletons'
|
import { engineCommandManager } from 'lib/singletons'
|
||||||
import React from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import Tooltip from './Tooltip'
|
import Tooltip from './Tooltip'
|
||||||
import { useStore } from 'useStore'
|
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
|
|
||||||
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
export const RefreshButton = ({ children }: React.PropsWithChildren) => {
|
||||||
const { auth } = useSettingsAuthContext()
|
const { auth } = useSettingsAuthContext()
|
||||||
const token = auth?.context?.token
|
const token = auth?.context?.token
|
||||||
const { htmlRef } = useStore((s) => ({
|
const coreDumpManager = useMemo(
|
||||||
htmlRef: s.htmlRef,
|
() => new CoreDumpManager(engineCommandManager, token),
|
||||||
}))
|
[]
|
||||||
const coreDumpManager = new CoreDumpManager(
|
|
||||||
engineCommandManager,
|
|
||||||
htmlRef,
|
|
||||||
token
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
|