@htmlplus/element 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +123 -25
  2. package/dist/client/decorators/bind.js +2 -1
  3. package/dist/client/decorators/element.js +113 -3
  4. package/dist/client/decorators/event.d.ts +19 -1
  5. package/dist/client/decorators/event.js +2 -2
  6. package/dist/client/decorators/index.js +0 -1
  7. package/dist/client/decorators/listen.d.ts +8 -1
  8. package/dist/client/decorators/method.js +2 -2
  9. package/dist/client/decorators/property.d.ts +11 -1
  10. package/dist/client/decorators/property.js +14 -5
  11. package/dist/client/decorators/state.js +8 -4
  12. package/dist/client/helpers/direction.d.ts +1 -1
  13. package/dist/client/helpers/slots.js +2 -1
  14. package/dist/client/services/link.js +3 -3
  15. package/dist/client/utils/api.d.ts +5 -1
  16. package/dist/client/utils/define-property.d.ts +1 -0
  17. package/dist/client/utils/define-property.js +1 -0
  18. package/dist/client/utils/host.js +1 -1
  19. package/dist/client/utils/index.d.ts +1 -1
  20. package/dist/client/utils/index.js +1 -1
  21. package/dist/compiler/compiler.js +3 -3
  22. package/dist/compiler/index.d.ts +1 -2
  23. package/dist/compiler/index.js +1 -2
  24. package/dist/compiler/plugins/attach.js +7 -10
  25. package/dist/compiler/plugins/docs.js +1 -0
  26. package/dist/compiler/plugins/extract.js +14 -2
  27. package/dist/compiler/plugins/index.d.ts +1 -0
  28. package/dist/compiler/plugins/index.js +1 -0
  29. package/dist/compiler/plugins/react.proxy/index.d.ts +1 -0
  30. package/dist/compiler/plugins/react.proxy/index.js +1 -0
  31. package/dist/compiler/plugins/react.proxy/react.proxy.d.ts +9 -0
  32. package/dist/compiler/plugins/react.proxy/react.proxy.js +60 -0
  33. package/dist/compiler/plugins/react.proxy/templates/README.md.hbs +1 -0
  34. package/dist/compiler/plugins/react.proxy/templates/_.gitignore.hbs +2 -0
  35. package/dist/compiler/plugins/react.proxy/templates/package.json.hbs +36 -0
  36. package/dist/compiler/plugins/react.proxy/templates/rollup.config.js.hbs +20 -0
  37. package/dist/compiler/plugins/react.proxy/templates/src/components/index.ts.hbs +3 -0
  38. package/dist/compiler/plugins/react.proxy/templates/src/components/{{fileName}}.ts.hbs +38 -0
  39. package/dist/compiler/plugins/react.proxy/templates/src/index.ts.hbs +1 -0
  40. package/dist/compiler/plugins/react.proxy/templates/src/proxy.ts.hbs +277 -0
  41. package/dist/compiler/plugins/react.proxy/templates/tsconfig.json.hbs +17 -0
  42. package/dist/compiler/utils/__dirname.d.ts +1 -0
  43. package/dist/compiler/utils/__dirname.js +5 -0
  44. package/dist/compiler/utils/index.d.ts +3 -0
  45. package/dist/compiler/utils/index.js +3 -0
  46. package/dist/compiler/utils/is-directory-empty.d.ts +1 -0
  47. package/dist/compiler/utils/is-directory-empty.js +19 -0
  48. package/dist/compiler/utils/render-template.d.ts +1 -0
  49. package/dist/compiler/utils/render-template.js +25 -0
  50. package/dist/types/context.d.ts +2 -0
  51. package/dist/types/index.d.ts +0 -5
  52. package/dist/types/index.js +0 -5
  53. package/dist/types/plugin.d.ts +4 -3
  54. package/package.json +10 -4
  55. package/dist/client/decorators/listen-options.d.ts +0 -2
  56. package/dist/client/decorators/listen-options.js +0 -2
  57. package/dist/types/api.d.ts +0 -5
  58. package/dist/types/api.js +0 -1
  59. package/dist/types/direction.d.ts +0 -1
  60. package/dist/types/direction.js +0 -1
  61. package/dist/types/event-options.d.ts +0 -18
  62. package/dist/types/event-options.js +0 -1
  63. package/dist/types/listen-options.d.ts +0 -7
  64. package/dist/types/listen-options.js +0 -1
  65. package/dist/types/property-options.d.ts +0 -10
  66. package/dist/types/property-options.js +0 -1
