Initial commit

This commit is contained in:
Gordon 2021-03-24 01:15:25 +00:00
parent b29ece8904
commit fbe3dd7a7d
24 changed files with 49410 additions and 9796 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 4
max_line_length = 120
[{*.ts,*.tsx,*.js,*.json,*.yaml,*.md}]
indent_size = 2

2
.env
View File

@ -1 +1 @@
PUBLIC_URL=./
PUBLIC_URL=./

1
.gitignore vendored
View File

@ -10,6 +10,7 @@
/build
# misc
/resources
.DS_Store
.env.local
.env.development.local

34
.vscode/launch.json vendored
View File

@ -1,18 +1,20 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/ext-src"
}
]
}
"version": "0.2.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/out/src/**/*.js"
]
}
]
}

11
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,11 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
"typescript.tsc.autoDetect": "off" // Turn off tsc task auto detection since we have the necessary task as npm scripts
}

16
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,16 @@
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build",
"isBackground": false,
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 Peng Lyu
Copyright (c) 2021 Gordon Larrigan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,34 +1,5 @@
# VSCode Webview React
# VSCode kanbn extension
This project was bootstrapped with
* [Create React App](https://github.com/facebookincubator/create-react-app)
* [Create React App TypeScript](https://github.com/wmonk/create-react-app-typescript)
* [VSCode Extension Webview Sample](https://github.com/Microsoft/vscode-extension-samples/tree/master/webview-sample)
[The webview API](https://code.visualstudio.com/docs/extensions/webview) allows extensions to create customizable views within VSCode. Single Page Application frameworks are perfect fit for this use case. However, to make modern JavaScript frameworks/toolchains appeal to VSCode webview API's [security best practices](https://code.visualstudio.com/docs/extensions/webview#_security) requires some knowledge of both the bundling framework you are using and how VSCode secures webview. This project aims to provide an out-of-box starter kit for Create React App and TypeScript in VSCode's webview.
## Development
Run following commands in the terminal
```shell
yarn install
yarn run build
```
And then press F5, in Extension Development Host session, run `Start React Webview` command from command palette.
## Under the hood
Things we did on top of Create React App TypeScript template
* We inline `index.html` content in `ext-src/extension.ts` when creating the webview
* We set strict security policy for accessing resources in the webview.
* Only resources in `/build` can be accessed
* Onlu resources whose scheme is `vscode-resource` can be accessed.
* For all resources we are going to use in the webview, we change their schemes to `vscode-resource`
* Since we only allow local resources, absolute path for styles/images (e.g., `/static/media/logo.svg`) will not work. We add a `.env` file which sets `PUBLIC_URL` to `./` and after bundling, resource urls will be relative.
* We add baseUrl `<base href="${vscode.Uri.file(path.join(this._extensionPath, 'build')).with({ scheme: 'vscode-resource' })}/">` and then all relative paths work.
## Limitations
Right now you can only run production bits (`yarn run build`) in the webview, how to make dev bits work (webpack dev server) is still unknown yet. Suggestions and PRs welcome !
// TODO readme...
```

116
ext-src/ReactPanel.ts Normal file
View File

@ -0,0 +1,116 @@
import * as path from 'path';
import * as vscode from 'vscode';
export default class ReactPanel {
public static currentPanel: ReactPanel | undefined;
private static readonly viewType = 'react';
private readonly _panel: vscode.WebviewPanel;
private readonly _extensionPath: string;
private _disposables: vscode.Disposable[] = [];
public static createOrShow(extensionPath: string) {
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
// If we already have a panel, show it.
// Otherwise, create a new panel.
if (ReactPanel.currentPanel) {
ReactPanel.currentPanel._panel.reveal(column);
} else {
ReactPanel.currentPanel = new ReactPanel(extensionPath, column || vscode.ViewColumn.One);
}
}
private constructor(extensionPath: string, column: vscode.ViewColumn) {
this._extensionPath = extensionPath;
// Create and show a new webview panel
this._panel = vscode.window.createWebviewPanel(ReactPanel.viewType, "React", column, {
// Enable javascript in the webview
enableScripts: true,
// And restric the webview to only loading content from our extension's `media` directory.
localResourceRoots: [
vscode.Uri.file(path.join(this._extensionPath, 'build'))
]
});
// Set the webview's initial html content
this._panel.webview.html = this._getHtmlForWebview();
// Listen for when the panel is disposed
// This happens when the user closes the panel or when the panel is closed programatically
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
// Handle messages from the webview
this._panel.webview.onDidReceiveMessage(message => {
switch (message.command) {
case 'alert':
vscode.window.showErrorMessage(message.text);
return;
}
}, null, this._disposables);
}
public doRefactor() {
this._panel.webview.postMessage({ command: 'refactor' });
}
public dispose() {
ReactPanel.currentPanel = undefined;
// Clean up our resources
this._panel.dispose();
while (this._disposables.length) {
const x = this._disposables.pop();
if (x) {
x.dispose();
}
}
}
private _getHtmlForWebview() {
const manifest = require(path.join(this._extensionPath, 'build', 'asset-manifest.json'));
const mainScript = manifest['main.js'];
const mainStyle = manifest['main.css'];
const scriptPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'build', mainScript));
const scriptUri = scriptPathOnDisk.with({ scheme: 'vscode-resource' });
const stylePathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'build', mainStyle));
const styleUri = stylePathOnDisk.with({ scheme: 'vscode-resource' });
// Use a nonce to whitelist which scripts can be run
const nonce = getNonce();
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>React App</title>
<link rel="stylesheet" type="text/css" href="${styleUri}">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}';style-src vscode-resource: 'unsafe-inline' http: https: data:;">
<base href="${vscode.Uri.file(path.join(this._extensionPath, 'build')).with({ scheme: 'vscode-resource' })}/">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
}
function getNonce() {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}

View File

@ -1,131 +1,77 @@
import * as path from 'path';
import * as kanbn from '@basementuniverse/kanbn/src/main';
import * as vscode from 'vscode';
import ReactPanel from './ReactPanel';
let statusBarItem: vscode.StatusBarItem;
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('react-webview.start', () => {
ReactPanel.createOrShow(context.extensionPath);
}));
// Register a command to initialise kanbn in the current workspace. This command will be invoked when the status
// bar item is clicked in a workspace where kanbn isn't already initialised.
const initialiseCommandId = 'kanbn.init';
context.subscriptions.push(vscode.commands.registerCommand(initialiseCommandId, async () => {
// If no workspace folder is opened, we can't initialise kanbn
if (vscode.workspace.workspaceFolders === undefined) {
vscode.window.showErrorMessage('You need to open a workspace before initialising kanbn.');
return;
}
// Otherwise, check if kanbn is already initialised in the current workspace
console.log(kanbn.getMainFolder());
// Prints /home/gordon/.kanbn because presumably vscode runs extension code with process.cwd() as /home/<user>
// TODO update kanbn to inject root (see const ROOT in kanbn/src/main.js) into every method that needs it...
// if (vscode.workspace.workspaceFolders !== undefined) {
// const name = await vscode.window.showInputBox({
// value: '',
// placeHolder: 'The project name.',
// validateInput: text => {
// return text.length < 1 ? 'The project name cannot be empty.' : null;
// }
// });
// if (name !== undefined) {
// vscode.window.showInformationMessage(`creating with ${name}`);
// }
// }
// TODO initialise kanbn board
// updateStatusBarItem();
// console.log(kanbn);
// console.log(`kanbn initialised: ${await kanbn.initialised()}`);
}));
// Register a command to open the kanbn board. This command will be invoked when the status bar item is clicked
// in a workspace where kanbn has already been initialised.
const openBoardCommandId = 'kanbn.open';
context.subscriptions.push(vscode.commands.registerCommand(openBoardCommandId, () => {
ReactPanel.createOrShow(context.extensionPath);
}));
// If a workspace folder is open, add a status bar item and start watching for file changes
if (vscode.workspace.workspaceFolders !== undefined) {
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0);
statusBarItem.command = openBoardCommandId;
context.subscriptions.push(statusBarItem);
updateStatusBarItem();
const uri = vscode.workspace.workspaceFolders[0].uri.fsPath;
const fileWatcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(uri, '.kanbn/*'));
fileWatcher.onDidChange(e => {
// TODO update kanbn board
updateStatusBarItem();
console.log(e);
});
}
}
/**
* Manages react webview panels
*/
class ReactPanel {
/**
* Track the currently panel. Only allow a single panel to exist at a time.
*/
public static currentPanel: ReactPanel | undefined;
private static readonly viewType = 'react';
private readonly _panel: vscode.WebviewPanel;
private readonly _extensionPath: string;
private _disposables: vscode.Disposable[] = [];
public static createOrShow(extensionPath: string) {
const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;
// If we already have a panel, show it.
// Otherwise, create a new panel.
if (ReactPanel.currentPanel) {
ReactPanel.currentPanel._panel.reveal(column);
} else {
ReactPanel.currentPanel = new ReactPanel(extensionPath, column || vscode.ViewColumn.One);
}
}
private constructor(extensionPath: string, column: vscode.ViewColumn) {
this._extensionPath = extensionPath;
// Create and show a new webview panel
this._panel = vscode.window.createWebviewPanel(ReactPanel.viewType, "React", column, {
// Enable javascript in the webview
enableScripts: true,
// And restric the webview to only loading content from our extension's `media` directory.
localResourceRoots: [
vscode.Uri.file(path.join(this._extensionPath, 'build'))
]
});
// Set the webview's initial html content
this._panel.webview.html = this._getHtmlForWebview();
// Listen for when the panel is disposed
// This happens when the user closes the panel or when the panel is closed programatically
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
// Handle messages from the webview
this._panel.webview.onDidReceiveMessage(message => {
switch (message.command) {
case 'alert':
vscode.window.showErrorMessage(message.text);
return;
}
}, null, this._disposables);
}
public doRefactor() {
// Send a message to the webview webview.
// You can send any JSON serializable data.
this._panel.webview.postMessage({ command: 'refactor' });
}
public dispose() {
ReactPanel.currentPanel = undefined;
// Clean up our resources
this._panel.dispose();
while (this._disposables.length) {
const x = this._disposables.pop();
if (x) {
x.dispose();
}
}
}
private _getHtmlForWebview() {
const manifest = require(path.join(this._extensionPath, 'build', 'asset-manifest.json'));
const mainScript = manifest['main.js'];
const mainStyle = manifest['main.css'];
const scriptPathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'build', mainScript));
const scriptUri = scriptPathOnDisk.with({ scheme: 'vscode-resource' });
const stylePathOnDisk = vscode.Uri.file(path.join(this._extensionPath, 'build', mainStyle));
const styleUri = stylePathOnDisk.with({ scheme: 'vscode-resource' });
// Use a nonce to whitelist which scripts can be run
const nonce = getNonce();
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>React App</title>
<link rel="stylesheet" type="text/css" href="${styleUri}">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}';style-src vscode-resource: 'unsafe-inline' http: https: data:;">
<base href="${vscode.Uri.file(path.join(this._extensionPath, 'build')).with({ scheme: 'vscode-resource' })}/">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
export function deactivate(): void {
//
}
function getNonce() {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
function updateStatusBarItem(): void {
if (statusBarItem === undefined) {
return;
}
statusBarItem.text = `$(project) Not initialised`;
statusBarItem.show();
}

39256
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,38 @@
{
"name": "vscode-webview-react",
"name": "vscode-kanbn",
"version": "0.1.0",
"engines": {
"vscode": "^1.23.0"
},
"publisher": "rebornix",
"publisher": "basementuniverse",
"activationEvents": [
"onCommand:react-webview.start"
"onStartupFinished",
"onCommand:kanbn.open"
],
"main": "./build/ext-src/extension.js",
"contributes": {
"commands": [
{
"command": "react-webview.start",
"title": "Start React Webview",
"category": "React"
"command": "kanbn.init",
"title": "Initialise kanbn",
"category": "Kanbn"
},
{
"command": "kanbn.open",
"title": "Open board",
"category": "Kanbn"
}
]
},
"dependencies": {
"@basementuniverse/kanbn": "file:~/Projects/kanbn",
"react": "^16.3.2",
"react-beautiful-dnd": "12.2.0",
"react-dom": "^16.3.2",
"terser": "3.16.0",
"terser": "3.14.1",
"uuid": "3.3.3",
"vscode": "^1.1.17"
},
"resolutions": {
"terser": "3.14.1"
},
"scripts": {
"vscode:prepublish": "./scripts/build-non-split.js && tsc -p tsconfig.extension.json",
"postinstall": "node ./node_modules/vscode/bin/install",
@ -42,7 +48,7 @@
"@types/react-dom": "^16.0.5",
"react-scripts": "^2.1.3",
"rewire": "^4.0.1",
"typescript": "^3.3.1"
"typescript": "^4.0.2"
},
"browserslist": [
">0.2%",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -1,15 +0,0 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

View File

@ -1,28 +0,0 @@
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}
.App-title {
font-size: 1.5em;
}
.App-intro {
font-size: large;
}
@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}

View File

@ -1,22 +1,149 @@
import * as React from 'react';
import './App.css';
import React, { useState } from "react";
import { DragDropContext, Draggable, Droppable } from "react-beautiful-dnd";
import uuid from "uuid/v4";
import logo from './logo.svg';
const itemsFromBackend = [
{ id: uuid(), content: "First task" },
{ id: uuid(), content: "Second task" },
{ id: uuid(), content: "Third task" },
{ id: uuid(), content: "Fourth task" },
{ id: uuid(), content: "Fifth task" }
];
class App extends React.Component {
public render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.tsx</code> and save to reload.
</p>
</div>
);
const columnsFromBackend = {
[uuid()]: {
name: "Requested",
items: itemsFromBackend
},
[uuid()]: {
name: "To do",
items: []
},
[uuid()]: {
name: "In Progress",
items: []
},
[uuid()]: {
name: "Done",
items: []
}
};
const onDragEnd = (result, columns, setColumns) => {
if (!result.destination) return;
const { source, destination } = result;
if (source.droppableId !== destination.droppableId) {
const sourceColumn = columns[source.droppableId];
const destColumn = columns[destination.droppableId];
const sourceItems = [...sourceColumn.items];
const destItems = [...destColumn.items];
const [removed] = sourceItems.splice(source.index, 1);
destItems.splice(destination.index, 0, removed);
setColumns({
...columns,
[source.droppableId]: {
...sourceColumn,
items: sourceItems
},
[destination.droppableId]: {
...destColumn,
items: destItems
}
});
} else {
const column = columns[source.droppableId];
const copiedItems = [...column.items];
const [removed] = copiedItems.splice(source.index, 1);
copiedItems.splice(destination.index, 0, removed);
setColumns({
...columns,
[source.droppableId]: {
...column,
items: copiedItems
}
});
}
};
function App() {
const [columns, setColumns] = useState(columnsFromBackend);
return (
<div style={{ display: "flex", justifyContent: "center", height: "100%" }}>
<DragDropContext
onDragEnd={result => onDragEnd(result, columns, setColumns)}
>
{Object.entries(columns).map(([columnId, column], index) => {
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center"
}}
key={columnId}
>
<h2>{column.name}</h2>
<div style={{ margin: 8 }}>
<Droppable droppableId={columnId} key={columnId}>
{(provided, snapshot) => {
return (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver
? "lightblue"
: "lightgrey",
padding: 4,
width: 250,
minHeight: 500
}}
>
{column.items.map((item, index) => {
return (
<Draggable
key={item.id}
draggableId={item.id}
index={index}
>
{(provided, snapshot) => {
return (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
userSelect: "none",
padding: 16,
margin: "0 0 8px 0",
minHeight: "50px",
backgroundColor: snapshot.isDragging
? "#263B4A"
: "#456C86",
color: "white",
...provided.draggableProps.style
}}
>
{item.content}
</div>
);
}}
</Draggable>
);
})}
{provided.placeholder}
</div>
);
}}
</Droppable>
</div>
</div>
);
})}
</DragDropContext>
</div>
);
}
export default App;

View File

@ -1,7 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

1
src/react-beautiful-dnd.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'react-beautiful-dnd';

1
src/uuid.v4.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'uuid/v4';

View File

@ -1,21 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "build",
"lib": [
"es6",
"dom"
],
"sourceMap": true,
"rootDir": ".",
"strict": true
},
"include": [
"ext-src"
],
"exclude": [
"node_modules",
".vscode-test"
]
}
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "build",
"lib": [
"es6",
"dom"
],
"sourceMap": true,
"rootDir": ".",
"strict": true
},
"include": [
"ext-src"
],
"exclude": [
"node_modules",
".vscode-test"
]
}

View File

@ -17,7 +17,8 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve"
"jsx": "preserve",
"noImplicitAny": false
},
"include": [
"src"

View File

@ -1,10 +1,14 @@
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"extends": [
"tslint:recommended",
"tslint-react",
"tslint-config-prettier"
],
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"ext-src/**/*.ts"
"node_modules/**/*.ts",
"ext-src/**/*.ts"
]
}
}

19196
yarn.lock

File diff suppressed because it is too large Load Diff