${this.data.map(({ value, tab, icon, getContent }, index) => {
- const isCurrent = (value ?? index) === this.value;
+ const isCurrent: boolean = (value ?? index) === this.value;
if (isCurrent) currentContent = getContent?.() || '';
return html`
this.#onOpen();
+ showPicker() {
+ this.#onOpen();
+ }
}
diff --git a/packages/gem-port/.gitignore b/packages/gem-port/.gitignore
new file mode 100644
index 00000000..65776c32
--- /dev/null
+++ b/packages/gem-port/.gitignore
@@ -0,0 +1 @@
+/bin/
\ No newline at end of file
diff --git a/packages/gem-port/package.json b/packages/gem-port/package.json
new file mode 100644
index 00000000..9a4b3202
--- /dev/null
+++ b/packages/gem-port/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "gem-port",
+ "version": "0.0.1",
+ "description": "Export React component",
+ "keywords": [
+ "gem",
+ "react",
+ "generator"
+ ],
+ "bin": {
+ "gem-port": "bin/index.js"
+ },
+ "files": [
+ "/bin/"
+ ],
+ "scripts": {
+ "build": "esbuild ./src/index.ts --outdir=./bin --bundle --platform=node --minify --sourcemap --external:typescript",
+ "start": "yarn build --watch",
+ "prepublishOnly": "yarn build"
+ },
+ "dependencies": {
+ "@gemjs/config": "^1.6.11",
+ "commander": "^7.2.0",
+ "gem-analyzer": "^1.7.0",
+ "ts-morph": "^13.0.0",
+ "typescript": "^4.5.0"
+ },
+ "devDependencies": {
+ },
+ "author": "mantou132",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/mantou132/gem.git",
+ "directory": "packages/gem-port"
+ },
+ "bugs": {
+ "url": "https://github.com/mantou132/gem/issues"
+ },
+ "homepage": "https://github.com/mantou132/gem#readme"
+}
diff --git a/packages/gem-port/src/index.ts b/packages/gem-port/src/index.ts
new file mode 100644
index 00000000..5b4e6302
--- /dev/null
+++ b/packages/gem-port/src/index.ts
@@ -0,0 +1,125 @@
+#!/usr/bin/env node
+
+import path from 'path';
+import { readdirSync, readFileSync, statSync } from 'fs';
+
+import { getElements } from 'gem-analyzer';
+import { Project } from 'ts-morph';
+import * as ts from 'typescript';
+import program from 'commander';
+
+import { name, description, version } from '../package.json';
+
+const cliOptions = {
+ outDir: './',
+};
+
+function createReactSourceFile(elementFilePath: string, outDir: string) {
+ const content = readFileSync(elementFilePath, { encoding: 'utf-8' });
+ const project = new Project({ useInMemoryFileSystem: true });
+ const file = project.createSourceFile(elementFilePath, content);
+ const basename = path.basename(elementFilePath, path.extname(elementFilePath));
+ // FIXME
+ const relativePath = path.relative(path.resolve(outDir), path.dirname(elementFilePath)).replace('src/', '');
+ return Object.fromEntries(
+ getElements(file).map(({ name: tag, constructorName, properties, methods, events }) => {
+ const componentName = constructorName.replace('Element', '');
+ const componentPropsName = `${componentName}Props`;
+ const componentMethodsName = `${componentName}Methods`;
+ return [
+ componentName + '.tsx',
+ `
+ import React, { ForwardRefExoticComponent, HTMLAttributes, RefAttributes, forwardRef, useImperativeHandle, useRef } from 'react';
+ import { TemplateResult } from '@mantou/gem/lib/element';
+ import { ${constructorName} } from '${relativePath}/${basename}';
+ export { ${constructorName} };
+
+ export type ${componentPropsName} = HTMLAttributes
& RefAttributes<${constructorName}> & {
+ ${properties
+ .map(({ name, attribute, reactive }) =>
+ !reactive ? '' : [name, attribute ? 'string' : 'any'].join('?:'),
+ )
+ .join(';')}
+ ${events.map((event) => [`on${event}`, `(arg: CustomEvent) => any`].join('?:')).join(';')}
+ };
+
+ export type ${componentMethodsName} = {
+ ${methods.map(({ name }) => [name, `typeof ${constructorName}.prototype.${name}`].join(': ')).join(';')}
+ }
+
+ declare global {
+ namespace JSX {
+ interface IntrinsicElements {
+ '${tag}': ${componentPropsName};
+ }
+ }
+ }
+
+ const ${componentName}: ForwardRefExoticComponent & RefAttributes<${componentMethodsName}>> = forwardRef<${componentMethodsName}, ${componentPropsName}>(function (props, ref): JSX.Element {
+ const elementRef = useRef<${constructorName}>(null);
+ useImperativeHandle(ref, () => {
+ return {
+ ${methods
+ .map(
+ ({ name }) => `
+ ${name}(...args) {
+ elementRef.current?.${name}(...args)
+ }
+ `,
+ )
+ .join(',')}
+ };
+ }, []);
+ return <${tag} ref={elementRef} {...props}>${tag}>;
+ })
+
+ export default ${componentName};
+ `,
+ ];
+ }),
+ );
+}
+
+function createSourceFiles(elementsDir: string, outDir: string) {
+ const fileSystem: Record = {};
+ readdirSync(elementsDir).forEach((filename) => {
+ const elementFilePath = path.resolve(elementsDir, filename);
+ if (statSync(elementFilePath).isFile()) {
+ // if (!elementFilePath.includes('color-pick') && !elementFilePath.includes('card')) return;
+ Object.assign(fileSystem, createReactSourceFile(elementFilePath, outDir));
+ }
+ });
+ return fileSystem;
+}
+
+function compile(elementsDir: string): void {
+ const outDir = path.resolve(cliOptions.outDir, 'react');
+ const options: ts.CompilerOptions = {
+ jsx: ts.JsxEmit.React,
+ target: ts.ScriptTarget.ES2020,
+ declaration: true,
+ outDir,
+ };
+ const fileSystem = createSourceFiles(elementsDir, outDir);
+ const host = ts.createCompilerHost(options);
+ const originReadFile = host.readFile;
+ host.readFile = (filename: string) => {
+ if (filename in fileSystem) return fileSystem[filename];
+ return originReadFile(filename);
+ };
+ const program = ts.createProgram(Object.keys(fileSystem), options, host);
+ program.emit();
+}
+
+program
+ .name(name)
+ .description(description)
+ .version(version, '-v, --version')
+ .option('-o, --outdir ', `specify out dir`, (outdir: string) => (cliOptions.outDir = outdir), cliOptions.outDir)
+ .arguments('')
+ .action((dir: string) => {
+ compile(dir);
+ process.exit(0);
+ });
+
+program.parse(process.argv).outputHelp();
diff --git a/packages/gem-port/tsconfig.json b/packages/gem-port/tsconfig.json
new file mode 100644
index 00000000..12e6e5d3
--- /dev/null
+++ b/packages/gem-port/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "@gemjs/config/tsconfig",
+ "compilerOptions": {
+ "module": "commonjs"
+ },
+ "include": ["src"],
+ "exclude": []
+}
diff --git a/packages/gem/src/lib/utils.ts b/packages/gem/src/lib/utils.ts
index 2bef5ab3..9a1369b6 100644
--- a/packages/gem/src/lib/utils.ts
+++ b/packages/gem/src/lib/utils.ts
@@ -245,7 +245,7 @@ export interface StyledKeyValuePair {
// https://bugzilla.mozilla.org/show_bug.cgi?id=1520690
// https://bugs.webkit.org/show_bug.cgi?id=228684
export let useNativeCSSStyleSheet = true;
-let CSSStyleSheet = window.CSSStyleSheet;
+let CSSStyleSheet = globalThis.CSSStyleSheet;
try {
new (CSSStyleSheet as any)();
} catch {