@@ -12,7 +12,7 @@ const log = (namespace, message) => {
12
12
  logUpdate(`${new Date().toLocaleTimeString()} [@htmlplus/element]${namespace ? `[${namespace}]` : ''} ${message}`);
13
13
  };
14
14
  export default (...plugins) => {
15
- const global = {
15
+ let global = {
16
16
  contexts: {}
17
17
  };
18
18
  const start = () => __awaiter(void 0, void 0, void 0, function* () {
@@ -20,7 +20,7 @@ export default (...plugins) => {
20
20
  for (const plugin of plugins) {
21
21
  if (!plugin.start)
22
22
  continue;
23
- yield plugin.start(global);
23
+ global = (yield plugin.start(global)) || global;
24
24
  log(plugin.name, 'Started successfully.');
25
25
  }
26
26
  });
@@ -43,7 +43,7 @@ export default (...plugins) => {
43
43
  for (const plugin of plugins) {
44
44
  if (!plugin.finish)
45
45
  continue;
46
- yield plugin.finish(global);
46
+ global = (yield plugin.finish(global)) || global;
47
47
  log(plugin.name, 'Finished successfully.');
48
48
  }
49
49
  log(undefined, 'Finished.');
@@ -1,3 +1,2 @@
1
- import compiler from './compiler.js';
1
+ export { default as default } from './compiler.js';
2
2
  export * from './plugins/index.js';
3
- export default compiler;
@@ -1,3 +1,2 @@
1
- import compiler from './compiler.js';
1
+ export { default as default } from './compiler.js';
2
2
  export * from './plugins/index.js';
3
- export default compiler;
@@ -1,5 +1,4 @@
1
1
  import t from '@babel/types';
2
- import { pascalCase } from 'change-case';
3
2
  import * as CONSTANTS from '../../configs/constants.js';
4
3
  import { visitor } from '../utils/index.js';
5
4
  const defaults = {
@@ -48,37 +47,35 @@ export const attach = (options) => {
48
47
  ]), undefined, undefined, undefined, true));
49
48
  }
50
49
  if (options.typings) {
51
- const className = pascalCase(context.componentTag.split('-').slice(1).join('-'));
52
- const elementName = `HTML${className}Element`;
53
50
  visitor(context.fileAST, {
54
51
  Program(path) {
55
52
  path.node.body.push(Object.assign(t.tsModuleDeclaration(t.identifier('global'), t.tsModuleBlock([
56
- t.tsInterfaceDeclaration(t.identifier(elementName), null, [], t.tsInterfaceBody([
53
+ t.tsInterfaceDeclaration(t.identifier(context.componentInterfaceName), null, [], t.tsInterfaceBody([
57
54
  ...context.classProperties.map((property) => Object.assign(t.tSPropertySignature(property.key, property.typeAnnotation), {
58
55
  optional: property.optional,
59
56
  leadingComments: property.leadingComments
60
57
  }))
61
58
  ])),
62
59
  t.variableDeclaration('var', [
63
- t.variableDeclarator(Object.assign(t.identifier(elementName), {
60
+ t.variableDeclarator(Object.assign(t.identifier(context.componentInterfaceName), {
64
61
  typeAnnotation: t.tSTypeAnnotation(t.tSTypeLiteral([
65
- t.tSPropertySignature(t.identifier('prototype'), t.tsTypeAnnotation(t.tSTypeReference(t.identifier(elementName)))),
66
- t.tSConstructSignatureDeclaration(null, [], t.tSTypeAnnotation(t.tSTypeReference(t.identifier(elementName))))
62
+ t.tSPropertySignature(t.identifier('prototype'), t.tsTypeAnnotation(t.tSTypeReference(t.identifier(context.componentInterfaceName)))),
63
+ t.tSConstructSignatureDeclaration(null, [], t.tSTypeAnnotation(t.tSTypeReference(t.identifier(context.componentInterfaceName))))
67
64
  ]))
68
65
  }))
69
66
  ]),
70
- t.tsInterfaceDeclaration(t.identifier(className), null, [], t.tsInterfaceBody([
67
+ t.tsInterfaceDeclaration(t.identifier(context.componentClassName), null, [], t.tsInterfaceBody([
71
68
  ...context.classProperties.map((property) => Object.assign(t.tSPropertySignature(property.key, property.typeAnnotation), {
72
69
  optional: property.optional,
73
70
  leadingComments: property.leadingComments
74
71
  }))
75
72
  ])),
76
73
  t.tsInterfaceDeclaration(t.identifier('HTMLElementTagNameMap'), null, [], t.tsInterfaceBody([
77
- t.tSPropertySignature(t.stringLiteral(context.componentTag), t.tSTypeAnnotation(t.tSIntersectionType([t.tSTypeReference(t.identifier(className))])))
74
+ t.tSPropertySignature(t.stringLiteral(context.componentTag), t.tSTypeAnnotation(t.tSIntersectionType([t.tSTypeReference(t.identifier(context.componentClassName))])))
78
75
  ])),
79
76
  t.exportNamedDeclaration(t.tSModuleDeclaration(t.identifier('JSX'), t.tsModuleBlock([
80
77
  t.tsInterfaceDeclaration(t.identifier('IntrinsicElements'), undefined, undefined, t.tsInterfaceBody([
81
- t.tsPropertySignature(t.stringLiteral(context.componentTag), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(className))))
78
+ t.tsPropertySignature(t.stringLiteral(context.componentTag), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(context.componentClassName))))
82
79
  ]))
83
80
  ])))
84
81
  ])), {
@@ -1,5 +1,6 @@
1
1
  import { capitalCase, paramCase } from 'change-case';
2
2
  import fs from 'fs';
3
+ // import glob from 'glob';
3
4
  import path from 'path';
4
5
  import { getInitializer, getTags, getType, printType } from '../utils/index.js';
5
6
  export const docs = (options) => {
@@ -1,5 +1,5 @@
1
1
  import * as t from '@babel/types';
2
- import { paramCase } from 'change-case';
2
+ import { pascalCase, paramCase } from 'change-case';
3
3
  import fs from 'fs';
4
4
  import path from 'path';
5
5
  import * as CONSTANTS from '../../configs/constants.js';
@@ -43,7 +43,19 @@ export const extract = (options) => {
43
43
  context.fileExtension = path.extname(context.filePath);
44
44
  context.fileName = path.basename(context.filePath, context.fileExtension);
45
45
  context.className = (_b = (_a = context.class) === null || _a === void 0 ? void 0 : _a.id) === null || _b === void 0 ? void 0 : _b.name;
46
- context.componentKey = paramCase(context.className);
46
+ // TODO
47
+ // context.componentKey = paramCase(context.className);
48
+ context.componentClassName = pascalCase(context.componentTag.split('-').slice(1).join('-'));
49
+ context.componentInterfaceName = `HTML${context.componentClassName}Element`;
50
+ // TODO
51
+ // const componentClassName = "DialogBody"; [OK]
52
+ // const componentInterfaceName = "HTMLDialogBodyElement"; [OK]
53
+ // const componentTag = "plus-dialog-body"; [OK]
54
+ // const componentClassNameInCategory = "Body"; [RAW]
55
+ // const componentKey = "dialog-body-1"; [RAW]
56
+ // const fileName = "dialogBodyNew"; [OK]
57
+ // const className = "DialogBody1"; [OK]
58
+ // const category = "Dialog"; [RAW]
47
59
  (() => {
48
60
  const stylePath = path.join(context.directoryPath, `${context.fileName}.scss`);
49
61
  if (!fs.existsSync(stylePath))
@@ -1,3 +1,4 @@
1
+ export * from './react.proxy/index.js';
1
2
  export * from './attach.js';
2
3
  export * from './docs.js';
3
4
  export * from './extract.js';
@@ -1,3 +1,4 @@
1
+ export * from './react.proxy/index.js';
1
2
  export * from './attach.js';
2
3
  export * from './docs.js';
3
4
  export * from './extract.js';
@@ -0,0 +1 @@
1
+ export * from './react.proxy.js';
@@ -0,0 +1 @@
1
+ export * from './react.proxy.js';
@@ -0,0 +1,9 @@
1
+ export interface ReactProxyOptions {
2
+ dist: string;
3
+ corePackageName: string;
4
+ categorize?: boolean;
5
+ }
6
+ export declare const reactProxy: (options: ReactProxyOptions) => {
7
+ name: string;
8
+ finish: (global: any) => Promise<void>;
9
+ };
@@ -0,0 +1,60 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { __dirname, isDirectoryEmpty, renderTemplate } from '../../utils/index.js';
11
+ export const reactProxy = (options) => {
12
+ const name = 'react-proxy';
13
+ const finish = (global) => __awaiter(void 0, void 0, void 0, function* () {
14
+ const config = { cwd: __dirname(import.meta.url) };
15
+ const component = 'templates/src/components/*fileName*';
16
+ global = Object.assign({}, global, { options });
17
+ const skip = [];
18
+ const getKey = (component) => component.componentClassName;
19
+ global.groups = Object.values(global.contexts)
20
+ .sort((a, b) => getKey(b).length - getKey(a).length)
21
+ .map((component, index, components) => ({
22
+ key: getKey(component),
23
+ components: components.filter((current) => getKey(current).startsWith(getKey(component)))
24
+ }))
25
+ .sort((a, b) => b.components.length - a.components.length)
26
+ .filter((group) => {
27
+ if (skip.includes(group.key))
28
+ return;
29
+ group.components.forEach((component) => skip.push(getKey(component)));
30
+ return true;
31
+ })
32
+ .map((group) => {
33
+ const root = group.components.find((component) => getKey(component) == group.key);
34
+ const all = group.components
35
+ .map((component) => (Object.assign(Object.assign({}, component), { componentClassNameInCategory: getKey(component).replace(group.key, '') })))
36
+ .reverse();
37
+ const filterd = all.filter((component) => getKey(component) != group.key);
38
+ return {
39
+ single: !filterd.length,
40
+ root,
41
+ all,
42
+ filterd
43
+ };
44
+ })
45
+ .sort((a, b) => (getKey(a.root) < getKey(b.root) ? -1 : 0));
46
+ if (yield isDirectoryEmpty(options.dist)) {
47
+ renderTemplate(['templates/**', `!${component}`], options.dist, config)(global);
48
+ }
49
+ else {
50
+ renderTemplate(['templates/src/proxy*', 'templates/src/components/index*'], options.dist, config)(global);
51
+ }
52
+ for (const group of global.groups) {
53
+ renderTemplate(component, options.dist, config)(Object.assign({ options, fileName: group.root.fileName }, group));
54
+ }
55
+ });
56
+ return {
57
+ name,
58
+ finish
59
+ };
60
+ };
@@ -0,0 +1 @@
1
+ # React output target for your custom element.
@@ -0,0 +1,2 @@
1
+ dist
2
+ node_modules
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "your-react-package-name",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "description": "React output target for your custom element.",
6
+ "exports": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "prebuild": "npm run clean",
10
+ "build": "rollup -c",
11
+ "clean": "rimraf dist"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "{{options.corePackageName}}": "latest",
18
+ "change-case": "^4.1.2"
19
+ },
20
+ "devDependencies": {
21
+ "@rollup/plugin-commonjs": "^15.0.0",
22
+ "@rollup/plugin-node-resolve": "^9.0.0",
23
+ "@types/react": "^16.9.49",
24
+ "react": "^17.0.1",
25
+ "react-dom": "^17.0.1",
26
+ "rimraf": "^3.0.2",
27
+ "rollup": "^2.27.1",
28
+ "rollup-plugin-peer-deps-external": "^2.2.3",
29
+ "rollup-plugin-typescript2": "^0.27.2",
30
+ "typescript": "^4.0.2"
31
+ },
32
+ "peerDependencies": {
33
+ "react": "^16.0.0 || ^17.0.0",
34
+ "react-dom": "^16.0.0 || ^17.0.0"
35
+ }
36
+ }
@@ -0,0 +1,20 @@
1
+ import commonjs from '@rollup/plugin-commonjs';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import peerDepsExternal from 'rollup-plugin-peer-deps-external';
4
+ import typescript from 'rollup-plugin-typescript2';
5
+
6
+ export default {
7
+ input: 'src/index.ts',
8
+ output: [
9
+ {
10
+ dir: 'dist/components',
11
+ format: 'esm'
12
+ }
13
+ ],
14
+ plugins: [
15
+ peerDepsExternal(),
16
+ resolve(),
17
+ commonjs(),
18
+ typescript()
19
+ ]
20
+ };
@@ -0,0 +1,3 @@
1
+ {{#each groups}}
2
+ export * from './{{root.fileName}}';
3
+ {{/each}}
@@ -0,0 +1,38 @@
1
+ /* eslint-disable */
2
+ /* tslint:disable */
3
+ /* auto-generated */
4
+
5
+ import { proxy } from '../proxy';
6
+ import type { JSX } from '{{options.corePackageName}}';
7
+
8
+ {{#each all}}
9
+ import {{componentClassName}} from '{{../options.corePackageName}}/{{fileName}}';
10
+ {{/each}}
11
+
12
+ {{#each all}}
13
+ const {{componentClassName}} = /*@__PURE__*/ proxy<{{componentInterfaceName}}, JSX.{{componentClassName}}>(
14
+ '{{componentTag}}',
15
+ [
16
+ {{#each classProperties}}
17
+ '{{key.name}}',
18
+ {{/each}}
19
+ ],
20
+ [
21
+ {{#each classEvents}}
22
+ '{{key.name}}',
23
+ {{/each}}
24
+ ],
25
+ );
26
+
27
+ {{/each}}
28
+ {{#if single}}
29
+ export { {{root.componentClassName}} }
30
+ {{else}}
31
+ const All = /*@__PURE__*/ Object.assign({{root.componentClassName}}, {
32
+ {{#each filterd}}
33
+ {{componentClassNameInCategory}}: {{componentClassName}},
34
+ {{/each}}
35
+ });
36
+
37
+ export { All as {{root.componentClassName}} }
38
+ {{/if}}
@@ -0,0 +1 @@
1
+ export * from './components';
@@ -0,0 +1,277 @@
1
+ /**
2
+ * version 0.0.9
3
+ */
4
+ import { camelCase, paramCase, pascalCase } from 'change-case';
5
+ import React from 'react';
6
+
7
+ type EventHandlerType = (event: Event) => any;
8
+
9
+ type FinalPropsType<ElementType> = Omit<PropsType<ElementType>, 'forwardedRef'>;
10
+
11
+ type Mutable<T> = { -readonly [P in keyof T]-?: T[P] };
12
+
13
+ interface ExtraType {
14
+ props?: Array<string>;
15
+ events?: Array<string>;
16
+ }
17
+
18
+ interface PropsType<ElementType> extends React.HTMLAttributes<ElementType> {
19
+ forwardedRef: React.RefObject<ElementType>;
20
+ ref?: React.Ref<any>;
21
+ }
22
+
23
+ export interface StyleReactProps {
24
+ class?: string;
25
+ className?: string;
26
+ style?: {
27
+ [key: string]: any;
28
+ };
29
+ }
30
+
31
+ const arrayToMap = (array: string[] | DOMTokenList) => {
32
+ const map = new Map<string, string>();
33
+
34
+ (array as string[]).forEach((s: string) => map.set(s, s));
35
+
36
+ return map;
37
+ };
38
+
39
+ const getCustomEvent = (name: string, events: Array<string>) => {
40
+ // TODO
41
+ name = camelCase(name.slice(3));
42
+
43
+ const event = events.find((event) => event.endsWith(name));
44
+
45
+ if (!event) return;
46
+
47
+ return event;
48
+ };
49
+
50
+ const forwardRef = <ElementType, PropType>(ReactComponent: any) => {
51
+ const forwardRef = (
52
+ props: PropType & Omit<React.HTMLAttributes<ElementType>, 'style'> & StyleReactProps,
53
+ ref: React.Ref<ElementType>
54
+ ) => {
55
+ const { children, ...remainedProps } = props;
56
+
57
+ const newProps = {
58
+ ...remainedProps,
59
+ forwardedRef: ref
60
+ };
61
+
62
+ return React.createElement(ReactComponent, newProps, children);
63
+ };
64
+
65
+ forwardRef.displayName = ReactComponent.displayName;
66
+
67
+ return React.forwardRef(forwardRef);
68
+ };
69
+
70
+ const isEvent = (name: string) => {
71
+ return name.indexOf('on') === 0 && name[2] === name[2].toUpperCase();
72
+ };
73
+
74
+ const isPrimitive = (value: any) => {
75
+ const type = typeof value;
76
+
77
+ const match = type.match(/boolean|string|number/);
78
+
79
+ return match;
80
+ };
81
+
82
+ const getProps = <ElementType>(ref: React.Ref<ElementType>, props: PropsType<ElementType>, extra: ExtraType) => {
83
+ const { forwardedRef } = props;
84
+
85
+ const result: FinalPropsType<ElementType> = {
86
+ ref: mergeRefs(forwardedRef, ref)
87
+ };
88
+
89
+ Object.keys(props).forEach((name) => {
90
+ if (name === 'children' || name === 'className' || name === 'forwardedRef' || name === 'ref') return;
91
+
92
+ const value = props[name];
93
+
94
+ if (isEvent(name)) {
95
+ if (typeof document === 'undefined') return;
96
+
97
+ const event = getCustomEvent(name, extra.events);
98
+
99
+ if (event) return;
100
+
101
+ result[name] = value;
102
+ } else if (extra.props.includes(name)) {
103
+ if (!isPrimitive(value)) return;
104
+
105
+ result[paramCase(name)] = value;
106
+ } else {
107
+ result[name] = value;
108
+ }
109
+ });
110
+
111
+ return result;
112
+ };
113
+
114
+ const mergeRefs =
115
+ <ElementType>(...refs: React.Ref<ElementType>[]) =>
116
+ (value: ElementType) => {
117
+ return refs.forEach((ref) => {
118
+ if (typeof ref === 'function') return ref(value);
119
+
120
+ if (ref == null) return;
121
+
122
+ (ref as Mutable<React.RefObject<ElementType>>).current = value;
123
+ });
124
+ };
125
+
126
+ const setClass = <ElementType>(element: ElementType, props: PropsType<ElementType>) => {
127
+ const classes: string[] = [];
128
+
129
+ const current = arrayToMap((element as any).classList);
130
+
131
+ const prev: string = element['$class'];
132
+ const next: string = props.className || (props as any).class;
133
+
134
+ const prevClass = arrayToMap(prev ? prev.split(' ') : []);
135
+ const nextClass = arrayToMap(next ? next.split(' ') : []);
136
+
137
+ current.forEach((key) => {
138
+ if (nextClass.has(key)) {
139
+ classes.push(key);
140
+
141
+ nextClass.delete(key);
142
+ } else if (!prevClass.has(key)) {
143
+ classes.push(key);
144
+ }
145
+ });
146
+
147
+ nextClass.forEach((key) => classes.push(key));
148
+
149
+ const className = classes.join(' ');
150
+
151
+ (element as any).className = className;
152
+
153
+ element['$class'] = className;
154
+ };
155
+
156
+ const setEvent = (element: Element, name: string, handler: EventHandlerType) => {
157
+ const events = element['$events'] || (element['$events'] = {});
158
+
159
+ const previous = events[name];
160
+
161
+ previous && element.removeEventListener(name, previous);
162
+
163
+ function callback(event: Event) {
164
+ handler && handler.call(this, event);
165
+ }
166
+
167
+ element.addEventListener(name, (events[name] = callback));
168
+ };
169
+
170
+ const setProps = <ElementType>(element: ElementType, props: PropsType<ElementType>, extra: ExtraType) => {
171
+ if (!(element instanceof Element)) return;
172
+
173
+ setClass<ElementType>(element, props);
174
+
175
+ Object.keys(props).forEach((name) => {
176
+ if (
177
+ name === 'children' ||
178
+ name === 'class' ||
179
+ name === 'className' ||
180
+ name === 'forwardedRef' ||
181
+ name === 'ref' ||
182
+ name === 'style'
183
+ )
184
+ return;
185
+
186
+ const value = props[name];
187
+
188
+ if (isEvent(name)) {
189
+ if (typeof document === 'undefined') return;
190
+
191
+ const event = getCustomEvent(name, extra.events);
192
+
193
+ if (!event) return;
194
+
195
+ setEvent(element, event, value);
196
+ } else if (extra.props.includes(name)) {
197
+ if (isPrimitive(value)) {
198
+ element.setAttribute(paramCase(name), value);
199
+ } else {
200
+ element[name] = value;
201
+ }
202
+ } else {
203
+ element[name] = value;
204
+ }
205
+ });
206
+ };
207
+
208
+ export const proxy = <ElementType, PropType>(
209
+ tagName: string,
210
+ props: Array<string> = [],
211
+ events: Array<string> = []
212
+ ) => {
213
+ const extra: ExtraType = {
214
+ props,
215
+ events
216
+ };
217
+
218
+ const ReactComponent = class extends React.Component<PropsType<ElementType>> {
219
+ element!: ElementType;
220
+
221
+ setElement = (element: ElementType) => {
222
+ this.element = element;
223
+ };
224
+
225
+ constructor(props: PropsType<ElementType>) {
226
+ super(props);
227
+ }
228
+
229
+ componentDidMount() {
230
+ this.componentDidUpdate(/*this.props*/);
231
+ }
232
+
233
+ componentDidUpdate(/*prevProps: InternalProps<ElementType>*/) {
234
+ setProps<ElementType>(this.element as any, this.props, extra);
235
+ }
236
+
237
+ componentWillUnmount() {
238
+ if (!this.element) return;
239
+
240
+ const events = this.element['$events'] || {};
241
+
242
+ Object.keys(events).forEach((name) => {
243
+ const handler = events[name];
244
+
245
+ (this.element as any).removeEventListener(name, handler);
246
+ });
247
+
248
+ delete this.element['$events'];
249
+ }
250
+
251
+ render() {
252
+ const { children } = this.props;
253
+
254
+ const props = getProps<ElementType>(this.setElement, this.props, extra);
255
+
256
+ return React.createElement(tagName, props, children);
257
+ }
258
+ };
259
+
260
+ // TODO
261
+ // const ReactComponentNew = (props: InternalPropsType<ElementType>) => {
262
+
263
+ // const { children } = props;
264
+
265
+ // const ref = useRef(null);
266
+
267
+ // const newProps: FinalPropsType<ElementType> = getProps(ref, props, events);
268
+
269
+ // useEffect(() => setProps(ref.current, props, events));
270
+
271
+ // return React.createElement(tagName, newProps, children);
272
+ // }
273
+
274
+ ReactComponent['displayName'] = pascalCase(tagName);
275
+
276
+ return forwardRef<ElementType, PropType>(ReactComponent);
277
+ };
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "experimentalDecorators": true,
4
+ "declaration": true,
5
+ "declarationDir": "dist",
6
+ "module": "esnext",
7
+ "target": "es5",
8
+ "lib": ["es6", "dom", "es2016", "es2017"],
9
+ "sourceMap": true,
10
+ "jsx": "react",
11
+ "moduleResolution": "node",
12
+ "allowSyntheticDefaultImports": true,
13
+ "esModuleInterop": true
14
+ },
15
+ "include": ["src"],
16
+ "exclude": ["dist", "node_modules"]
17
+ }
@@ -0,0 +1 @@
1
+ export declare const __dirname: (url: string | URL) => string;
@@ -0,0 +1,5 @@
1
+ import { dirname } from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ export const __dirname = (url) => {
4
+ return dirname(fileURLToPath(url));
5
+ };
@@ -1,7 +1,10 @@
1
+ export * from './__dirname.js';
1
2
  export * from './get-initializer.js';
2
3
  export * from './get-tags.js';
3
4
  export * from './get-type.js';
4
5
  export * from './has-decorator.js';
6
+ export * from './is-directory-empty.js';
5
7
  export * from './print-type.js';
6
8
  export * from './print.js';
9
+ export * from './render-template.js';
7
10
  export * from './visitor.js';
@@ -1,7 +1,10 @@
1
+ export * from './__dirname.js';
1
2
  export * from './get-initializer.js';
2
3
  export * from './get-tags.js';
3
4
  export * from './get-type.js';
4
5
  export * from './has-decorator.js';
6
+ export * from './is-directory-empty.js';
5
7
  export * from './print-type.js';
6
8
  export * from './print.js';
9
+ export * from './render-template.js';
7
10
  export * from './visitor.js';
@@ -0,0 +1 @@
1
+ export declare const isDirectoryEmpty: (directory: string) => Promise<boolean>;