diff --git a/.gitignore b/.gitignore
index 0999174..27f5511 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,9 @@
/lib
/dist
/.cache
+fixtures
+support
+plugins
node_modules
package-lock.json
pnpm-lock.yaml
diff --git a/cypress.json b/cypress.json
index bd86a80..c80b699 100644
--- a/cypress.json
+++ b/cypress.json
@@ -1,4 +1,8 @@
{
"baseUrl": "http://localhost:1234",
- "video": false
+ "chromeWebSecurity": false,
+ "defaultCommandTimeout": 10000,
+ "modifyObstructiveCode": false,
+ "video": false,
+ "fixturesFolder": false
}
diff --git a/cypress/integration/test.spec.js b/cypress/integration/test.spec.js
index 208bfbd..dcee743 100644
--- a/cypress/integration/test.spec.js
+++ b/cypress/integration/test.spec.js
@@ -1,13 +1,25 @@
///
+const { watchFile } = require("fs")
+
context('Page load', () => {
beforeEach(() => {
cy.visit('/')
+ cy.wait(500)
})
describe('React integration', () => {
+
it('Should mount', () => {
cy.get('#app')
.should('exist', 'success')
})
+ it('Should have foo property on button', () => {
+ cy.get('.clicker')
+ // .its('foo')
+ // .should('eq', 3)
+ .then(($el) => {
+ cy.wrap($el[0].foo).should('eq', 3)
+ })
+ })
})
})
diff --git a/example/index.js b/example/index.js
index 7e18bea..f9452d1 100644
--- a/example/index.js
+++ b/example/index.js
@@ -13,6 +13,9 @@ function main(sources) {
const reset$ = sources.react
.select(btnSel)
.events('click')
+ .debug((ev) => {
+ return ev.target.printer()
+ })
.mapTo(() => 0);
const count$ = xs
@@ -22,7 +25,7 @@ function main(sources) {
const vdom$ = count$.map(i =>
h('div', [
h('h1', `Hello ${i} times`),
- h('button', {sel: btnSel}, 'Reset'),
+ h('button', {sel: btnSel, className: 'clicker', domProps: {foo: 3, printer: () => console.log('domProps being used')}}, 'Reset'),
]),
);
diff --git a/package.json b/package.json
index cac7bb9..74b2fef 100644
--- a/package.json
+++ b/package.json
@@ -49,8 +49,11 @@
"compile": "npm run compile-cjs && npm run compile-es6",
"compile-cjs": "tsc --module commonjs --outDir ./lib/cjs",
"compile-es6": "echo 'TODO' : tsc --module es6 --outDir ./lib/es6",
- "test": "$(npm bin)/mocha test/*.ts --require ts-node/register --recursive; cypress run",
+ "test": "$(npm bin)/mocha test/*.ts --require ts-node/register --recursive",
+ "full-test": "npm test; npm run cypress:run",
"start": "parcel example/index.html",
- "serve-test": "start-server-and-test start http://localhost:1234 test"
+ "serve-test": "start-server-and-test start http://localhost:1234 full-test",
+ "cypress:open": "cypress open",
+ "cypress:run": "cypress run"
}
}
diff --git a/src/h.ts b/src/h.ts
index 76c12b0..0de6203 100644
--- a/src/h.ts
+++ b/src/h.ts
@@ -5,6 +5,10 @@ import {
ElementType,
ReactHTML,
Attributes,
+ Component,
+ ComponentType,
+ createRef,
+ forwardRef
} from 'react';
import {incorporate} from './incorporate';
@@ -17,6 +21,78 @@ type PropsLike
= P & PropsExtensions & Attributes;
type Children = string | Array;
+export function domPropify(Comp: any): ComponentType {
+ class DomProps extends Component {
+ private ref: any;
+ private domProps: any;
+ constructor(props) {
+ super(props);
+ this.domProps = this.props.domProps;
+ this.ref = props.forwardedRef || createRef();
+ }
+
+ public componentDidMount() {
+ if (this.domProps && this.ref) {
+ Object.entries(this.domProps).forEach(([key, val]) => {
+ this.ref.current[key] = val;
+ });
+ }
+ }
+
+ render() {
+ const p: any = {ref: this.ref, ...this.props};
+ delete p.forwardedRef
+ delete p.domProps;
+ return createElement(Comp, p);
+ }
+ }
+
+ return forwardRef((props, ref) => {
+ return createElement(DomProps, {...props, forwardedRef: ref});
+ });
+}
+
+export function domHookify(Comp: any): ComponentType {
+ class DomHooks extends Component {
+ private ref: any;
+ private hooks: any;
+ constructor(props) {
+ super(props);
+ this.hooks = this.props.domHooks;
+ this.ref = props.forwardedRef || createRef();
+ }
+
+ public componentDidMount() {
+ if (this.hooks && this.hooks.insert && this.ref) {
+ this.hooks.insert({elm: this.ref.current})
+ }
+ }
+
+ public componentDidUpdate() {
+ if (this.hooks && this.hooks.update && this.ref) {
+ this.hooks.update({elm: this.ref.current})
+ }
+ }
+
+ public componentWillUnmount() {
+ if (this.hooks && this.hooks.destroy && this.ref) {
+ this.hooks.destroy({elm: this.ref.current})
+ }
+ }
+
+ render() {
+ const p: any = {ref: this.ref, ...this.props};
+ delete p.forwardedRef
+ delete p.domHooks;
+ return createElement(Comp, p);
+ }
+ }
+
+ return forwardRef((props, ref) => {
+ return createElement(DomHooks, {...props, forwardedRef: ref});
+ });
+}
+
function createElementSpreading(
type: ElementType
| keyof ReactHTML,
props: PropsLike
| null,
@@ -36,7 +112,7 @@ function hyperscriptProps
(
if (!props.sel) {
return createElement(type, props);
} else {
- return createElement(incorporate(type), props);
+ return createElement(domHookify(domPropify(incorporate(type))), props);
}
}
@@ -55,7 +131,7 @@ function hyperscriptPropsChildren
(
if (!props.sel) {
return createElementSpreading(type, props, children);
} else {
- return createElementSpreading(incorporate(type), props, children);
+ return createElementSpreading(domHookify(domPropify(incorporate(type))), props, children);
}
}