Skip to content

Commit f122496

Browse files
Merge pull request #1 from functionalland/feature/types
Add types and update tests
2 parents 6d77ba9 + 89134c3 commit f122496

File tree

14 files changed

+821
-578
lines changed

14 files changed

+821
-578
lines changed

README.md

Lines changed: 87 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
11
# Functional Component
22

33
This is an experiemental project. The goal is to build a rendering framework
4-
leveraging the [web components API](https://developer.mozilla.org/en-US/docs/Web/Web_Components).
4+
leveraging the
5+
[web components API](https://developer.mozilla.org/en-US/docs/Web/Web_Components).
56
If you don't know what to do with it... it's okay.
67

78
## API
89

910
### `factorizeComponent`
1011

11-
Factorizes a component given a render function, a state and an arbitrary number of composable functions.
12+
Factorizes a component given a render function, a state and an arbitrary number
13+
of composable functions.
1214

13-
The first argument is a render function. The function is called once when the component is connected to the DOM.
14-
The render function should accept two parameters, the first one is the element that is being rendered.
15-
The second parameter is the current state that should be used to render the component.
15+
The first argument is a render function. The function is called once when the
16+
component is connected to the DOM. The render function should accept two
17+
parameters, the first one is the element that is being rendered. The second
18+
parameter is the current state that should be used to render the component.
1619

17-
The second argument to the `factorizeComponent` function is an object that will be used as the inital state.
20+
The second argument to the `factorizeComponent` function is an object that will
21+
be used as the inital state.
1822

19-
`State :: Object`
20-
`R :: (DOMElement, State) -> void`
21-
`F :: (((Component, R, State) -> C) -> void, ((DOMElement) -> E) -> void) -> void`
22-
`factorizeComponent :: ((DOMElement, State) -> void, State, [...F]) -> Component`
23+
`State :: Object`\
24+
`R :: (DOMElement, State) -> void`\
25+
`F :: (((Component, R, State) -> C) -> void, ((DOMElement) -> E) -> void) -> void`\
26+
`factorizeComponent :: ((DOMElement, State) -> void, State, [...F]) -> Component`
2327

2428
```js
2529
window.customElements.define(
@@ -30,23 +34,24 @@ window.customElements.define(
3034
h1.textContent = title;
3135
e.appendChild(e);
3236
},
33-
{ title: "Bluebird" }
34-
)
37+
{ title: "Bluebird" },
38+
),
3539
);
3640
```
3741

3842
#### Higher-order-function
3943

40-
The `factorizeComponent` also accepts an arbitrary amount of functions as arguments.
41-
Those higher-order-functions should accept 2 parameters; the first one is named `factorize`, the second is named
42-
`construct`.
44+
The `factorizeComponent` also accepts an arbitrary amount of functions as
45+
arguments. Those higher-order-functions should accept 2 parameters; the first
46+
one is named `factorize`, the second is named `construct`.
4347

44-
Both HOFs accepts a function that will be called, respectively, at the factory phase, before the component is
45-
initialize, and, at the construction phase, when the component is being instantiated.
48+
Both HOFs accepts a function that will be called, respectively, at the factory
49+
phase, before the component is initialize, and, at the construction phase, when
50+
the component is being instantiated.
4651

47-
The factorize function has three parameters; the first parameter is a Component constructor;
48-
the second parameter is the render function which can be called to queue a render request;
49-
the third parameter is the initial state.
52+
The factorize function has three parameters; the first parameter is a Component
53+
constructor; the second parameter is the render function which can be called to
54+
queue a render request; the third parameter is the initial state.
5055

5156
```js
5257
window.customElements.define(
@@ -65,16 +70,16 @@ window.customElements.define(
6570
value() {
6671
render(this);
6772
},
68-
}
73+
},
6974
);
7075

7176
return Component;
7277
});
7378
construct((element) => {
7479
element.dataset.forceRender = true;
7580
});
76-
}
77-
)
81+
},
82+
),
7883
);
7984
```
8085

@@ -92,33 +97,37 @@ fetchTemplate("/demo.html")()
9297

9398
### `useAttributes`
9499

95-
Creates a reactive lifecycle with a simple state reducer.
96-
When a user or a program sets an attribute of the component, the validation function is called which decides if the
97-
component should be rendered again.
100+
Creates a reactive lifecycle with a simple state reducer. When a user or a
101+
program sets an attribute of the component, the validation function is called
102+
which decides if the component should be rendered again.
98103

99-
The `useAttributes` function accepts a function to validate an observed attributes value and create a new state. The
100-
validation function should have three parameters. The first one is an object representing the attribute that was
101-
changed, the second is the element that is affected and the last is the current state of the element. The validation
102-
function shoudl return a state fragment or false to cancel the render.
104+
The `useAttributes` function accepts a function to validate an observed
105+
attributes value and create a new state. The validation function should have
106+
three parameters. The first one is an object representing the attribute that was
107+
changed, the second is the element that is affected and the last is the current
108+
state of the element. The validation function shoudl return a state fragment or
109+
false to cancel the render.
103110

104-
The hook function also takes a map object for all of the attributes to observe.The value is a function to transform
105-
the value before the validation function called. If not transformation is needed, just pass the identity function.
106-
`(x) => x`
111+
The hook function also takes a map object for all of the attributes to
112+
observe.The value is a function to transform the value before the validation
113+
function called. If not transformation is needed, just pass the identity
114+
function. `(x) => x`
107115

108116
```js
109117
window.customElements.define(
110118
"iy-demo",
111119
factorizeComponent(
112120
(element, { value }) => {
113-
const span = element.querySelector("span");
114-
span.textContent = String(value);
121+
const span = element.querySelector("span");
122+
span.textContent = String(value);
115123
},
116124
{ value: 0 },
117125
useAttributes(
118-
({ oldValue, value }) => (oldValue !== value && value >= 0) ? ({ value }) : false,
126+
({ oldValue, value }) =>
127+
(oldValue !== value && value >= 0) ? ({ value }) : false,
119128
{
120-
value: Number
121-
}
129+
value: Number,
130+
},
122131
),
123132
(factorize) => {
124133
factorize((Component) => {
@@ -143,24 +152,28 @@ window.customElements.define(
143152
);
144153
return Component;
145154
});
146-
}
147-
)
155+
},
156+
),
148157
);
149158
```
150159

151160
### `useCallbacks`
152161

153-
Hooks into the component's lifecycle. Learn more about [lifecycle callbacks on MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks)
162+
Hooks into the component's lifecycle. Learn more about
163+
[lifecycle callbacks on MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks)
154164

155-
The function accepts as argument an object of function to hook into one of the following callback:
156-
`connectedCallback`, `disconnectedCallback`, `attributeChangedCallback` and `adoptedCallback`.
165+
The function accepts as argument an object of function to hook into one of the
166+
following callback: `connectedCallback`, `disconnectedCallback`,
167+
`attributeChangedCallback` and `adoptedCallback`.
157168

158-
Each callback function will be called when appropriate with the element, the relevant options and a `asyncRender`
159-
function as arguments.
160-
The `asyncRender` function can be called at any moment with a "state setter" function. This returns a thunk function
161-
that may accept an argument. When the thunk function is called, the "state setter" function is called with the
162-
current element and state as argument. This function should return a state fragment or false. The state fragment is
163-
then merged with the current state and set the relevant component attributes. See `useAttribute`.
169+
Each callback function will be called when appropriate with the element, the
170+
relevant options and a `asyncRender` function as arguments. The `asyncRender`
171+
function can be called at any moment with a "state setter" function. This
172+
returns a thunk function that may accept an argument. When the thunk function is
173+
called, the "state setter" function is called with the current element and state
174+
as argument. This function should return a state fragment or false. The state
175+
fragment is then merged with the current state and set the relevant component
176+
attributes. See `useAttribute`.
164177

165178
```js
166179
window.customElements.define(
@@ -178,8 +191,11 @@ window.customElements.define(
178191
button.textContent = "Add";
179192
element.appendChild(span);
180193
element.appendChild(button);
181-
button.addEventListener("click", render((e, { value }) => ({ value: ++value })));
182-
}
194+
button.addEventListener(
195+
"click",
196+
render((e, { value }) => ({ value: ++value })),
197+
);
198+
},
183199
}),
184200
(factorize) => {
185201
factorize((Component, render) => {
@@ -206,16 +222,16 @@ window.customElements.define(
206222

207223
return Component;
208224
});
209-
}
210-
)
225+
},
226+
),
211227
);
212228
```
213229

214230
### `useShadow`
215231

216232
Attaches a shadow root to every instance of the Component.
217-
218-
```js
233+
234+
```js
219235
window.customElements.define(
220236
"iy-demo",
221237
factorizeComponent(
@@ -224,21 +240,23 @@ window.customElements.define(
224240
span.textContent = String(value);
225241
},
226242
{ value: 0 },
227-
useShadow({ mode: "open" })
228-
)
243+
useShadow({ mode: "open" }),
244+
),
229245
);
230-
```
246+
```
231247

232248
### `useTemplate`
233249

234-
Automatically appends a clone of a template to the element or the element's shadow root.
250+
Automatically appends a clone of a template to the element or the element's
251+
shadow root.
235252

236-
The function accepts a function that must return a template instance or a Promise of a template instance.
237-
Optionally, the function can also be passed an object as the second argument that is used to define
238-
children that would be often queried during the render phase.
239-
The object's values must be a function that will accept the component instance as the first parameter
240-
and return a child element or node list.
241-
The elements will be accessible as the `elements` property of the Component instance element.
253+
The function accepts a function that must return a template instance or a
254+
Promise of a template instance. Optionally, the function can also be passed an
255+
object as the second argument that is used to define children that would be
256+
often queried during the render phase. The object's values must be a function
257+
that will accept the component instance as the first parameter and return a
258+
child element or node list. The elements will be accessible as the `elements`
259+
property of the Component instance element.
242260

243261
```js
244262
window.customElements.define(
@@ -252,16 +270,15 @@ window.customElements.define(
252270
useTemplate(
253271
() => {
254272
const t = window.document.createElement("template");
255-
t.innerHTML = `<span>0</span><button>Add</button>`
273+
t.innerHTML = `<span>0</span><button>Add</button>`;
256274

257275
return t;
258276
},
259277
{
260278
number: (e) => e.shadowRoot.querySelector("span"),
261-
addButton: (e) => e.shadowRoot.querySelector("button")
262-
}
263-
)
279+
addButton: (e) => e.shadowRoot.querySelector("button"),
280+
},
281+
),
264282
),
265283
);
266284
```
267-

library/asserts.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { Deno } = globalThis;
22
const noColor = typeof Deno?.noColor === "boolean" ? Deno.noColor : true;
3-
let enabled = !noColor;
3+
const enabled = !noColor;
44
function code(open, close) {
55
return {
66
open: `\x1b[${open.join(";")}m`,
@@ -82,7 +82,7 @@ const ANSI_PATTERN = new RegExp(
8282
function stripColor(string) {
8383
return string.replace(ANSI_PATTERN, "");
8484
}
85-
var DiffType;
85+
let DiffType;
8686
(function (DiffType1) {
8787
DiffType1["removed"] = "removed";
8888
DiffType1["common"] = "common";

library/asserts.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ import {
1212
stripColor,
1313
white,
1414
} from "https://deno.land/[email protected]/fmt/colors.ts";
15-
import { diff, DiffResult, diffstr, DiffType } from "https://deno.land/[email protected]/testing/_diff.ts";
15+
import {
16+
diff,
17+
DiffResult,
18+
diffstr,
19+
DiffType,
20+
} from "https://deno.land/[email protected]/testing/_diff.ts";
1621

1722
const CAN_NOT_DISPLAY = "[Cannot display]";
1823

0 commit comments

Comments
 (0)