diff --git a/.babelrc b/.babelrc index 67ed1b73..ee9bbff2 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,10 @@ { - "presets": ["@babel/env", "@babel/react", "@babel/flow"], + "presets": ["@babel/typescript", "@babel/env", "@babel/react", "@babel/flow"], "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }], - "@babel/proposal-class-properties" + "@babel/proposal-class-properties", + "@babel/plugin-proposal-nullish-coalescing-operator", + "@babel/plugin-proposal-optional-chaining" + ] } diff --git a/README.md b/README.md index 8f483f87..6556ab8d 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ JS.Sketcher is a **parametric** 2D and 3D CAD modeler written in pure javascript [2D Sketcher](http://web-cad.org/sketcher.html#__sample2D__) +[Help Docs](./web/docs/index.md) + [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=WADW7V7CC32CY&lc=US&item_name=web%2dcad%2eorg¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) Current Status diff --git a/modules/doc/DocumentationWindow.tsx b/modules/doc/DocumentationWindow.tsx new file mode 100644 index 00000000..612f29ef --- /dev/null +++ b/modules/doc/DocumentationWindow.tsx @@ -0,0 +1,96 @@ +import React, {useEffect, useState} from 'react'; +import {stream} from "lstream"; +import Window from "ui/components/Window"; +import {useStream} from "ui/effects"; +import marked from 'marked'; + +export const DocumentationTopic$ = stream(); +export const DocumentationUIState$ = stream(); + +export interface DocumentationRequest { + topic: string; + x: number, + y: number +} + +export function DocumentationWindow() { + + const request: DocumentationRequest = useStream(DocumentationTopic$); + const [content, setContent] = useState(null); + useEffect(() => { + window.__CAD_APP.DocumentationTopic$ = DocumentationTopic$; + if (!request) { + setContent(null); + return; + } + + fetch(`/docs/${topic}.md`).then(res => res.text()).then(source => { + const tokens = marked.lexer(source); + fixLinks(tokens); + const html = marked.parser(tokens, { + baseUrl: 'docs/' + }); + setContent(html); + }).catch(e => { + console.error(); + setContent('No documentation for ' + topic + '.md'); + }); + + }, [request?.topic]); + + if (!request) { + return null; + } + + const {topic, x, y} = request; + + const stateJson = sessionStorage.getItem('DocumentationWindow'); + let uiState; + try { + uiState = JSON.parse(stateJson); + } catch (ignore) { + + } + + if (!uiState) { + uiState = { + width: 350, + height: 700 + } + } + + return DocumentationTopic$.next(null)} + onResize={el => DocumentationUIState$.next(el)}> +

+ + +} +DocumentationUIState$.throttle(3000).attach(el => { + const rect = el.getBoundingClientRect(); + sessionStorage.setItem('DocumentationWindow', JSON.stringify({ + width: rect.width, + height: rect.height, + })); +}); + + +function fixLinks(inputTokens: any[]) { + const stack = []; + inputTokens.forEach(t => stack.push(t)); + while (stack.length) { + const token = stack.pop(); + if (token.type === 'link' && token.href) { + //removing .md suffix + token.href = `javascript:__CAD_APP.DocumentationTopic$.next({topic: '${token.href.substring(0, token.href.length-3)}'});` + } + if (token.tokens) { + token.tokens.forEach(t => stack.push(t)); + } + } + + + +} \ No newline at end of file diff --git a/modules/ui/WindowSystem.jsx b/modules/ui/WindowSystem.jsx deleted file mode 100644 index fcb0d90f..00000000 --- a/modules/ui/WindowSystem.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import {NOOP} from "../gems/func"; - -//TODO: remove it -export default class WindowSystem extends React.Component { - - constructor() { - super(); - } - - componentDidMount() { - } - - componentWillUnMount() { - } - - render() { - return this.props.children; - } - - childContext = { - setWindowMoveHandler: NOOP - }; - - getChildContext() { - return this.childContext; - } - - static childContextTypes = { - setWindowMoveHandler: PropTypes.func - } - -} diff --git a/modules/ui/components/Window.jsx b/modules/ui/components/Window.jsx index b8972a2c..eca30643 100644 --- a/modules/ui/components/Window.jsx +++ b/modules/ui/components/Window.jsx @@ -1,10 +1,9 @@ import React from 'react'; import ls from './Window.less' -import Fa from "./Fa"; -import WindowSystem from '../WindowSystem'; import cx from 'classnames'; -import {NOOP} from "../../gems/func"; +import {NOOP} from '../../gems/func'; +import {FaTimes} from 'react-icons/fa'; export default class Window extends React.Component { @@ -12,15 +11,17 @@ export default class Window extends React.Component { resizeHelper = new ResizeHelper(); render() { + let {initWidth, initHeight, initLeft, initTop, initRight, initBottom, setFocus, className, - resizeCapturingBuffer, resize, - children, title, icon, minimizable, onClose, ...props} = this.props; - return

+ resizeCapturingBuffer, resize, enableResize, children, title, icon, minimizable, onClose, controlButtons, ...props} = this.props; + + return
{icon}{title.toUpperCase()}
- {minimizable && _} - + {controlButtons} + {minimizable && _} +
@@ -86,6 +87,7 @@ export default class Window extends React.Component { this.el.style.left = this.originLocation.left + dx + 'px'; this.el.style.top = this.originLocation.top + dy + 'px'; + e.preventDefault(); } }; @@ -97,7 +99,8 @@ export default class Window extends React.Component { if (el === null) { return; } - let {initWidth, initHeight, initLeft, initTop, initRight, initBottom, resize, resizeCapturingBuffer, onResize, ...props} = this.props; + let {initWidth, initHeight, initLeft, initTop, initRight, initBottom, resizeCapturingBuffer, onResize, ...props} = this.props; + if (initWidth) { el.style.width = initWidth + 'px'; } @@ -114,10 +117,17 @@ export default class Window extends React.Component { } else if (initBottom) { el.style.top = (window.innerHeight - el.offsetHeight - initBottom) + 'px'; } - this.resizeHelper.registerResize(el, resize, resizeCapturingBuffer); + this.resizeHelper.registerResize(el, this.resizeConfig, resizeCapturingBuffer, onResize); this.el = el; + }; + + get resizeConfig() { + let {resize, enableResize} = this.props; + if (enableResize) { + resize= DIRECTIONS.NORTH | DIRECTIONS.SOUTH | DIRECTIONS.WEST | DIRECTIONS.EAST; + } + return resize; } - } Window.defaultProps = { @@ -168,8 +178,9 @@ export class ResizeHelper { el.style.top = top + 'px'; } if (onResize !== undefined) { - onResize(); + onResize(el); } + e.preventDefault(); }; if (this.controlGlobalListeners) { const moveListener = e => { @@ -270,3 +281,7 @@ export const DIRECTIONS = { function _maskTest(mask, value) { return (mask & value) === value; } + +export function WindowControlButton({danger, ...props}) { + return ; +} \ No newline at end of file diff --git a/modules/ui/components/Window.less b/modules/ui/components/Window.less index 8c20b2ff..671c19ab 100644 --- a/modules/ui/components/Window.less +++ b/modules/ui/components/Window.less @@ -11,9 +11,13 @@ min-height: 20px; } +.mandatoryBorder { + border: 5px solid #444444; +} + .bar { display: flex; - align-items: baseline; + align-items: center; justify-content: space-between; background-color: @bg-color; line-height: 1; @@ -25,6 +29,14 @@ .button { display: inline-block; padding: 6px 5px 6px 5px; + .button-behavior(@color-accent); + svg { + width: 12px; + height: 12px; + } +} + +.danger { .button-behavior(@color-danger); } diff --git a/modules/ui/effects.js b/modules/ui/effects.js index 30634c08..31c1791f 100644 --- a/modules/ui/effects.js +++ b/modules/ui/effects.js @@ -6,7 +6,7 @@ export function useStream(getStream) { const basicStreams = useContext(StreamsContext); const [state, setState] = useState(); - const stream = getStream(basicStreams); + const stream = typeof getStream === 'function' ? getStream(basicStreams) : getStream; if (!stream) { console.log(getStream); @@ -24,7 +24,7 @@ export function useStreamWithUpdater(getStream) { const data = useStream(getStream); const basicStreams = useContext(StreamsContext); - const stream = getStream(basicStreams); + const stream = typeof getStream === 'function' ? getStream(basicStreams) : getStream; const updater = useCallback((val) => { diff --git a/modules/ui/styles/init/documentation.less b/modules/ui/styles/init/documentation.less new file mode 100644 index 00000000..a8425a5d --- /dev/null +++ b/modules/ui/styles/init/documentation.less @@ -0,0 +1,5 @@ +.documentation-content { + background: #323444; + font-size: 13px; + padding: 10px; +} \ No newline at end of file diff --git a/modules/ui/styles/init/index.less b/modules/ui/styles/init/index.less index 6c476095..2c4297fa 100644 --- a/modules/ui/styles/init/index.less +++ b/modules/ui/styles/init/index.less @@ -8,3 +8,4 @@ @import "./svg.less"; @import "./icons.less"; @import "./scroll"; +@import "./documentation"; diff --git a/package-lock.json b/package-lock.json index a69b0257..9d4ea0af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -761,6 +761,15 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-syntax-typescript": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", + "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", @@ -1127,6 +1136,135 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-transform-typescript": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.9.6.tgz", + "integrity": "sha512-8OvsRdvpt3Iesf2qsAn+YdlwAJD7zJ+vhFZmDCa4b8dTp7MmHtKk5FF2mCsGxjZwuwsy/yIIay/nLmxST1ctVQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.9.6", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-typescript": "^7.8.3" + }, + "dependencies": { + "@babel/generator": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", + "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", + "dev": true, + "requires": { + "@babel/types": "^7.9.6", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.6.tgz", + "integrity": "sha512-6N9IeuyHvMBRyjNYOMJHrhwtu4WJMrYf8hVbEHD3pbbbmNOk1kmXSQs7bA4dYDUaIx4ZEzdnvo6NwC3WHd/Qow==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-replace-supers": "^7.9.6", + "@babel/helper-split-export-declaration": "^7.8.3" + } + }, + "@babel/helper-function-name": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", + "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.9.5" + } + }, + "@babel/helper-replace-supers": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz", + "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/parser": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", + "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", + "dev": true + }, + "@babel/traverse": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", + "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.6", + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", + "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.9.5", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@babel/plugin-transform-unicode-regex": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", @@ -1268,6 +1406,16 @@ "integrity": "sha512-dStnEQgejNYIHFNACdDCigK4BF7wgW6Zahv9Dc2un7rGjbeVtZhBfR3sy0I7ZJOhBexkFxVdMZ5hqmll7BFShw==", "dev": true }, + "@babel/preset-typescript": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz", + "integrity": "sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.9.0" + } + }, "@babel/runtime": { "version": "7.8.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", @@ -1527,6 +1675,31 @@ "integrity": "sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA==", "dev": true }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", + "dev": true + }, + "@types/react": { + "version": "16.9.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.34.tgz", + "integrity": "sha512-8AJlYMOfPe1KGLKyHpflCg5z46n0b5DbRfqDksxBLBTUpB75ypDBAO9eCUcjNwE6LCUslwTz00yyG/X9gaVtow==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "@types/react-dom": { + "version": "16.9.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.7.tgz", + "integrity": "sha512-GHTYhM8/OwUCf254WO5xqR/aqD3gC9kSTLpopWGpQLpnw23jk44RvMHsyUSEplvRJZdHxhJGMMLF0kCPYHPhQA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/sizzle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", @@ -3909,11 +4082,6 @@ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "dev": true }, - "diff-match-patch": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.0.tgz", - "integrity": "sha1-HMPIOkkNZ/ldkeOfatHy4Ia2MEg=" - }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -7638,6 +7806,11 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz", + "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -8646,6 +8819,12 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -11049,6 +11228,99 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "ts-loader": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.2.tgz", + "integrity": "sha512-DwpZFB67RoILQHx42dMjSgv2STpacsQu5X+GD/H9ocd8IhU0m8p3b/ZrIln2KmcucC6xep2PdEMEblpWT71euA==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -11122,6 +11394,76 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true + }, + "typescript-loader": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/typescript-loader/-/typescript-loader-1.1.3.tgz", + "integrity": "sha1-X/fmfLO6WSUZAUqswar2ZqcJ3gE=", + "dev": true, + "requires": { + "bluebird": "^2.7.1", + "loader-utils": "^0.2.6", + "object-assign": "^2.0.0", + "typescript": "^1.4.1" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "typescript": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz", + "integrity": "sha1-tHXW4N/wv1DyluXKbvn7tccyDx4=", + "dev": true + } + } + }, "ua-parser-js": { "version": "0.7.18", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.18.tgz", diff --git a/package.json b/package.json index 8b502228..4e8f744f 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,16 @@ "@babel/core": "^7.9.0", "@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", "@babel/preset-env": "^7.9.0", "@babel/preset-flow": "^7.9.0", "@babel/preset-react": "^7.9.1", "@babel/preset-stage-2": "^7.8.3", + "@babel/preset-typescript": "^7.9.0", "@cypress/webpack-preprocessor": "^4.1.3", + "@types/react": "^16.9.34", + "@types/react-dom": "^16.9.7", "babel-eslint": "^10.1.0", "babel-loader": "^8.1.0", "babel-plugin-transform-decorators-legacy": "^1.3.5", @@ -48,6 +53,9 @@ "less-loader": "^5.0.0", "raw-loader": "^4.0.0", "style-loader": "^1.1.3", + "ts-loader": "^7.0.2", + "typescript": "^3.8.3", + "typescript-loader": "^1.1.3", "webpack": "^4.42.1", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3" @@ -55,11 +63,11 @@ "dependencies": { "classnames": "2.2.5", "clipper-lib": "6.2.1", - "diff-match-patch": "1.0.0", "earcut": "2.1.1", "less": "^3.11.1", "libtess": "1.2.2", "lodash": "^4.17.15", + "marked": "^1.0.0", "mousetrap": "1.6.1", "numeric": "1.2.6", "prop-types": "15.6.0", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..8ff2e1e4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "lib": ["es2018", "dom"], + "sourceMap": true, + "jsx": "react", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "target": "ES5", + "baseUrl": ".", + "paths": { + "*": [ + "modules/*", + "node_modules/*" + ] + } + } +} diff --git a/web/app/cad/craft/wizard/components/Wizard.jsx b/web/app/cad/craft/wizard/components/Wizard.jsx index 12b2d550..7febdbca 100644 --- a/web/app/cad/craft/wizard/components/Wizard.jsx +++ b/web/app/cad/craft/wizard/components/Wizard.jsx @@ -1,5 +1,5 @@ import React from 'react'; -import Window from 'ui/components/Window'; +import Window, {WindowControlButton} from 'ui/components/Window'; import Stack from 'ui/components/Stack'; import Button from 'ui/components/controls/Button'; import ButtonGroup from 'ui/components/controls/ButtonGroup'; @@ -9,6 +9,8 @@ import CadError from '../../../../utils/errors'; import {FormContext} from './form/Form'; import connect from 'ui/connect'; import {combine} from 'lstream'; +import {DocumentationTopic$} from "../../../../../../modules/doc/DocumentationWindow"; +import {IoMdHelp} from "react-icons/io"; @connect((streams, props) => combine(props.context.workingRequest$, props.context.state$) .map(([workingRequest, state]) => ({ @@ -57,7 +59,16 @@ export default class Wizard extends React.Component { title={title} onClose={this.cancel} onKeyDown={this.onKeyDown} - setFocus={this.focusFirstInput}> + setFocus={this.focusFirstInput} + controlButtons={<> + DocumentationTopic$.next({ + topic: operation.id, + x: e.pageX + 40, + y: e.pageY + })}> + + + }>
diff --git a/web/app/cad/dom/components/UISystem.jsx b/web/app/cad/dom/components/UISystem.jsx index 505b4c12..ac259e5c 100644 --- a/web/app/cad/dom/components/UISystem.jsx +++ b/web/app/cad/dom/components/UISystem.jsx @@ -2,10 +2,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import MenuHolder from '../menu/MenuHolder'; -import WindowSystem from 'ui/WindowSystem'; import ActionInfo from '../actionInfo/ActionInfo'; import ContributedComponents from './ContributedComponents'; -import {stream} from '../../../../../modules/lstream'; +import {stream} from 'lstream'; +import {DocumentationWindow} from 'doc/DocumentationWindow'; +import {Scope} from "../../../sketcher/components/Scope"; +import {ContextualControls} from "../../../sketcher/components/ContextualControls"; +import {ConstraintEditor} from "../../../sketcher/components/ConstraintEditor"; +import SketcherOperationWizard from "../../../sketcher/components/SketcherOperationWizard"; +import {StageControl} from "../../../sketcher/components/StageControl"; export default class UISystem extends React.Component { @@ -15,10 +20,9 @@ export default class UISystem extends React.Component { return
- - {this.props.children} - - + {this.props.children} + +
} diff --git a/web/app/cad/dom/components/View3d.jsx b/web/app/cad/dom/components/View3d.jsx index 3153264a..a736b4ff 100644 --- a/web/app/cad/dom/components/View3d.jsx +++ b/web/app/cad/dom/components/View3d.jsx @@ -14,6 +14,10 @@ import SketcherMode from '../../sketch/components/SketcherMode'; import {ConstraintExplorer} from '../../../sketcher/components/ConstraintExplorer'; import {Scope} from "../../../sketcher/components/Scope"; import {InplaceSketcher} from "../../sketch/components/InplaceSketcher"; +import {ContextualControls} from "../../../sketcher/components/ContextualControls"; +import {ConstraintEditor} from "../../../sketcher/components/ConstraintEditor"; +import SketcherOperationWizard from "../../../sketcher/components/SketcherOperationWizard"; +import {StageControl} from "../../../sketcher/components/StageControl"; export default class View3d extends React.Component { @@ -40,6 +44,10 @@ export default class View3d extends React.Component {
+ + + +
diff --git a/web/app/sketcher/history.js b/web/app/sketcher/history.js index 3dcebaa4..9d5b878f 100644 --- a/web/app/sketcher/history.js +++ b/web/app/sketcher/history.js @@ -1,9 +1,8 @@ -import diff_match_patch from 'diff-match-patch'; /** @constructor */ function HistoryManager(viewer) { this.viewer = viewer; - this.dmp = new diff_match_patch(); + // this.dmp = new diff_match_patch(); this.init({}); // this.init(this.viewer.io.serializeSketch()); } @@ -80,9 +79,9 @@ HistoryManager.prototype.redo = function () { }; HistoryManager.prototype.applyDiff = function (text1, diff) { - var dmp = this.dmp; - var results = dmp.patch_apply(diff, text1); - return results[0]; + // var dmp = this.dmp; + // var results = dmp.patch_apply(diff, text1); + // return results[0]; }; HistoryManager.prototype.applyDiffInv = function (text1, diff) { @@ -103,17 +102,17 @@ HistoryManager.prototype.reversePatch = function (plist) { }; HistoryManager.prototype.getDiff = function (text1, text2) { - var dmp = this.dmp; - var diff = dmp.diff_main(text1, text2, true); - - if (diff.length > 2) { - dmp.diff_cleanupSemantic(diff); - } - - var patch_list = dmp.patch_make(text1, text2, diff); - //var patch_text = dmp.patch_toText(patch_list); - //console.log(patch_list); - return patch_list; + // var dmp = this.dmp; + // var diff = dmp.diff_main(text1, text2, true); + // + // if (diff.length > 2) { + // dmp.diff_cleanupSemantic(diff); + // } + // + // var patch_list = dmp.patch_make(text1, text2, diff); + // //var patch_text = dmp.patch_toText(patch_list); + // //console.log(patch_list); + // return patch_list; }; export {HistoryManager} \ No newline at end of file diff --git a/web/docs/BOOLEAN_OPPERATIONS.md b/web/docs/BOOLEAN_OPPERATIONS.md new file mode 100644 index 00000000..397a581d --- /dev/null +++ b/web/docs/BOOLEAN_OPPERATIONS.md @@ -0,0 +1,20 @@ +# ![](../img/cad/union32.png)![](../img/cad/subtract32.png)![](../img/cad/intersection32.png)BOOLEAN OPPERATIONS + +Boolean operations allow for solids to be used as tools to shape and modify other solids. + + +# ![](../img/cad/union32.png)UNION +Union allows solids to be combined to create a new solid. + +![](img/bool-UNION.gif) + +# ![](../img/cad/subtract32.png)SUBTRACT +Subtract allows one solid to be used as a cuttong tool for another sold. Usefull for making hole features. +Selection A will have selection B removed from it. + +![](img/bool-SUBTRACT.gif) + +# ![](../img/cad/intersection32.png)INTERSECTION +Intersection allows for the creation of a new solid in the space where 2 exising solids overlap. + +![](img/bool-INTERSECTION.gif) diff --git a/web/docs/BOX.md b/web/docs/BOX.md new file mode 100644 index 00000000..b28af9e2 --- /dev/null +++ b/web/docs/BOX.md @@ -0,0 +1,7 @@ +# ![](../img/cad/cube32.png)BOX +![](img/box-dialog.gif) + +The BOX command can be accesed by hovering over the center point of an existing datum and clicking. This brings up a menue with the BOX command as an option. + +Size of the box can be specified with the width, height and depth fields. +The boolean drop down allows for boolean operations with existing 3d solids. See [BOOLEAN_OPPERATIONS.md](BOOLEAN_OPPERATIONS.md "BOOLEAN_OPPERATIONS.md"). diff --git a/web/docs/CONE.md b/web/docs/CONE.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/CONE.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/CUT.md b/web/docs/CUT.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/CUT.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/CYLINDER.md b/web/docs/CYLINDER.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/CYLINDER.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/DATUM_CREATE.md b/web/docs/DATUM_CREATE.md new file mode 100644 index 00000000..c8a4d79a --- /dev/null +++ b/web/docs/DATUM_CREATE.md @@ -0,0 +1,13 @@ +# ![](../img/cad/datum32.png)Datum Create +![](img/create-datum.gif) + +While the CREATE DATUM dialog is open the datum can be dragged using the vector arrows. Optionally the values can be enter in the fields of the dialog. + +Datiums consist of a point and 3 vectors defining a relative location and orientation. The location and orientation can be moved after initial creation. See ![](../img/cad/datum-move32.png)[DATUM_MOVE.md](DATUM_MOVE.md "DATUM_MOVE.md") +![](../img/cad/datum-rotate32.png)[DATUM_ROTATE.md](DATUM_ROTATE.md "DATUM_ROTATE.md") + +The datium feature provides a point that can be used as the baisus for plane features or the origin point of a 3d primitive. + +The datium feature also provides 3 vectors. These vectors can be used for defining a direction of an extride/cut or the acces of a revolve feature. + + diff --git a/web/docs/DATUM_MOVE.md b/web/docs/DATUM_MOVE.md new file mode 100644 index 00000000..ee30faab --- /dev/null +++ b/web/docs/DATUM_MOVE.md @@ -0,0 +1,9 @@ +# ![](../img/cad/datum-move32.png)Datum Move +![](img/move-datum.gif) + + +The MOVE DATUM dialog can be accesed by hovering over the center point of an existing datum and clicking. This brings up a menue with the MOVE DATUM command as an option. + +While the MOVE DATUM dialog is open the datum can be dragged using the vector arrows. Optionally the values can be enter in the fields of the dialog. + +Optionally a new copy of the exisintg datum can be created rather than the translation of the original. diff --git a/web/docs/DATUM_ROTATE.md b/web/docs/DATUM_ROTATE.md new file mode 100644 index 00000000..0c343fe1 --- /dev/null +++ b/web/docs/DATUM_ROTATE.md @@ -0,0 +1,7 @@ +# ![](../img/cad/datum-rotate32.png)Datum Rotate +![](img/rotate-datum.gif) + + +The ROTATE DATUM dialog can be accesed by hovering over the center point of an existing datum and clicking. This brings up a menue with the ROTATE DATUM command as an option. + +While the ROTATE DATUM dialog is open the rotational axis can be selected. An angle then can be entered to change the orientation of datum. diff --git a/web/docs/EditFace.md b/web/docs/EditFace.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/EditFace.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/FILLET.md b/web/docs/FILLET.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/web/docs/FILLET.md @@ -0,0 +1 @@ + diff --git a/web/docs/HistoryTimeline.md b/web/docs/HistoryTimeline.md new file mode 100644 index 00000000..5c38d4a5 --- /dev/null +++ b/web/docs/HistoryTimeline.md @@ -0,0 +1 @@ +Place holder diff --git a/web/docs/INTERSECTION.md b/web/docs/INTERSECTION.md new file mode 100644 index 00000000..9e5a513e --- /dev/null +++ b/web/docs/INTERSECTION.md @@ -0,0 +1 @@ +See [BOOLEAN_OPPERATIONS.md](BOOLEAN_OPPERATIONS.md "BOOLEAN_OPPERATIONS.md"). diff --git a/web/docs/PLANE.md b/web/docs/PLANE.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/PLANE.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/REVOLVE.md b/web/docs/REVOLVE.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/REVOLVE.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/ReassignSketch.md b/web/docs/ReassignSketch.md new file mode 100644 index 00000000..5c38d4a5 --- /dev/null +++ b/web/docs/ReassignSketch.md @@ -0,0 +1 @@ +Place holder diff --git a/web/docs/SPHERE.md b/web/docs/SPHERE.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/SPHERE.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/SUBTRACT.md b/web/docs/SUBTRACT.md new file mode 100644 index 00000000..9e5a513e --- /dev/null +++ b/web/docs/SUBTRACT.md @@ -0,0 +1 @@ +See [BOOLEAN_OPPERATIONS.md](BOOLEAN_OPPERATIONS.md "BOOLEAN_OPPERATIONS.md"). diff --git a/web/docs/Save.md b/web/docs/Save.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/Save.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/StlExport.md b/web/docs/StlExport.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/StlExport.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/TORUS.md b/web/docs/TORUS.md new file mode 100644 index 00000000..55f985c9 --- /dev/null +++ b/web/docs/TORUS.md @@ -0,0 +1 @@ +place holder diff --git a/web/docs/UNION.md b/web/docs/UNION.md new file mode 100644 index 00000000..9e5a513e --- /dev/null +++ b/web/docs/UNION.md @@ -0,0 +1 @@ +See [BOOLEAN_OPPERATIONS.md](BOOLEAN_OPPERATIONS.md "BOOLEAN_OPPERATIONS.md"). diff --git a/web/docs/index.md b/web/docs/index.md new file mode 100644 index 00000000..bba9d269 --- /dev/null +++ b/web/docs/index.md @@ -0,0 +1,30 @@ +- ![](../img/cad/datum32.png)[DATUM_CREATE.md](DATUM_CREATE.md "DATUM_CREATE.md") +- ![](../img/cad/datum-move32.png)[DATUM_MOVE.md](DATUM_MOVE.md "DATUM_MOVE.md") +- ![](../img/cad/datum-rotate32.png)[DATUM_ROTATE.md](DATUM_ROTATE.md "DATUM_ROTATE.md") +- ![](../img/cad/plane32.png)[PLANE.md](PLANE.md "PLANE.md") +- ![](../img/cad/face-edit96.png)[EditFace.md](EditFace.md "EditFace.md") +- ![](../img/cad/revolve32.png)[REVOLVE.md](REVOLVE.md "REVOLVE.md") +- ![](../img/cad/cut32.png)[CUT.md](CUT.md "CUT.md") +- ![](../img/cad/fillet32.png)[FILLET.md](FILLET.md "FILLET.md") + + +- ![](../img/cad/xxxxxxxx.png)[ReassignSketch.md](ReassignSketch.md "ReassignSketch.md") + + + +- ![](../img/cad/cylinder32.png)[CYLINDER.md](CYLINDER.md "CYLINDER.md") +- ![](../img/cad/cone32.png)[CONE.md](CONE.md "CONE.md") +- ![](../img/cad/sphere32.png)[SPHERE.md](SPHERE.md "SPHERE.md") +- ![](../img/cad/torus32.png)[TORUS.md](TORUS.md "TORUS.md") + + + +- ![](../img/cad/union32.png)[UNION.md](UNION.md "UNION.md") +- ![](../img/cad/subtract32.png)[SUBTRACT.md](SUBTRACT.md "SUBTRACT.md") +- ![](../img/cad/intersection32.png)[INTERSECTION.md](INTERSECTION.md "INTERSECTION.md") + + +- ![](../img/cad/stl32.png)[StlExport.md](StlExport.md "StlExport.md") +- ![](../img/cad/cone32.png)[Save.md](Save.md "Save.md") + +- [index.md](index.md "index.md") diff --git a/webpack.config.js b/webpack.config.js index b6e4d2bb..d7c011a9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -29,7 +29,7 @@ module.exports = { new webpack.HotModuleReplacementPlugin(), ], resolve: { - extensions: ['.js', '.jsx'], + extensions: ['.js', '.jsx', ".ts", ".tsx"], modules: [MODULES, "node_modules"] }, devServer: { @@ -48,7 +48,7 @@ module.exports = { }, module: { rules: [{ - test: /\.(js|jsx)$/, + test: /\.(js|jsx|ts|tsx)$/, loader: 'babel-loader', include: [MODULES, WEB_APP, INTEGRATION_TESTS] }, {