Skip to content

Commit 4950640

Browse files
committed
docs
1 parent ead6962 commit 4950640

8 files changed

Lines changed: 104 additions & 26 deletions

File tree

README.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -731,18 +731,39 @@ There are several collections on Stackblitz with over 200 examples that can get
731731
732732
[The Collection](https://stackblitz.com/@dariomannu/collections/rimmel-js-experiments) 🧞 Stream-Oriented programming examples using Rimmel.
733733
734+
### Recipes
735+
How to do stream-oriented this and that
736+
737+
[Drag'n'Drop](https://stackblitz.com/orgs/github/ReactiveHTML/collections/drad-and-drop) Several different ways to implement drag'n'drop
738+
739+
[Fetching Data](https://stackblitz.com/orgs/github/ReactiveHTML/collections/fetching-data) Connecting to REST APIs
740+
741+
[UI Components](https://stackblitz.com/orgs/github/ReactiveHTML/collections/ui-components) How streams make it simpler to manage any sort of UI component
742+
743+
[Dialog Boxes](https://stackblitz.com/orgs/github/ReactiveHTML/collections/dialog-boxes) From popups to login boxes and forms
744+
745+
[Observable Types](https://stackblitz.com/orgs/github/ReactiveHTML/collections/observable-types) When lists are involved, consider this
746+
734747
### Experiments
735748
This is the cutting-edge of what you can do with Rimmel, still being refined here and there, but will show you where things are going and maybe give you some inspiration.
736749
737750
[Web Components](https://stackblitz.com/@dariomannu/collections/web-components) 🧩 Experimental support for custom elements and web components in stream-oriented style.
738751
739752
[Web Workers](https://stackblitz.com/@dariomannu/collections/web-workers) 🛠️ Experiments running your Rimmel components inside web workers
740753
741-
[Novel Design Patterns](https://stackblitz.com/@dariomannu/collections/novel-design-patterns) 📖 What makes stream-oriented programming different
754+
[Novel Design Patterns](https://stackblitz.com/@dariomannu/collections/novel-design-patterns) 📖 What makes stream-oriented programming unique
755+
756+
[Native Observables](https://stackblitz.com/orgs/github/ReactiveHTML/collections/native-observables-in-rimmel-js) 👶 A few ways to integrate with the current web standards proposal for native Observables.
757+
758+
[Observable Polyfill](https://stackblitz.com/@dariomannu/collections/observable-polyfill) 🧴 Stream-oriented examples for when you need a native polyfill
759+
760+
[Callforwards](https://stackblitz.com/orgs/github/ReactiveHTML/collections/callforwards) 🤙 Want to explore alternative stream types beside Observables?
761+
762+
[LeapingBunny](https://stackblitz.com/@dariomannu/collections/leapingbunny) 💉 Unit testing your streams and components with ASCII-ART sequences
742763
743-
[Observable Polyfill](https://stackblitz.com/@dariomannu/collections/observable-polyfill) 🧴 stream-oriented examples for the [observable-polyfill](https://github.com/keithamus/observable-polyfill/).
764+
[WebGL/WebGPU](https://stackblitz.com/orgs/github/ReactiveHTML/collections/webgl-webgpu) 🎲 Integrations with THREE.js
744765
745-
[Native Observables](https://stackblitz.com/orgs/github/ReactiveHTML/collections/native-observables-in-rimmel-js) 👶 Experiments using native Observables.
766+
[Security](https://stackblitz.com/@paperboy/collections/rimmel-js-security) 🔒 Hardening your stream-oriented applications
746767
747768
### The classics
748769

src/lib/addListener.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ const isEventListenerObject = (l: any): l is EventListenerObject => !!l?.handleE
99

1010
export const addListener = (node: EventTarget, eventName: RMLEventName, listener: RMLEventListener, options?: AddEventListenerOptions | boolean) => {
1111
// We also force-add an event listener if we're inside a ShadowRoot (do we really need to?), as events inside web components don't seem to fire otherwise
12-
if (USE_DOM_OBSERVABLES && node.when) {
12+
if (USE_DOM_OBSERVABLES && (node as any).when) {
1313
// Explicitly excluding the isEventListenerObject as Domenic doesn't want .when() to support it
1414
if (!isEventListenerObject(listener)) {
15-
const source = node.when(eventName, <ObservableEventListenerOptions | undefined>options);
15+
const source = (node as any).when(eventName, <ObservableEventListenerOptions | undefined>options);
1616
if (isObservature(listener)) {
1717
(<IObservature<Event>>listener).addSource(source as MonkeyPatchedObservable<Event>);
1818
} else {

src/parser/parser.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,64 @@ describe('Parser', () => {
344344
describe('Sinks', () => {
345345

346346
describe('Attributes', () => {
347+
348+
describe('Classes', () => {
349+
350+
describe('When a string is passed', () => {
351+
352+
it('sets the value inline', () => {
353+
const className = 'my-class';
354+
const template = rml`<div class="${className}">Hello</div>`;
355+
356+
expect(template).toEqual('<div class="my-class">Hello</div>');
357+
});
358+
359+
it('sets deferred values later, initial value is empty', () => {
360+
const className = defer('my-class');
361+
const template = rml`<div class="${className}">Hello</div>`;
362+
363+
expect(template).toMatch(/<div.+class="">Hello<\/div>/);
364+
expect(waitingElementHandlers.get('RMLREF+0')).toMatchObject([
365+
// TODO: match the sink, too
366+
{ source: className, type: 'sink', t: 'class' },
367+
]);
368+
});
369+
370+
});
371+
372+
describe('When a plain object is passed', () => {
373+
374+
it('sets the value inline', () => {
375+
const classes = { 'class-a': true, 'class-b': false, 'class-c': true };
376+
const template = rml`<div class="${classes}">Hello</div>`;
377+
378+
expect(template).toEqual('<div class="class-a class-c">Hello</div>');
379+
});
380+
381+
});
382+
383+
describe('When an object of deferred values is passed', () => {
384+
385+
it('sets values later, initial value is empty', () => {
386+
const classes = { 'class-a': defer(true), 'class-b': defer(false) };
387+
const template = rml`<div class="${classes}">Hello</div>`;
388+
389+
expect(template).toMatch(/<div.+class="">Hello<\/div>/);
390+
expect(waitingElementHandlers.get('RMLREF+0')).toMatchObject([
391+
// TODO: match the sink, too
392+
{ source: classes['class-a'], type: 'sink', t: 'class' },
393+
]);
394+
});
395+
396+
});
397+
398+
});
399+
400+
describe('Styles', () => {
401+
402+
});
403+
404+
347405
});
348406

349407
describe('Dataset', () => {

src/sinks/event-handler-sink.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { addListener } from "../lib/addListener";
2-
import type { RMLEventListener, HTMLEventName } from "../types/dom";
2+
import type { EventListener, HTMLEventName } from "../types/dom";
33
import type { Sink } from "../types/sink";
44

5+
// FIXME: wrap handler and options in an object, x streams can't emit both values!
6+
// Alternatively, set it in the constructor
57
export const EventHandlerSink: Sink<HTMLElement> = (node: HTMLElement, e: HTMLEventName) =>
6-
(handler: RMLEventListener, options?: AddEventListenerOptions) =>
7-
addListener(node, e, handler, options);
8+
(handler: EventListener<Event>, options?: AddEventListenerOptions) =>
9+
// FIXME: to be able to remove an event listener, will need to store a reference to it first!
10+
addListener(node, e, handler, options)
11+
;
12+

src/sinks/inner-html-sink.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,3 @@ export const InnerHTML: ExplicitSink<'content'> = (source: RMLTemplateExpression
2525
sink: InnerHTMLSink,
2626
})
2727
;
28-

src/sources/event-listener.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import { addListener } from "../lib/addListener";
2-
import type { RMLEventListener, HTMLEventName } from "../types/dom";
2+
import type { EventListener, HTMLEventName } from "../types/dom";
3+
4+
export const eventListnerSource = (node: HTMLElement, eventName: HTMLEventName, handler: EventListener<Event>, options?: AddEventListenerOptions) =>
5+
addListener(node, eventName, handler, options)
6+
;
37

4-
export const eventListnerSource = (
5-
node: HTMLElement,
6-
eventName: HTMLEventName,
7-
handler: RMLEventListener,
8-
options?: AddEventListenerOptions
9-
) => {
10-
return addListener(node, eventName, handler, options);
11-
};

src/sources/swap-source.test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { Observable } from 'rxjs';
33
import { Subject } from 'rxjs';
44
import { Swap, swap } from './swap-source';
55
import { MockElement, MockEvent } from '../test-support';
6+
import { Observer } from '../types';
67

78
describe('Swap Event Adapter', () => {
89
it('Swaps a value from an element with a static string', () => {
@@ -17,7 +18,7 @@ describe('Swap Event Adapter', () => {
1718
target: el as HTMLInputElement
1819
});
1920
const handlerSpy = jest.fn();
20-
const source = Swap(newValue, handlerSpy);
21+
const source = Swap(newValue, handlerSpy) as Observer<any>;
2122

2223
source.next(eventData);
2324

@@ -36,8 +37,8 @@ it('Swaps a value from an element with empty string by default', () => {
3637
const eventData = MockEvent('input', {
3738
target: el as HTMLInputElement
3839
});
39-
const handlerSpy = jest.fn();
40-
const source = Swap(undefined, handlerSpy);
40+
const handlerSpy = jest.fn();
41+
const source = Swap(undefined, handlerSpy) as Observer<any>;
4142

4243
source.next(eventData);
4344

@@ -57,7 +58,7 @@ it('Swaps a value using a function that transforms based on the old value', () =
5758
target: el as HTMLInputElement
5859
});
5960
const handlerSpy = jest.fn();
60-
const source = Swap(replacementFn, handlerSpy);
61+
const source = Swap(replacementFn, handlerSpy) as Observer<any>;
6162

6263
source.next(eventData);
6364

src/types/dom.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,19 +106,17 @@ export interface EventListenerObject<E extends Event | any> {
106106
handleEvent(e: E): void;
107107
};
108108

109-
export type EventListener<E extends Event> = EventListenerFunction<E> | EventListenerObject<E>;
110-
export type EventListenerOrEventListenerObject<E extends Event> = EventListener<E>;
109+
export type EventListener<E extends Event = Event> = EventListenerFunction<E> | EventListenerObject<E>;
111110

112111
// /**
113112
// * A generic equivalent of the DOM's EventListenerOrEventListenerObject
114113
// */
115-
// export type EventListenerOrEventListenerObject<T = Event> = ((evt: T) => void) | { handleEvent: (evt: T) => void };
114+
export type EventListenerOrEventListenerObject<E extends Event = Event> = EventListener<E>;
116115

117116
export type BooleanAttributeValue<T extends BooleanAttribute> = MaybeFuture<boolean | T | 'true'>;
118117

119118
type DisabledType = 'disabled';
120119

121-
122120
// export type DocumentObject<E extends HTMLElement> = EventObject & ClassAttribute & DatasetObject & StyleObject & ValueAttribute<E> & ContentAttribute & GenericAttribute;
123121

124122
/**

0 commit comments

Comments
 (0)