@htmlplus/element 1.1.0 → 2.0.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htmlplus/element",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "author": "Masood Abdolian <m.abdolian@gmail.com>",
@@ -1,6 +1,5 @@
1
1
  export * from './assets.js';
2
2
  export * from './copy.js';
3
- export * from './customElementReact/index.js';
4
3
  export * from './customElement.js';
5
4
  export * from './document.js';
6
5
  export * from './extract.js';
@@ -1,6 +1,5 @@
1
1
  export * from './assets.js';
2
2
  export * from './copy.js';
3
- export * from './customElementReact/index.js';
4
3
  export * from './customElement.js';
5
4
  export * from './document.js';
6
5
  export * from './extract.js';
@@ -1,16 +0,0 @@
1
- import { TransformerPlugin, TransformerPluginContext } from '../../transformer.types';
2
- export declare const CUSTOM_ELEMENT_REACT_OPTIONS: Partial<CustomElementReactOptions>;
3
- export interface CustomElementReactOptions {
4
- compact?: boolean;
5
- destination: string;
6
- eventName?: (eventName: string) => string;
7
- importerElement: (context: TransformerPluginContext) => {
8
- source: string;
9
- };
10
- importerElementType: (context: TransformerPluginContext) => {
11
- source: string;
12
- imported: string;
13
- local: string;
14
- };
15
- }
16
- export declare const customElementReact: (options: CustomElementReactOptions) => TransformerPlugin;
@@ -1,97 +0,0 @@
1
- import { pascalCase } from 'change-case';
2
- import { __dirname, isDirectoryEmpty, renderTemplate } from '../../utils/index.js';
3
- export const CUSTOM_ELEMENT_REACT_OPTIONS = {};
4
- export const customElementReact = (options) => {
5
- const name = 'customElementReact';
6
- options = Object.assign({}, CUSTOM_ELEMENT_REACT_OPTIONS, options);
7
- const finish = (global) => {
8
- // TODO
9
- const globalNew = {
10
- contexts: global.contexts.reduce((previous, current) => (Object.assign(Object.assign({}, previous), { [current.filePath]: current })), {}),
11
- options
12
- };
13
- const config = { cwd: __dirname(import.meta.url) };
14
- const isEmpty = isDirectoryEmpty(options.destination);
15
- const skip = [];
16
- const getKey = (element) => element.className;
17
- for (const key in globalNew.contexts) {
18
- const context = globalNew.contexts[key];
19
- const classEvents = context.classEvents.map((classEvent) => {
20
- var _a, _b;
21
- const from = 'on' + pascalCase(classEvent.key.name);
22
- const to = (_b = (_a = options.eventName) === null || _a === void 0 ? void 0 : _a.call(options, from)) !== null && _b !== void 0 ? _b : from;
23
- return Object.assign(Object.assign({}, classEvent), { from,
24
- to });
25
- });
26
- const fileName = context.fileName;
27
- const importerElement = options.importerElement(context);
28
- const importerElementType = options.importerElementType(context);
29
- const state = Object.assign(Object.assign({}, context), { classEvents,
30
- fileName,
31
- importerElement,
32
- importerElementType,
33
- options });
34
- const patterns = [
35
- 'templates/src/components/*fileName*.ts.hbs',
36
- '!templates/src/components/*fileName*.compact.ts.hbs'
37
- ];
38
- renderTemplate(patterns, options.destination, config)(state);
39
- }
40
- if (options.compact) {
41
- globalNew.groups = Object.values(globalNew.contexts)
42
- .sort((a, b) => getKey(b).length - getKey(a).length)
43
- .map((element, index, elements) => ({
44
- key: getKey(element),
45
- elements: elements.filter((current) => getKey(current).startsWith(getKey(element)))
46
- }))
47
- .sort((a, b) => b.elements.length - a.elements.length)
48
- .filter((group) => {
49
- if (skip.includes(group.key))
50
- return;
51
- group.elements.forEach((element) => skip.push(getKey(element)));
52
- return true;
53
- })
54
- .map((group) => {
55
- const all = group.elements
56
- .reverse()
57
- .map((element, index) => {
58
- const elementClassNameInCategory = getKey(element).replace(group.key, '');
59
- const importerElement = options.importerElement(element);
60
- const importerElementType = options.importerElementType(element);
61
- return Object.assign(Object.assign({}, element), { elementClassNameInCategory,
62
- importerElement,
63
- importerElementType });
64
- })
65
- // TODO: experimental
66
- .sort((a, b) => (getKey(b) < getKey(a) ? 0 : -1));
67
- return {
68
- all,
69
- filterd: all.slice(1),
70
- root: all[0],
71
- single: all.length == 1
72
- };
73
- })
74
- .sort((a, b) => (getKey(a.root) < getKey(b.root) ? -1 : 0));
75
- for (const group of globalNew.groups) {
76
- if (group.single)
77
- continue;
78
- const state = Object.assign({ fileName: group.root.fileName, options }, group);
79
- const patterns = ['templates/src/components/*fileName*.compact.ts.hbs'];
80
- renderTemplate(patterns, options.destination, config)(state);
81
- }
82
- }
83
- if (isEmpty) {
84
- const patterns = [
85
- 'templates/**',
86
- '!templates/src/components/*fileName*.ts.hbs',
87
- '!templates/src/components/*fileName*.compact.ts.hbs'
88
- ];
89
- renderTemplate(patterns, options.destination, config)(globalNew);
90
- }
91
- if (!isEmpty) {
92
- const patterns = ['templates/src/proxy*', 'templates/src/components/index*'];
93
- renderTemplate(patterns, options.destination, config)(globalNew);
94
- }
95
- };
96
- return { name, finish };
97
- };
@@ -1 +0,0 @@
1
- export * from './customElementReact.js';
@@ -1 +0,0 @@
1
- export * from './customElementReact.js';
@@ -1 +0,0 @@
1
- # React output target for your custom element.
@@ -1,2 +0,0 @@
1
- dist
2
- node_modules
@@ -1,37 +0,0 @@
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
- "YOUR_CORE_PACKAGE_NAME": "latest",
18
- "change-case": "^5.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
- "glob": "^7.2.0",
25
- "react": "^17.0.1",
26
- "react-dom": "^17.0.1",
27
- "rimraf": "^3.0.2",
28
- "rollup": "^2.27.1",
29
- "rollup-plugin-peer-deps-external": "^2.2.3",
30
- "rollup-plugin-typescript2": "^0.27.2",
31
- "typescript": "^4.0.2"
32
- },
33
- "peerDependencies": {
34
- "react": "^18.0.0",
35
- "react-dom": "^18.0.0"
36
- }
37
- }
@@ -1,21 +0,0 @@
1
- import commonjs from '@rollup/plugin-commonjs';
2
- import resolve from '@rollup/plugin-node-resolve';
3
- import glob from 'glob';
4
- import peerDepsExternal from 'rollup-plugin-peer-deps-external';
5
- import typescript from 'rollup-plugin-typescript2';
6
-
7
- export default {
8
- input: glob.sync('src/**/*.ts'),
9
- output: [
10
- {
11
- dir: 'dist',
12
- format: 'esm',
13
- },
14
- ],
15
- plugins: [
16
- peerDepsExternal(),
17
- resolve(),
18
- commonjs(),
19
- typescript(),
20
- ],
21
- };
@@ -1,17 +0,0 @@
1
- /**************************************************
2
- * THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALY
3
- **************************************************/
4
-
5
- {{#if options.compact}}
6
- {{#each groups}}
7
- {{#if single}}
8
- export * from './{{root.fileName}}';
9
- {{else}}
10
- export * from './{{root.fileName}}.compact';
11
- {{/if}}
12
- {{/each}}
13
- {{else}}
14
- {{#each contexts}}
15
- export * from './{{fileName}}';
16
- {{/each}}
17
- {{/if}}
@@ -1,18 +0,0 @@
1
- /**************************************************
2
- * THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALY
3
- **************************************************/
4
-
5
- {{#each all}}
6
- import { {{className}} } from './{{fileName}}';
7
- {{/each}}
8
-
9
- const All = Object.assign(
10
- {{root.className}},
11
- {
12
- {{#each filterd}}
13
- {{elementClassNameInCategory}}: {{className}},
14
- {{/each}}
15
- }
16
- );
17
-
18
- export { All as {{root.className}} }
@@ -1,23 +0,0 @@
1
- /**************************************************
2
- * THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALY
3
- **************************************************/
4
- import { {{className}} as {{className}}Core } from '{{importerElement.source}}';
5
- import type { {{className}}Element, {{importerElementType.imported}} as {{importerElementType.local}} } from '{{importerElementType.source}}';
6
-
7
- import { proxy } from '../proxy';
8
- import type { Rename } from '../proxy';
9
-
10
- type Renamed = Rename<
11
- {{importerElementType.local}},
12
- {
13
- {{#each classEvents}}
14
- {{from}}: '{{to}}';
15
- {{/each}}
16
- }
17
- >;
18
-
19
- export const {{className}} = proxy<{{className}}Element, Renamed>(
20
- {{className}}Core.TAG,
21
- [{{#each classProperties}}'{{key.name}}', {{/each}}],
22
- [{{#each classEvents}}'{{key.name}}', {{/each}}],
23
- );
@@ -1 +0,0 @@
1
- export * from './elements';
@@ -1,269 +0,0 @@
1
- /**************************************************
2
- * THIS FILE IS AUTO-GENERATED, DO NOT EDIT MANUALY
3
- **************************************************/
4
- import React from 'react';
5
-
6
- import { camelCase, kebabCase, pascalCase } from 'change-case';
7
-
8
- export type Rename<T, R extends { [K in keyof R]: K extends keyof T ? PropertyKey : 'Error: key not in T' }> = {
9
- [P in keyof T as P extends keyof R ? R[P] : P]: T[P];
10
- };
11
-
12
- type EventHandlerType = (event: Event) => any;
13
-
14
- type FinalPropsType<ElementType> = Omit<PropsType<ElementType>, 'forwardedRef'>;
15
-
16
- type Mutable<T> = { -readonly [P in keyof T]-?: T[P] };
17
-
18
- interface ExtraType {
19
- props?: Array<string>;
20
- events?: Array<string>;
21
- }
22
-
23
- interface PropsType<ElementType> extends React.HTMLAttributes<ElementType> {
24
- forwardedRef: React.RefObject<ElementType>;
25
- ref?: React.Ref<any>;
26
- }
27
-
28
- export interface StyleReactProps {
29
- class?: string;
30
- className?: string;
31
- style?: {
32
- [key: string]: any;
33
- };
34
- }
35
-
36
- const arrayToMap = (array: string[] | DOMTokenList) => {
37
- const map = new Map<string, string>();
38
-
39
- (array as string[]).forEach((s: string) => map.set(s, s));
40
-
41
- return map;
42
- };
43
-
44
- const getCustomEvent = (name: string, events: Array<string>) => {
45
- // TODO
46
- name = camelCase(name.slice(3));
47
-
48
- const event = events.find((event) => event.endsWith(name));
49
-
50
- if (!event) return;
51
-
52
- return event;
53
- };
54
-
55
- const forwardRef = <ElementType, PropType>(ReactComponent: any) => {
56
- const forwardRef = (
57
- props: PropType & Omit<React.HTMLAttributes<ElementType>, 'style'> & StyleReactProps,
58
- ref: React.Ref<ElementType>
59
- ) => {
60
- const { children, ...remainedProps } = props;
61
-
62
- const newProps = {
63
- ...remainedProps,
64
- forwardedRef: ref
65
- };
66
-
67
- return React.createElement(ReactComponent, newProps, children);
68
- };
69
-
70
- forwardRef.displayName = ReactComponent.displayName;
71
-
72
- return React.forwardRef(forwardRef);
73
- };
74
-
75
- const isEvent = (name: string) => {
76
- return name.indexOf('on') === 0 && name[2] === name[2].toUpperCase();
77
- };
78
-
79
- const isPrimitive = (value: any) => {
80
- const type = typeof value;
81
-
82
- const match = type.match(/boolean|string|number/);
83
-
84
- return match;
85
- };
86
-
87
- const getProps = <ElementType>(ref: React.Ref<ElementType>, props: PropsType<ElementType>, extra: ExtraType) => {
88
- const { forwardedRef } = props;
89
-
90
- const result: FinalPropsType<ElementType> = {
91
- ref: mergeRefs(forwardedRef, ref)
92
- };
93
-
94
- Object.keys(props).forEach((name) => {
95
- if (name === 'children' || name === 'className' || name === 'forwardedRef' || name === 'ref') return;
96
-
97
- const value = (props as any)[name];
98
-
99
- if (isEvent(name)) {
100
- if (typeof document === 'undefined') return;
101
-
102
- const event = getCustomEvent(name, extra.events || []);
103
-
104
- if (event) return;
105
-
106
- (result as any)[name] = value;
107
- } else if (extra.props?.includes(name)) {
108
- if (!isPrimitive(value)) return;
109
-
110
- (result as any)[kebabCase(name)] = value;
111
- } else {
112
- (result as any)[name] = value;
113
- }
114
- });
115
-
116
- return result;
117
- };
118
-
119
- const mergeRefs =
120
- <ElementType>(...refs: React.Ref<ElementType>[]) =>
121
- (value: ElementType) => {
122
- return refs.forEach((ref) => {
123
- if (typeof ref === 'function') return ref(value);
124
-
125
- if (ref == null) return;
126
-
127
- (ref as Mutable<React.RefObject<ElementType>>).current = value;
128
- });
129
- };
130
-
131
- const setClass = <ElementType>(element: ElementType, props: PropsType<ElementType>) => {
132
- const classes: string[] = [];
133
-
134
- const current = arrayToMap((element as any).classList);
135
-
136
- const prev: string = (element as any)['$class'];
137
- const next: string = props.className || (props as any).class;
138
-
139
- const prevClass = arrayToMap(prev ? prev.split(' ') : []);
140
- const nextClass = arrayToMap(next ? next.split(' ') : []);
141
-
142
- current.forEach((key) => {
143
- if (nextClass.has(key)) {
144
- classes.push(key);
145
-
146
- nextClass.delete(key);
147
- } else if (!prevClass.has(key)) {
148
- classes.push(key);
149
- }
150
- });
151
-
152
- nextClass.forEach((key) => classes.push(key));
153
-
154
- const className = classes.join(' ');
155
-
156
- (element as any).className = className;
157
-
158
- (element as any)['$class'] = className;
159
- };
160
-
161
- const setEvent = (element: Element, name: string, handler: EventHandlerType) => {
162
- const events = (element as any)['$events'] || ((element as any)['$events'] = {});
163
-
164
- const previous = events[name];
165
-
166
- previous && element.removeEventListener(pascalCase(name), previous);
167
-
168
- element.addEventListener(
169
- pascalCase(name),
170
- (events[name] = function callback(event: Event) {
171
- handler && handler.call(this, event);
172
- })
173
- );
174
- };
175
-
176
- const setProps = <ElementType>(element: ElementType, props: PropsType<ElementType>, extra: ExtraType) => {
177
- if (!(element instanceof Element)) return;
178
-
179
- setClass<ElementType>(element, props);
180
-
181
- Object.keys(props).forEach((name) => {
182
- if (
183
- name === 'children' ||
184
- name === 'class' ||
185
- name === 'className' ||
186
- name === 'forwardedRef' ||
187
- name === 'ref' ||
188
- name === 'style'
189
- )
190
- return;
191
-
192
- const value = (props as any)[name];
193
-
194
- if (isEvent(name)) {
195
- if (typeof document === 'undefined') return;
196
-
197
- const event = getCustomEvent(name, extra.events || []);
198
-
199
- if (!event) return;
200
-
201
- setEvent(element, event, value);
202
- } else if (extra.props?.includes(name)) {
203
- if (isPrimitive(value)) {
204
- element.setAttribute(kebabCase(name), value);
205
- } else {
206
- (element as any)[name] = value;
207
- }
208
- } else {
209
- (element as any)[name] = value;
210
- }
211
- });
212
- };
213
-
214
- export const proxy = <ElementType, PropType>(
215
- tagName: string,
216
- props: Array<string> = [],
217
- events: Array<string> = []
218
- ) => {
219
- const extra: ExtraType = {
220
- props,
221
- events
222
- };
223
-
224
- const ReactComponent = class extends React.Component<PropsType<ElementType>> {
225
- element!: ElementType;
226
-
227
- setElement = (element: ElementType) => {
228
- this.element = element;
229
- };
230
-
231
- constructor(props: PropsType<ElementType>) {
232
- super(props);
233
- }
234
-
235
- componentDidMount() {
236
- this.componentDidUpdate(/*this.props*/);
237
- }
238
-
239
- componentDidUpdate(/*prevProps: InternalProps<ElementType>*/) {
240
- setProps<ElementType>(this.element as any, this.props, extra);
241
- }
242
-
243
- componentWillUnmount() {
244
- if (!this.element) return;
245
-
246
- const events = (this.element as any)['$events'] || {};
247
-
248
- Object.keys(events).forEach((name) => {
249
- const handler = events[name];
250
-
251
- (this.element as any).removeEventListener(pascalCase(name), handler);
252
- });
253
-
254
- delete (this.element as any)['$events'];
255
- }
256
-
257
- render() {
258
- const { children } = this.props;
259
-
260
- const props = getProps<ElementType>(this.setElement, this.props, extra);
261
-
262
- return React.createElement(tagName, props, children);
263
- }
264
- };
265
-
266
- (ReactComponent as any)['displayName'] = pascalCase(tagName);
267
-
268
- return forwardRef<ElementType, PropType>(ReactComponent);
269
- };
@@ -1,17 +0,0 @@
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
- }