move 'env' from state to context
This commit is contained in:
parent
9ef160aeb7
commit
f09261df93
13 changed files with 178 additions and 148 deletions
|
|
@ -16,15 +16,15 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.26.0",
|
"@eslint/js": "^9.26.0",
|
||||||
"@types/react": "^19.1.3",
|
"@types/react": "^19.1.4",
|
||||||
"@types/react-dom": "^19.1.3",
|
"@types/react-dom": "^19.1.5",
|
||||||
"@vitejs/plugin-react-swc": "^3.9.0",
|
"@vitejs/plugin-react-swc": "^3.9.0",
|
||||||
"eslint": "^9.26.0",
|
"eslint": "^9.26.0",
|
||||||
"eslint-plugin-react-hooks": "^5.2.0",
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
"eslint-plugin-react-refresh": "^0.4.20",
|
"eslint-plugin-react-refresh": "^0.4.20",
|
||||||
"globals": "^16.1.0",
|
"globals": "^16.1.0",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.8.3",
|
||||||
"typescript-eslint": "^8.32.0",
|
"typescript-eslint": "^8.32.1",
|
||||||
"vite": "^6.3.5"
|
"vite": "^6.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
156
pnpm-lock.yaml
generated
156
pnpm-lock.yaml
generated
|
|
@ -10,7 +10,7 @@ importers:
|
||||||
dependencies:
|
dependencies:
|
||||||
dope2:
|
dope2:
|
||||||
specifier: git+https://deemz.org/git/joeri/dope2.git
|
specifier: git+https://deemz.org/git/joeri/dope2.git
|
||||||
version: git+https://deemz.org/git/joeri/dope2.git#a9e21d7d94a7c75c34a95116931b458507131694
|
version: git+https://deemz.org/git/joeri/dope2.git#e631f11aa52b2adda8809c1b0b41cc991fbe8890
|
||||||
react:
|
react:
|
||||||
specifier: ^19.1.0
|
specifier: ^19.1.0
|
||||||
version: 19.1.0
|
version: 19.1.0
|
||||||
|
|
@ -22,11 +22,11 @@ importers:
|
||||||
specifier: ^9.26.0
|
specifier: ^9.26.0
|
||||||
version: 9.26.0
|
version: 9.26.0
|
||||||
'@types/react':
|
'@types/react':
|
||||||
specifier: ^19.1.3
|
specifier: ^19.1.4
|
||||||
version: 19.1.3
|
version: 19.1.4
|
||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^19.1.3
|
specifier: ^19.1.5
|
||||||
version: 19.1.3(@types/react@19.1.3)
|
version: 19.1.5(@types/react@19.1.4)
|
||||||
'@vitejs/plugin-react-swc':
|
'@vitejs/plugin-react-swc':
|
||||||
specifier: ^3.9.0
|
specifier: ^3.9.0
|
||||||
version: 3.9.0(vite@6.3.5)
|
version: 3.9.0(vite@6.3.5)
|
||||||
|
|
@ -46,8 +46,8 @@ importers:
|
||||||
specifier: ~5.8.3
|
specifier: ~5.8.3
|
||||||
version: 5.8.3
|
version: 5.8.3
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.32.0
|
specifier: ^8.32.1
|
||||||
version: 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
version: 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
vite:
|
vite:
|
||||||
specifier: ^6.3.5
|
specifier: ^6.3.5
|
||||||
version: 6.3.5
|
version: 6.3.5
|
||||||
|
|
@ -262,8 +262,8 @@ packages:
|
||||||
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
|
||||||
engines: {node: '>=18.18'}
|
engines: {node: '>=18.18'}
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.1':
|
'@modelcontextprotocol/sdk@1.11.2':
|
||||||
resolution: {integrity: sha512-9LfmxKTb1v+vUS1/emSk1f5ePmTLkb9Le9AxOB5T0XM59EUumwcS45z05h7aiZx3GI0Bl7mjb3FMEglYj+acuQ==}
|
resolution: {integrity: sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
|
|
@ -459,59 +459,59 @@ packages:
|
||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
|
||||||
'@types/react-dom@19.1.3':
|
'@types/react-dom@19.1.5':
|
||||||
resolution: {integrity: sha512-rJXC08OG0h3W6wDMFxQrZF00Kq6qQvw0djHRdzl3U5DnIERz0MRce3WVc7IS6JYBwtaP/DwYtRRjVlvivNveKg==}
|
resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^19.0.0
|
'@types/react': ^19.0.0
|
||||||
|
|
||||||
'@types/react@19.1.3':
|
'@types/react@19.1.4':
|
||||||
resolution: {integrity: sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==}
|
resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==}
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.32.0':
|
'@typescript-eslint/eslint-plugin@8.32.1':
|
||||||
resolution: {integrity: sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==}
|
resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
'@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.9.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.32.0':
|
'@typescript-eslint/parser@8.32.1':
|
||||||
resolution: {integrity: sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==}
|
resolution: {integrity: sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.9.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.32.0':
|
'@typescript-eslint/scope-manager@8.32.1':
|
||||||
resolution: {integrity: sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==}
|
resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.32.0':
|
'@typescript-eslint/type-utils@8.32.1':
|
||||||
resolution: {integrity: sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==}
|
resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.9.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/types@8.32.0':
|
'@typescript-eslint/types@8.32.1':
|
||||||
resolution: {integrity: sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==}
|
resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.32.0':
|
'@typescript-eslint/typescript-estree@8.32.1':
|
||||||
resolution: {integrity: sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==}
|
resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <5.9.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.32.0':
|
'@typescript-eslint/utils@8.32.1':
|
||||||
resolution: {integrity: sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==}
|
resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
typescript: '>=4.8.4 <5.9.0'
|
typescript: '>=4.8.4 <5.9.0'
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.32.0':
|
'@typescript-eslint/visitor-keys@8.32.1':
|
||||||
resolution: {integrity: sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==}
|
resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@vitejs/plugin-react-swc@3.9.0':
|
'@vitejs/plugin-react-swc@3.9.0':
|
||||||
|
|
@ -633,8 +633,8 @@ packages:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
dope2@git+https://deemz.org/git/joeri/dope2.git#a9e21d7d94a7c75c34a95116931b458507131694:
|
dope2@git+https://deemz.org/git/joeri/dope2.git#e631f11aa52b2adda8809c1b0b41cc991fbe8890:
|
||||||
resolution: {commit: a9e21d7d94a7c75c34a95116931b458507131694, repo: https://deemz.org/git/joeri/dope2.git, type: git}
|
resolution: {commit: e631f11aa52b2adda8809c1b0b41cc991fbe8890, repo: https://deemz.org/git/joeri/dope2.git, type: git}
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
|
|
||||||
dunder-proto@1.0.1:
|
dunder-proto@1.0.1:
|
||||||
|
|
@ -868,6 +868,10 @@ packages:
|
||||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
ignore@7.0.4:
|
||||||
|
resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
@ -1109,8 +1113,8 @@ packages:
|
||||||
scheduler@0.26.0:
|
scheduler@0.26.0:
|
||||||
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
|
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
|
||||||
|
|
||||||
semver@7.7.1:
|
semver@7.7.2:
|
||||||
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
|
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
|
@ -1191,8 +1195,8 @@ packages:
|
||||||
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
typescript-eslint@8.32.0:
|
typescript-eslint@8.32.1:
|
||||||
resolution: {integrity: sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==}
|
resolution: {integrity: sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0
|
eslint: ^8.57.0 || ^9.0.0
|
||||||
|
|
@ -1412,7 +1416,7 @@ snapshots:
|
||||||
|
|
||||||
'@humanwhocodes/retry@0.4.3': {}
|
'@humanwhocodes/retry@0.4.3': {}
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.11.1':
|
'@modelcontextprotocol/sdk@1.11.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
content-type: 1.0.5
|
content-type: 1.0.5
|
||||||
cors: 2.8.5
|
cors: 2.8.5
|
||||||
|
|
@ -1555,52 +1559,52 @@ snapshots:
|
||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
'@types/react-dom@19.1.3(@types/react@19.1.3)':
|
'@types/react-dom@19.1.5(@types/react@19.1.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.1.3
|
'@types/react': 19.1.4
|
||||||
|
|
||||||
'@types/react@19.1.3':
|
'@types/react@19.1.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
csstype: 3.1.3
|
csstype: 3.1.3
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)':
|
'@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.12.1
|
'@eslint-community/regexpp': 4.12.1
|
||||||
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/scope-manager': 8.32.0
|
'@typescript-eslint/scope-manager': 8.32.1
|
||||||
'@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/type-utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.32.0
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
eslint: 9.26.0
|
eslint: 9.26.0
|
||||||
graphemer: 1.4.0
|
graphemer: 1.4.0
|
||||||
ignore: 5.3.2
|
ignore: 7.0.4
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3)':
|
'@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.32.0
|
'@typescript-eslint/scope-manager': 8.32.1
|
||||||
'@typescript-eslint/types': 8.32.0
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
||||||
'@typescript-eslint/visitor-keys': 8.32.0
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
eslint: 9.26.0
|
eslint: 9.26.0
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.32.0':
|
'@typescript-eslint/scope-manager@8.32.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.32.0
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/visitor-keys': 8.32.0
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.32.0(eslint@9.26.0)(typescript@5.8.3)':
|
'@typescript-eslint/type-utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
||||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
eslint: 9.26.0
|
eslint: 9.26.0
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||||
|
|
@ -1608,36 +1612,36 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/types@8.32.0': {}
|
'@typescript-eslint/types@8.32.1': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.32.0(typescript@5.8.3)':
|
'@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.32.0
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/visitor-keys': 8.32.0
|
'@typescript-eslint/visitor-keys': 8.32.1
|
||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
fast-glob: 3.3.3
|
fast-glob: 3.3.3
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
minimatch: 9.0.5
|
minimatch: 9.0.5
|
||||||
semver: 7.7.1
|
semver: 7.7.2
|
||||||
ts-api-utils: 2.1.0(typescript@5.8.3)
|
ts-api-utils: 2.1.0(typescript@5.8.3)
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.32.0(eslint@9.26.0)(typescript@5.8.3)':
|
'@typescript-eslint/utils@8.32.1(eslint@9.26.0)(typescript@5.8.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0)
|
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0)
|
||||||
'@typescript-eslint/scope-manager': 8.32.0
|
'@typescript-eslint/scope-manager': 8.32.1
|
||||||
'@typescript-eslint/types': 8.32.0
|
'@typescript-eslint/types': 8.32.1
|
||||||
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3)
|
'@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
|
||||||
eslint: 9.26.0
|
eslint: 9.26.0
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.32.0':
|
'@typescript-eslint/visitor-keys@8.32.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.32.0
|
'@typescript-eslint/types': 8.32.1
|
||||||
eslint-visitor-keys: 4.2.0
|
eslint-visitor-keys: 4.2.0
|
||||||
|
|
||||||
'@vitejs/plugin-react-swc@3.9.0(vite@6.3.5)':
|
'@vitejs/plugin-react-swc@3.9.0(vite@6.3.5)':
|
||||||
|
|
@ -1758,7 +1762,7 @@ snapshots:
|
||||||
|
|
||||||
depd@2.0.0: {}
|
depd@2.0.0: {}
|
||||||
|
|
||||||
dope2@git+https://deemz.org/git/joeri/dope2.git#a9e21d7d94a7c75c34a95116931b458507131694:
|
dope2@git+https://deemz.org/git/joeri/dope2.git#e631f11aa52b2adda8809c1b0b41cc991fbe8890:
|
||||||
dependencies:
|
dependencies:
|
||||||
functional-red-black-tree: 1.0.1
|
functional-red-black-tree: 1.0.1
|
||||||
|
|
||||||
|
|
@ -1842,7 +1846,7 @@ snapshots:
|
||||||
'@humanfs/node': 0.16.6
|
'@humanfs/node': 0.16.6
|
||||||
'@humanwhocodes/module-importer': 1.0.1
|
'@humanwhocodes/module-importer': 1.0.1
|
||||||
'@humanwhocodes/retry': 0.4.3
|
'@humanwhocodes/retry': 0.4.3
|
||||||
'@modelcontextprotocol/sdk': 1.11.1
|
'@modelcontextprotocol/sdk': 1.11.2
|
||||||
'@types/estree': 1.0.7
|
'@types/estree': 1.0.7
|
||||||
'@types/json-schema': 7.0.15
|
'@types/json-schema': 7.0.15
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
|
|
@ -2053,6 +2057,8 @@ snapshots:
|
||||||
|
|
||||||
ignore@5.3.2: {}
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
|
ignore@7.0.4: {}
|
||||||
|
|
||||||
import-fresh@3.3.1:
|
import-fresh@3.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
parent-module: 1.0.1
|
parent-module: 1.0.1
|
||||||
|
|
@ -2272,7 +2278,7 @@ snapshots:
|
||||||
|
|
||||||
scheduler@0.26.0: {}
|
scheduler@0.26.0: {}
|
||||||
|
|
||||||
semver@7.7.1: {}
|
semver@7.7.2: {}
|
||||||
|
|
||||||
send@1.2.0:
|
send@1.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -2370,11 +2376,11 @@ snapshots:
|
||||||
media-typer: 1.1.0
|
media-typer: 1.1.0
|
||||||
mime-types: 3.0.1
|
mime-types: 3.0.1
|
||||||
|
|
||||||
typescript-eslint@8.32.0(eslint@9.26.0)(typescript@5.8.3):
|
typescript-eslint@8.32.1(eslint@9.26.0)(typescript@5.8.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/parser': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3)
|
'@typescript-eslint/utils': 8.32.1(eslint@9.26.0)(typescript@5.8.3)
|
||||||
eslint: 9.26.0
|
eslint: 9.26.0
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|
|
||||||
12
src/App.css
12
src/App.css
|
|
@ -42,3 +42,15 @@ footer {
|
||||||
footer a {
|
footer a {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.command {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0 6px 0 6px;
|
||||||
|
margin: 0 4px 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.command.highlighted {
|
||||||
|
background-color: dodgerblue;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import './App.css'
|
||||||
import { Editor, type EditorState } from './Editor'
|
import { Editor, type EditorState } from './Editor'
|
||||||
import { initialEditorState, nonEmptyEditorState, tripleFunctionCallEditorState } from "./configurations";
|
import { initialEditorState, nonEmptyEditorState, tripleFunctionCallEditorState } from "./configurations";
|
||||||
import { CommandContext } from './CommandContext';
|
import { CommandContext } from './CommandContext';
|
||||||
|
import { EnvContext } from './EnvContext';
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const [history, setHistory] = useState([initialEditorState]);
|
const [history, setHistory] = useState([initialEditorState]);
|
||||||
|
|
@ -52,7 +53,7 @@ export function App() {
|
||||||
const commands = [
|
const commands = [
|
||||||
["call" , "[c] call" ],
|
["call" , "[c] call" ],
|
||||||
["eval" , "[u] [Tab] [Enter] eval"],
|
["eval" , "[u] [Tab] [Enter] eval"],
|
||||||
["transform", "[t] transform" ],
|
["transform", "[t] [.] transform" ],
|
||||||
["let" , "[=] let ... in ..." ],
|
["let" , "[=] let ... in ..." ],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -80,15 +81,14 @@ export function App() {
|
||||||
}
|
}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main onKeyDown={onKeyDown}>
|
||||||
<CommandContext value={doHighlight}>
|
<CommandContext value={{undo: onUndo, redo: onRedo, doHighlight}}>
|
||||||
<Editor
|
<Editor
|
||||||
state={history.at(-1)!}
|
state={history.at(-1)!}
|
||||||
setState={pushHistory}
|
setState={pushHistory}
|
||||||
onResolve={() => {}}
|
onResolve={() => {}}
|
||||||
onCancel={() => {}}
|
onCancel={() => {}}
|
||||||
filter={() => true}
|
filter={() => true}
|
||||||
focus={true}
|
|
||||||
/>
|
/>
|
||||||
</CommandContext>
|
</CommandContext>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ export interface CallBlockState<
|
||||||
InputState=EditorState,
|
InputState=EditorState,
|
||||||
> {
|
> {
|
||||||
kind: "call";
|
kind: "call";
|
||||||
env: any;
|
|
||||||
fn: FnState;
|
fn: FnState;
|
||||||
input: InputState;
|
input: InputState;
|
||||||
resolved: undefined | Dynamic;
|
resolved: undefined | Dynamic;
|
||||||
|
|
@ -28,7 +27,7 @@ interface CallBlockProps<
|
||||||
}
|
}
|
||||||
|
|
||||||
function headlessCallBlock({state, setState, onResolve}: CallBlockProps) {
|
function headlessCallBlock({state, setState, onResolve}: CallBlockProps) {
|
||||||
const [unifyError, setUnifyError] = useState<UnifyError | undefined>(undefined);
|
const [unifyError, setUnifyError] = useState<typeof UnifyError | undefined>(undefined);
|
||||||
const {fn, input } = state;
|
const {fn, input } = state;
|
||||||
const setFn = (fn: EditorState) => {
|
const setFn = (fn: EditorState) => {
|
||||||
setState({...state, fn});
|
setState({...state, fn});
|
||||||
|
|
@ -52,7 +51,7 @@ function headlessCallBlock({state, setState, onResolve}: CallBlockProps) {
|
||||||
if (!(e instanceof UnifyError)) {
|
if (!(e instanceof UnifyError)) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
setUnifyError(e);
|
setUnifyError(e as typeof UnifyError);
|
||||||
onResolve({
|
onResolve({
|
||||||
...state, resolved: undefined
|
...state, resolved: undefined
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
|
|
||||||
export const CommandContext = createContext<{[key:string]: () => void}>({});
|
interface GlobalActions {
|
||||||
|
undo: () => void;
|
||||||
|
redo: () => void;
|
||||||
|
doHighlight: {[key:string]: () => void};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CommandContext = createContext<GlobalActions|null>(null);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.command {
|
.commandInput {
|
||||||
width: 160px;
|
width: 160px;
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ interface EditorProps extends State2Props<EditorState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCommands(type) {
|
function getCommands(type) {
|
||||||
const commands = ['u', 't', 'Enter', 'Backspace', 'ArrowLeft', 'ArrowRight', 'Tab', 'l', '='];
|
const commands = ['u', 't', 'Enter', 'Backspace', 'ArrowLeft', 'ArrowRight', 'Tab', 'l', '=', '.'];
|
||||||
if (getSymbol(type) === symbolFunction) {
|
if (getSymbol(type) === symbolFunction) {
|
||||||
commands.push('c');
|
commands.push('c');
|
||||||
}
|
}
|
||||||
|
|
@ -34,9 +34,9 @@ function getCommands(type) {
|
||||||
}
|
}
|
||||||
function getShortCommands(type) {
|
function getShortCommands(type) {
|
||||||
if (getSymbol(type) === symbolFunction) {
|
if (getSymbol(type) === symbolFunction) {
|
||||||
return 'c|Tab|t';
|
return 'c|Tab|.';
|
||||||
}
|
}
|
||||||
return 'Tab|t';
|
return 'Tab|.';
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeFocus(state: EditorState): EditorState {
|
function removeFocus(state: EditorState): EditorState {
|
||||||
|
|
@ -72,7 +72,7 @@ export function Editor({state, setState, onResolve, onCancel, filter}: EditorPro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const doHighlight = useContext(CommandContext);
|
const globalContext = useContext(CommandContext);
|
||||||
const onCommand = (e: React.KeyboardEvent) => {
|
const onCommand = (e: React.KeyboardEvent) => {
|
||||||
const type = getType(state.resolved);
|
const type = getType(state.resolved);
|
||||||
const commands = getCommands(type);
|
const commands = getCommands(type);
|
||||||
|
|
@ -84,7 +84,7 @@ export function Editor({state, setState, onResolve, onCancel, filter}: EditorPro
|
||||||
// u -> pass Up
|
// u -> pass Up
|
||||||
if (e.key === "u" || e.key === "Enter" || e.key === "Tab" && !e.shiftKey) {
|
if (e.key === "u" || e.key === "Enter" || e.key === "Tab" && !e.shiftKey) {
|
||||||
onResolve(state);
|
onResolve(state);
|
||||||
doHighlight.eval();
|
globalContext?.doHighlight.eval();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.key === "Tab" && e.shiftKey) {
|
if (e.key === "Tab" && e.shiftKey) {
|
||||||
|
|
@ -96,26 +96,24 @@ export function Editor({state, setState, onResolve, onCancel, filter}: EditorPro
|
||||||
// we become CallBlock
|
// we become CallBlock
|
||||||
setState({
|
setState({
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: state.env,
|
|
||||||
fn: removeFocus(state),
|
fn: removeFocus(state),
|
||||||
input: initialEditorState,
|
input: initialEditorState,
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
});
|
});
|
||||||
doHighlight.call();
|
globalContext?.doHighlight.call();
|
||||||
// focusNextElement();
|
// focusNextElement();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// t -> Transform
|
// t -> Transform
|
||||||
if (e.key === "t") {
|
if (e.key === "t" || e.key === ".") {
|
||||||
// we become CallBlock
|
// we become CallBlock
|
||||||
setState({
|
setState({
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: state.env,
|
|
||||||
fn: initialEditorState,
|
fn: initialEditorState,
|
||||||
input: removeFocus(state),
|
input: removeFocus(state),
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
});
|
});
|
||||||
doHighlight.transform();
|
globalContext?.doHighlight.transform();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.key === "Backspace" || e.key === "ArrowLeft") {
|
if (e.key === "Backspace" || e.key === "ArrowLeft") {
|
||||||
|
|
@ -132,13 +130,12 @@ export function Editor({state, setState, onResolve, onCancel, filter}: EditorPro
|
||||||
// we become LetInBlock
|
// we become LetInBlock
|
||||||
setState({
|
setState({
|
||||||
kind: "let",
|
kind: "let",
|
||||||
env: state.env,
|
inner: removeFocus(initialEditorState),
|
||||||
inner: initialEditorState,
|
|
||||||
name: "",
|
name: "",
|
||||||
value: state,
|
value: removeFocus(state),
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
});
|
});
|
||||||
doHighlight.let();
|
globalContext?.doHighlight.let();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -179,7 +176,7 @@ export function Editor({state, setState, onResolve, onCancel, filter}: EditorPro
|
||||||
? <input
|
? <input
|
||||||
ref={commandInputRef}
|
ref={commandInputRef}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
className="editable command"
|
className="editable commandInput"
|
||||||
placeholder={`<command: ${getShortCommands(getType(state.resolved))}>`}
|
placeholder={`<command: ${getShortCommands(getType(state.resolved))}>`}
|
||||||
onKeyDown={onCommand}
|
onKeyDown={onCommand}
|
||||||
value={""}
|
value={""}
|
||||||
|
|
|
||||||
9
src/EnvContext.ts
Normal file
9
src/EnvContext.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { createContext } from "react";
|
||||||
|
import { getDefaultTypeParser, module2Env, ModuleStd } from "dope2";
|
||||||
|
|
||||||
|
const mkType = getDefaultTypeParser();
|
||||||
|
export const extendedEnv = module2Env(ModuleStd.concat([
|
||||||
|
["functionWith3Params", { i: i => j => k => i + j + k, t: mkType("Int->Int->Int->Int") }],
|
||||||
|
]));
|
||||||
|
|
||||||
|
export const EnvContext = createContext(extendedEnv);
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import { Double, getType, Int, newDynamic, trie } from "dope2";
|
import { Double, getType, Int, newDynamic, trie } from "dope2";
|
||||||
import { focusNextElement, focusPrevElement, setRightMostCaretPosition } from "./util/dom_trickery";
|
import { autoInputWidth, focusNextElement, focusPrevElement, setRightMostCaretPosition } from "./util/dom_trickery";
|
||||||
import { parseDouble, parseInt } from "./util/parse";
|
import { parseDouble, parseInt } from "./util/parse";
|
||||||
|
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { Type } from "./Type";
|
import { Type } from "./Type";
|
||||||
|
|
||||||
import "./InputBlock.css";
|
import "./InputBlock.css";
|
||||||
import type { Dynamic, State2Props } from "./util/extra";
|
import type { Dynamic, State2Props } from "./util/extra";
|
||||||
|
import { EnvContext } from "./EnvContext";
|
||||||
|
|
||||||
export interface InputBlockState {
|
export interface InputBlockState {
|
||||||
kind: "input";
|
kind: "input";
|
||||||
env: any;
|
|
||||||
text: string;
|
text: string;
|
||||||
resolved: undefined | Dynamic;
|
resolved: undefined | Dynamic;
|
||||||
focus: boolean
|
focus: boolean
|
||||||
|
|
@ -39,7 +39,8 @@ const computeSuggestions = (text, env, filter) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function InputBlock({ state, setState, filter, onResolve, onCancel }: InputBlockProps) {
|
export function InputBlock({ state, setState, filter, onResolve, onCancel }: InputBlockProps) {
|
||||||
const {env, text, resolved, focus} = state;
|
const {text, resolved, focus} = state;
|
||||||
|
const env = useContext(EnvContext);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const [i, setI] = useState(0); // selected suggestion idx
|
const [i, setI] = useState(0); // selected suggestion idx
|
||||||
const [haveFocus, setHaveFocus] = useState(false); // whether to render suggestions or not
|
const [haveFocus, setHaveFocus] = useState(false); // whether to render suggestions or not
|
||||||
|
|
@ -51,12 +52,7 @@ export function InputBlock({ state, setState, filter, onResolve, onCancel }: Inp
|
||||||
const singleSuggestion = trie.growPrefix(env.name2dyn)(text);
|
const singleSuggestion = trie.growPrefix(env.name2dyn)(text);
|
||||||
const suggestions = useMemo(() => computeSuggestions(text, env, filter), [text]);
|
const suggestions = useMemo(() => computeSuggestions(text, env, filter), [text]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => autoInputWidth(inputRef, text), [inputRef, text]);
|
||||||
setI(0); // reset
|
|
||||||
if (inputRef.current) {
|
|
||||||
inputRef.current.style.width = `${text.length === 0 ? 140 : (text.length*8.7)}px`;
|
|
||||||
}
|
|
||||||
}, [text]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (focus) {
|
if (focus) {
|
||||||
|
|
@ -67,7 +63,6 @@ export function InputBlock({ state, setState, filter, onResolve, onCancel }: Inp
|
||||||
const onSelectSuggestion = ([name, dynamic]) => {
|
const onSelectSuggestion = ([name, dynamic]) => {
|
||||||
onResolve({
|
onResolve({
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env,
|
|
||||||
text: name,
|
text: name,
|
||||||
resolved: dynamic,
|
resolved: dynamic,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
@ -80,7 +75,6 @@ export function InputBlock({ state, setState, filter, onResolve, onCancel }: Inp
|
||||||
// un-resolve
|
// un-resolve
|
||||||
onResolve({
|
onResolve({
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env,
|
|
||||||
text: e.target.value,
|
text: e.target.value,
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
focus: true,
|
focus: true,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
|
import { useContext, useEffect, useRef } from "react";
|
||||||
import { Editor, type EditorState } from "./Editor";
|
import { Editor, type EditorState } from "./Editor";
|
||||||
|
import { EnvContext } from "./EnvContext";
|
||||||
import type { Dynamic, State2Props } from "./util/extra";
|
import type { Dynamic, State2Props } from "./util/extra";
|
||||||
|
import { growEnv } from "dope2";
|
||||||
|
import { autoInputWidth } from "./util/dom_trickery";
|
||||||
|
|
||||||
export interface LetInBlockState {
|
export interface LetInBlockState {
|
||||||
kind: "let";
|
kind: "let";
|
||||||
env: any;
|
|
||||||
name: string;
|
name: string;
|
||||||
value: EditorState;
|
value: EditorState;
|
||||||
inner: EditorState;
|
inner: EditorState;
|
||||||
|
|
@ -17,13 +19,26 @@ interface LetInBlockProps extends State2Props<LetInBlockState> {
|
||||||
|
|
||||||
|
|
||||||
export function LetInBlock({state, setState, onResolve}: LetInBlockProps) {
|
export function LetInBlock({state, setState, onResolve}: LetInBlockProps) {
|
||||||
const {env, name, value, inner, resolved} = state;
|
const {name, value, inner} = state;
|
||||||
|
const env = useContext(EnvContext);
|
||||||
|
const nameRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const onChangeName = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const onChangeName = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setState({...state, name: e.target.value});
|
setState({...state, name: e.target.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
nameRef.current?.focus();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => autoInputWidth(nameRef, name), [nameRef, name]);
|
||||||
|
|
||||||
|
const innerEnv = (name !== '') && value.resolved
|
||||||
|
&& growEnv(env)(name)(value.resolved) || env;
|
||||||
return <span className="letIn">
|
return <span className="letIn">
|
||||||
<div className="decl">
|
<div className="decl">
|
||||||
let <input
|
let <input
|
||||||
|
ref={nameRef}
|
||||||
className='editable'
|
className='editable'
|
||||||
value={name}
|
value={name}
|
||||||
placeholder="<variable name>"
|
placeholder="<variable name>"
|
||||||
|
|
@ -36,16 +51,18 @@ export function LetInBlock({state, setState, onResolve}: LetInBlockProps) {
|
||||||
onCancel={() => {} }
|
onCancel={() => {} }
|
||||||
setState={(state: EditorState) => {} }
|
setState={(state: EditorState) => {} }
|
||||||
/>
|
/>
|
||||||
in
|
in
|
||||||
</div>
|
</div>
|
||||||
<div className="inner">
|
<div className="inner">
|
||||||
|
<EnvContext value={innerEnv}>
|
||||||
<Editor
|
<Editor
|
||||||
state={inner}
|
state={inner}
|
||||||
|
setState={innerState => setState({...state, inner})}
|
||||||
filter={() => true}
|
filter={() => true}
|
||||||
onResolve={(state: EditorState) => {} }
|
onResolve={onResolve}
|
||||||
onCancel={() => {}}
|
onCancel={() => {}}
|
||||||
setState={(state: EditorState) => {} }
|
|
||||||
/>
|
/>
|
||||||
|
</EnvContext>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,30 @@
|
||||||
import { getDefaultTypeParser, module2Env, ModuleStd, trie, Int, apply } from "dope2";
|
import { apply, Int, trie } from "dope2";
|
||||||
import type { EditorState } from "./Editor";
|
import type { EditorState } from "./Editor";
|
||||||
|
import { extendedEnv } from "./EnvContext";
|
||||||
const mkType = getDefaultTypeParser();
|
|
||||||
export const extendedEnv = module2Env(ModuleStd.concat([
|
|
||||||
["functionWith3Params", { i: i => j => k => i + j + k, t: mkType("Int->Int->Int->Int") }],
|
|
||||||
]));
|
|
||||||
|
|
||||||
export const initialEditorState: EditorState = {
|
export const initialEditorState: EditorState = {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: extendedEnv,
|
|
||||||
text: "",
|
text: "",
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
focus: true,
|
focus: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const listPush = trie.get(initialEditorState.env.name2dyn)("list.push");
|
const listPush = trie.get(extendedEnv.name2dyn)("list.push");
|
||||||
const listEmptyList = trie.get(initialEditorState.env.name2dyn)("list.emptyList");
|
const listEmptyList = trie.get(extendedEnv.name2dyn)("list.emptyList");
|
||||||
const fourtyTwo = { i: 42n, t: Int };
|
const fourtyTwo = { i: 42n, t: Int };
|
||||||
|
|
||||||
export const nonEmptyEditorState: EditorState = {
|
export const nonEmptyEditorState: EditorState = {
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: initialEditorState.env,
|
|
||||||
fn: {
|
fn: {
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: initialEditorState.env,
|
|
||||||
fn: {
|
fn: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "list.push",
|
text: "list.push",
|
||||||
resolved: listPush,
|
resolved: listPush,
|
||||||
focus: false,
|
focus: false,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "list.emptyList",
|
text: "list.emptyList",
|
||||||
resolved: listEmptyList,
|
resolved: listEmptyList,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
@ -43,7 +34,6 @@ export const nonEmptyEditorState: EditorState = {
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "42",
|
text: "42",
|
||||||
resolved: fourtyTwo,
|
resolved: fourtyTwo,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
@ -52,29 +42,24 @@ export const nonEmptyEditorState: EditorState = {
|
||||||
resolved: undefined,
|
resolved: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const functionWith3Params = trie.get(initialEditorState.env.name2dyn)("functionWith3Params");
|
const functionWith3Params = trie.get(extendedEnv.name2dyn)("functionWith3Params");
|
||||||
const fourtyThree = { i: 43n, t: Int };
|
const fourtyThree = { i: 43n, t: Int };
|
||||||
const fourtyFour = { i: 44n, t: Int };
|
const fourtyFour = { i: 44n, t: Int };
|
||||||
|
|
||||||
export const tripleFunctionCallEditorState: EditorState = {
|
export const tripleFunctionCallEditorState: EditorState = {
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: initialEditorState.env,
|
|
||||||
fn: {
|
fn: {
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: initialEditorState.env,
|
|
||||||
fn: {
|
fn: {
|
||||||
kind: "call",
|
kind: "call",
|
||||||
env: initialEditorState.env,
|
|
||||||
fn: {
|
fn: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "functionWith3Params",
|
text: "functionWith3Params",
|
||||||
resolved: functionWith3Params,
|
resolved: functionWith3Params,
|
||||||
focus: false,
|
focus: false,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "42",
|
text: "42",
|
||||||
resolved: fourtyTwo,
|
resolved: fourtyTwo,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
@ -83,7 +68,6 @@ export const tripleFunctionCallEditorState: EditorState = {
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "43",
|
text: "43",
|
||||||
resolved: fourtyThree,
|
resolved: fourtyThree,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
@ -92,7 +76,6 @@ export const tripleFunctionCallEditorState: EditorState = {
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
kind: "input",
|
kind: "input",
|
||||||
env: initialEditorState.env,
|
|
||||||
text: "44",
|
text: "44",
|
||||||
resolved: fourtyFour,
|
resolved: fourtyFour,
|
||||||
focus: false,
|
focus: false,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import type { Ref } from "react";
|
||||||
|
|
||||||
// If there is a caret anywhere in the document (user entering text), returns the position of the caret in the focused element
|
// If there is a caret anywhere in the document (user entering text), returns the position of the caret in the focused element
|
||||||
export function getCaretPosition(): number | undefined {
|
export function getCaretPosition(): number | undefined {
|
||||||
|
|
@ -47,3 +48,9 @@ export function focusPrevElement() {
|
||||||
setRightMostCaretPosition(prevElem);
|
setRightMostCaretPosition(prevElem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const autoInputWidth = (inputRef: React.RefObject<HTMLInputElement| null>, text) => {
|
||||||
|
if (inputRef.current) {
|
||||||
|
inputRef.current.style.width = `${text.length === 0 ? 140 : (text.length*8.7)}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue