mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
feat: add TypeScript support
This commit is contained in:
@@ -30,13 +30,18 @@ tmux select-window -t penpot:1
|
|||||||
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
|
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
|
||||||
tmux send-keys -t penpot 'yarn run watch:app' enter
|
tmux send-keys -t penpot 'yarn run watch:app' enter
|
||||||
|
|
||||||
tmux new-window -t penpot:2 -n 'frontend storybook'
|
tmux new-window -t penpot:2 -n 'frontend ts'
|
||||||
tmux select-window -t penpot:2
|
tmux select-window -t penpot:2
|
||||||
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
|
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
|
||||||
|
tmux send-keys -t penpot 'yarn watch:ts' enter
|
||||||
|
|
||||||
|
tmux new-window -t penpot:3 -n 'frontend storybook'
|
||||||
|
tmux select-window -t penpot:3
|
||||||
|
tmux send-keys -t penpot 'cd penpot/frontend' enter C-l
|
||||||
tmux send-keys -t penpot 'yarn run watch:storybook' enter
|
tmux send-keys -t penpot 'yarn run watch:storybook' enter
|
||||||
|
|
||||||
tmux new-window -t penpot:3 -n 'exporter'
|
tmux new-window -t penpot:4 -n 'exporter'
|
||||||
tmux select-window -t penpot:3
|
tmux select-window -t penpot:4
|
||||||
tmux send-keys -t penpot 'cd penpot/exporter' enter C-l
|
tmux send-keys -t penpot 'cd penpot/exporter' enter C-l
|
||||||
tmux send-keys -t penpot 'rm -f target/app.js*' enter C-l
|
tmux send-keys -t penpot 'rm -f target/app.js*' enter C-l
|
||||||
tmux send-keys -t penpot 'yarn run watch' enter
|
tmux send-keys -t penpot 'yarn run watch' enter
|
||||||
@@ -45,8 +50,8 @@ tmux split-window -v
|
|||||||
tmux send-keys -t penpot 'cd penpot/exporter' enter C-l
|
tmux send-keys -t penpot 'cd penpot/exporter' enter C-l
|
||||||
tmux send-keys -t penpot './scripts/wait-and-start.sh' enter
|
tmux send-keys -t penpot './scripts/wait-and-start.sh' enter
|
||||||
|
|
||||||
tmux new-window -t penpot:4 -n 'backend'
|
tmux new-window -t penpot:5 -n 'backend'
|
||||||
tmux select-window -t penpot:4
|
tmux select-window -t penpot:5
|
||||||
tmux send-keys -t penpot 'cd penpot/backend' enter C-l
|
tmux send-keys -t penpot 'cd penpot/backend' enter C-l
|
||||||
tmux send-keys -t penpot './scripts/start-dev' enter
|
tmux send-keys -t penpot './scripts/start-dev' enter
|
||||||
|
|
||||||
|
|||||||
2
frontend/.gitignore
vendored
2
frontend/.gitignore
vendored
@@ -11,4 +11,4 @@ node_modules/
|
|||||||
/blob-report/
|
/blob-report/
|
||||||
/playwright/.cache/
|
/playwright/.cache/
|
||||||
/playwright/**/visual-specs/**/*.png
|
/playwright/**/visual-specs/**/*.png
|
||||||
|
/ts/dist/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
||||||
const config = {
|
const config = {
|
||||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)", "../ts/src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
|
||||||
staticDirs: ["../resources/public"],
|
staticDirs: ["../resources/public"],
|
||||||
addons: [
|
addons: [
|
||||||
"@storybook/addon-themes",
|
"@storybook/addon-themes",
|
||||||
|
|||||||
23
frontend/eslint.config.js
Normal file
23
frontend/eslint.config.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['ts/dist']),
|
||||||
|
{
|
||||||
|
files: ['ts/src/**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
reactHooks.configs['recommended-latest'],
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
@@ -17,7 +17,8 @@
|
|||||||
"@zip.js/zip.js@npm:^2.7.44": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
"@zip.js/zip.js@npm:^2.7.44": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
||||||
"@vitejs/plugin-react": "^4.2.0",
|
"@vitejs/plugin-react": "^4.2.0",
|
||||||
"playwright": "1.52.0",
|
"playwright": "1.52.0",
|
||||||
"playwright-core": "1.52.0"
|
"playwright-core": "1.52.0",
|
||||||
|
"globals": "^16.5.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:app:assets": "node ./scripts/build-app-assets.js",
|
"build:app:assets": "node ./scripts/build-app-assets.js",
|
||||||
@@ -32,8 +33,9 @@
|
|||||||
"e2e:server": "node ./scripts/e2e-server.js",
|
"e2e:server": "node ./scripts/e2e-server.js",
|
||||||
"fmt:clj": "cljfmt fix --parallel=true src/ test/",
|
"fmt:clj": "cljfmt fix --parallel=true src/ test/",
|
||||||
"fmt:clj:check": "cljfmt check --parallel=false src/ test/",
|
"fmt:clj:check": "cljfmt check --parallel=false src/ test/",
|
||||||
"fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -w",
|
"fmt:js": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -c ts/src/**/*.ts -w",
|
||||||
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js",
|
"fmt:js:check": "yarn run prettier -c src/**/*.stories.jsx -c playwright/**/*.js -c scripts/**/*.js -c ts/src/**/*.ts -c --check",
|
||||||
|
"lint:ts": "eslint ts/",
|
||||||
"lint:clj": "clj-kondo --parallel --lint src/",
|
"lint:clj": "clj-kondo --parallel --lint src/",
|
||||||
"lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
|
"lint:scss": "yarn run prettier -c resources/styles -c src/**/*.scss",
|
||||||
"lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
|
"lint:scss:fix": "yarn run prettier -c resources/styles -c src/**/*.scss -w",
|
||||||
@@ -50,6 +52,7 @@
|
|||||||
"watch:app": "yarn run clear:shadow-cache && concurrently \"yarn run watch:app:main\" \"yarn run watch:app:libs\"",
|
"watch:app": "yarn run clear:shadow-cache && concurrently \"yarn run watch:app:main\" \"yarn run watch:app:libs\"",
|
||||||
"watch": "yarn run watch:app:assets",
|
"watch": "yarn run watch:app:assets",
|
||||||
"watch:storybook": "yarn run build:storybook:assets && concurrently \"storybook dev -p 6006 --no-open\" \"yarn run watch:storybook:assets\"",
|
"watch:storybook": "yarn run build:storybook:assets && concurrently \"storybook dev -p 6006 --no-open\" \"yarn run watch:storybook:assets\"",
|
||||||
|
"watch:ts": "vite build --watch",
|
||||||
"watch:storybook:assets": "node ./scripts/watch-storybook.js"
|
"watch:storybook:assets": "node ./scripts/watch-storybook.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -59,11 +62,16 @@
|
|||||||
"@storybook/addon-vitest": "10.0.4",
|
"@storybook/addon-vitest": "10.0.4",
|
||||||
"@storybook/react-vite": "10.0.4",
|
"@storybook/react-vite": "10.0.4",
|
||||||
"@types/node": "^22.15.21",
|
"@types/node": "^22.15.21",
|
||||||
|
"@types/react": "^19.1.16",
|
||||||
|
"@types/react-dom": "^19.1.9",
|
||||||
"@vitest/browser": "3.2.4",
|
"@vitest/browser": "3.2.4",
|
||||||
"@vitest/coverage-v8": "3.2.4",
|
"@vitest/coverage-v8": "3.2.4",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.2.1",
|
||||||
"esbuild": "^0.25.9",
|
"esbuild": "^0.25.9",
|
||||||
|
"eslint": "^9.36.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.2.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.22",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"fancy-log": "^2.0.0",
|
"fancy-log": "^2.0.0",
|
||||||
"getopts": "^2.3.0",
|
"getopts": "^2.3.0",
|
||||||
@@ -95,6 +103,7 @@
|
|||||||
"storybook": "10.0.4",
|
"storybook": "10.0.4",
|
||||||
"svg-sprite": "^2.0.4",
|
"svg-sprite": "^2.0.4",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
|
"typescript-eslint": "^8.45.0",
|
||||||
"vite": "^6.3.5",
|
"vite": "^6.3.5",
|
||||||
"vitest": "^3.2.0",
|
"vitest": "^3.2.0",
|
||||||
"wasm-pack": "^0.13.1",
|
"wasm-pack": "^0.13.1",
|
||||||
@@ -108,7 +117,9 @@
|
|||||||
"@penpot/plugins-runtime": "1.3.2",
|
"@penpot/plugins-runtime": "1.3.2",
|
||||||
"@penpot/svgo": "penpot/svgo#v3.1",
|
"@penpot/svgo": "penpot/svgo#v3.1",
|
||||||
"@penpot/text-editor": "portal:./text-editor",
|
"@penpot/text-editor": "portal:./text-editor",
|
||||||
|
"@penpot/ts": "portal:./ts",
|
||||||
"@tokens-studio/sd-transforms": "1.2.11",
|
"@tokens-studio/sd-transforms": "1.2.11",
|
||||||
|
"@vitejs/plugin-react": "4.2.0",
|
||||||
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
||||||
"compression": "^1.8.1",
|
"compression": "^1.8.1",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<meta name="twitter:creator" content="@penpotapp">
|
<meta name="twitter:creator" content="@penpotapp">
|
||||||
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">
|
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)">
|
||||||
<link id="theme" href="css/main.css?version={{& version}}" rel="stylesheet" type="text/css" />
|
<link id="theme" href="css/main.css?version={{& version}}" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="css/ts-style.css?ts={{& ts}}" rel="stylesheet" type="text/css" />
|
||||||
{{#isDebug}}
|
{{#isDebug}}
|
||||||
<link href="css/debug.css?version={{& version}}" rel="stylesheet" type="text/css" />
|
<link href="css/debug.css?version={{& version}}" rel="stylesheet" type="text/css" />
|
||||||
{{/isDebug}}
|
{{/isDebug}}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
(ns app.main
|
(ns app.main
|
||||||
(:require
|
(:require
|
||||||
|
["@penpot/ts" :refer [setTranslation]]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.types.objects-map]
|
[app.common.types.objects-map]
|
||||||
@@ -38,6 +39,8 @@
|
|||||||
(log/setup! {:app :info})
|
(log/setup! {:app :info})
|
||||||
(log/set-level! :debug)
|
(log/set-level! :debug)
|
||||||
|
|
||||||
|
(setTranslation i18n/tr)
|
||||||
|
|
||||||
(when (= :browser cf/target)
|
(when (= :browser cf/target)
|
||||||
(log/inf :version (:full cf/version)
|
(log/inf :version (:full cf/version)
|
||||||
:asserts *assert*
|
:asserts *assert*
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
(ns app.main.ui.dashboard.projects
|
(ns app.main.ui.dashboard.projects
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
|
["@penpot/ts" :refer [TestTsxComponent]]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.time :as ct]
|
[app.common.time :as ct]
|
||||||
[app.main.data.common :as dcm]
|
[app.main.data.common :as dcm]
|
||||||
@@ -50,8 +51,11 @@
|
|||||||
::mf/props :obj
|
::mf/props :obj
|
||||||
::mf/private true}
|
::mf/private true}
|
||||||
[{:keys [can-edit]}]
|
[{:keys [can-edit]}]
|
||||||
|
;; (js/console.log "xxxx" TestTsxComponent)
|
||||||
(let [on-click (mf/use-fn #(st/emit! (dd/create-project)))]
|
(let [on-click (mf/use-fn #(st/emit! (dd/create-project)))]
|
||||||
[:header {:class (stl/css :dashboard-header) :data-testid "dashboard-header"}
|
[:header {:class (stl/css :dashboard-header) :data-testid "dashboard-header"}
|
||||||
|
[:div
|
||||||
|
[:> TestTsxComponent]]
|
||||||
[:div#dashboard-projects-title {:class (stl/css :dashboard-title)}
|
[:div#dashboard-projects-title {:class (stl/css :dashboard-title)}
|
||||||
[:h1 (tr "dashboard.projects-title")]]
|
[:h1 (tr "dashboard.projects-title")]]
|
||||||
(when can-edit
|
(when can-edit
|
||||||
|
|||||||
8
frontend/ts/package.json
Normal file
8
frontend/ts/package.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "@penpot/ts",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"type": "module",
|
||||||
|
"packageManager": "yarn@4.3.1"
|
||||||
|
}
|
||||||
3
frontend/ts/src/components/test-tsx.module.css
Normal file
3
frontend/ts/src/components/test-tsx.module.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.title {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
16
frontend/ts/src/components/test-tsx.stories.tsx
Normal file
16
frontend/ts/src/components/test-tsx.stories.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
import {TestTsxComponent } from "./test-tsx";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "TestTSX",
|
||||||
|
component: TestTsxComponent,
|
||||||
|
argTypes: {},
|
||||||
|
parameters: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {};
|
||||||
11
frontend/ts/src/components/test-tsx.tsx
Normal file
11
frontend/ts/src/components/test-tsx.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import styles from './test-tsx.module.css';
|
||||||
|
|
||||||
|
import { translate } from '../penpot-bridge';
|
||||||
|
|
||||||
|
export const TestTsxComponent = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2 className={styles.title}>{translate("labels.delete")} xx</h2>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
4
frontend/ts/src/index.tsx
Normal file
4
frontend/ts/src/index.tsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
export { TestTsxComponent } from "./components/test-tsx";
|
||||||
|
export { setTranslation } from "./penpot-bridge";
|
||||||
7
frontend/ts/src/penpot-bridge.ts
Normal file
7
frontend/ts/src/penpot-bridge.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export let translate = (key: string) => {
|
||||||
|
return key;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setTranslation(translations: (key: string) => string) {
|
||||||
|
translate = translations;
|
||||||
|
}
|
||||||
28
frontend/tsconfig.json
Normal file
28
frontend/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "ES2022",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"types": ["vite/client"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noUncheckedSideEffectImports": true
|
||||||
|
},
|
||||||
|
"include": ["ts/src"]
|
||||||
|
}
|
||||||
@@ -1,8 +1,25 @@
|
|||||||
/// <reference types="vitest/config" />
|
/// <reference types="vitest/config" />
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import { configDefaults } from "vitest/config";
|
import { configDefaults } from "vitest/config";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import { copyFileSync } from "fs";
|
||||||
|
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
|
||||||
|
const copyCssPlugin = () => ({
|
||||||
|
name: "copy-css",
|
||||||
|
closeBundle: () => {
|
||||||
|
try {
|
||||||
|
copyFileSync(
|
||||||
|
"./ts/dist/frontend.css",
|
||||||
|
"./resources/public/css/ts-style.css",
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error copying css file", e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
@@ -14,6 +31,7 @@ const dirname =
|
|||||||
|
|
||||||
// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon
|
// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
plugins: [react(), copyCssPlugin()],
|
||||||
test: {
|
test: {
|
||||||
exclude: [...configDefaults.exclude, "target/**", "resources/**"],
|
exclude: [...configDefaults.exclude, "target/**", "resources/**"],
|
||||||
environment: "jsdom",
|
environment: "jsdom",
|
||||||
@@ -50,4 +68,22 @@ export default defineConfig({
|
|||||||
"@public": resolve(__dirname, "./resources/public/js/"),
|
"@public": resolve(__dirname, "./resources/public/js/"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
build: {
|
||||||
|
outDir: './ts/dist/',
|
||||||
|
emptyOutDir: true,
|
||||||
|
lib: {
|
||||||
|
entry: './ts/src/index.tsx',
|
||||||
|
fileName: () => `index.js`,
|
||||||
|
formats: ['es'],
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['react', 'react-dom'],
|
||||||
|
output: {
|
||||||
|
globals: {
|
||||||
|
react: 'React',
|
||||||
|
"react-dom": "ReactDOM",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user