Skip to content

Commit b4c848e

Browse files
committed
refactor context
1 parent e1584db commit b4c848e

File tree

9 files changed

+96
-84
lines changed

9 files changed

+96
-84
lines changed

index.js

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ const effect = (fn) => {
160160
n();
161161
};
162162

163-
/** @see https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md */
164163
/* === Constants === */
165164
const CONTEXT_REQUEST = 'context-request';
166165
/* === Exported class === */
@@ -188,12 +187,42 @@ class ContextRequestEvent extends Event {
188187
callback;
189188
subscribe;
190189
constructor(context, callback, subscribe = false) {
191-
super(CONTEXT_REQUEST, { bubbles: true, composed: true });
190+
super(CONTEXT_REQUEST, {
191+
bubbles: true,
192+
composed: true
193+
});
192194
this.context = context;
193195
this.callback = callback;
194196
this.subscribe = subscribe;
195197
}
196198
}
199+
/**
200+
* Initialize context provider / consumer for a UIElement instance
201+
*
202+
* @param {UIelement} host - UIElement instance to initialize context for
203+
*/
204+
const initContext = (host) => {
205+
const proto = host.constructor;
206+
// context consumers
207+
const consumed = proto.consumedContexts || [];
208+
for (const context of consumed)
209+
host.set(String(context), undefined, false);
210+
setTimeout(() => {
211+
for (const context of consumed)
212+
host.dispatchEvent(new ContextRequestEvent(context, (value) => host.set(String(context), value)));
213+
});
214+
// context providers
215+
const provided = proto.providedContexts || [];
216+
if (!provided.length)
217+
return;
218+
host.addEventListener(CONTEXT_REQUEST, (e) => {
219+
const { context, callback } = e;
220+
if (!provided.includes(context) || !isFunction(callback))
221+
return;
222+
e.stopPropagation();
223+
callback(host.get(String(context)));
224+
});
225+
};
197226

198227
/* === Exported Function === */
199228
/**
@@ -217,6 +246,7 @@ async (ui) => {
217246
return ui;
218247
};
219248

249+
/* === Exported Functions === */
220250
/**
221251
* Add event listener to a target element
222252
*
@@ -480,26 +510,7 @@ class UIElement extends HTMLElement {
480510
* @since 0.7.0
481511
*/
482512
connectedCallback() {
483-
const proto = this.constructor;
484-
// context consumer
485-
const consumed = proto.consumedContexts || [];
486-
for (const context of consumed)
487-
this.set(String(context), undefined);
488-
setTimeout(() => {
489-
for (const context of consumed)
490-
this.dispatchEvent(new ContextRequestEvent(context, (value) => this.set(String(context), value)));
491-
});
492-
// context provider: listen to context request events
493-
const provided = proto.providedContexts || [];
494-
if (!provided.length)
495-
return;
496-
this.addEventListener(CONTEXT_REQUEST, (e) => {
497-
const { context, callback } = e;
498-
if (!provided.includes(context) || !isFunction(callback))
499-
return;
500-
e.stopPropagation();
501-
callback(this.#states.get(String(context)));
502-
});
513+
initContext(this);
503514
}
504515
disconnectedCallback() { }
505516
/**

index.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { setAttribute, setProperty, setStyle, setText, toggleAttribute, toggleCl
99

1010
/**
1111
* @name UIElement
12-
* @version 0.8.2
12+
* @version 0.8.3
1313
*/
1414

1515
export {

src/core/context-request.ts renamed to src/core/context.ts

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { UIElement } from "../ui-element"
2+
import { isFunction } from "./is-type"
3+
14
/** @see https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md */
25

36
/* === Type definitions === */
@@ -29,13 +32,13 @@ type ContextType<T extends UnknownContext> = T extends Context<infer _, infer V>
2932
type ContextCallback<V> = (value: V, unsubscribe?: () => void) => void
3033

3134
declare global {
32-
interface HTMLElementEventMap {
33-
/**
34-
* A 'context-request' event can be emitted by any element which desires
35-
* a context value to be injected by an external provider.
36-
*/
37-
'context-request': ContextRequestEvent<Context<unknown, unknown>>
38-
}
35+
interface HTMLElementEventMap {
36+
/**
37+
* A 'context-request' event can be emitted by any element which desires
38+
* a context value to be injected by an external provider.
39+
*/
40+
'context-request': ContextRequestEvent<Context<unknown, unknown>>
41+
}
3942
}
4043

4144
/* === Constants === */
@@ -64,21 +67,50 @@ const CONTEXT_REQUEST = 'context-request'
6467
* @property {boolean} [subscribe=false] - whether to subscribe to context changes
6568
*/
6669
class ContextRequestEvent<T extends UnknownContext> extends Event {
67-
public constructor(
68-
public readonly context: T,
69-
public readonly callback: ContextCallback<ContextType<T>>,
70-
public readonly subscribe: boolean = false
71-
) {
72-
super(CONTEXT_REQUEST, { bubbles: true, composed: true })
73-
}
70+
public constructor(
71+
public readonly context: T,
72+
public readonly callback: ContextCallback<ContextType<T>>,
73+
public readonly subscribe: boolean = false
74+
) {
75+
super(CONTEXT_REQUEST, {
76+
bubbles: true,
77+
composed: true
78+
})
79+
}
7480
}
7581

7682
/**
77-
* A function which creates a Context value object
83+
* Initialize context provider / consumer for a UIElement instance
84+
*
85+
* @param {UIelement} host - UIElement instance to initialize context for
7886
*/
79-
const createContext = <V>(key: unknown) => key as Context<typeof key, V>
87+
const initContext = (host: UIElement) => {
88+
const proto = host.constructor as typeof UIElement
89+
90+
// context consumers
91+
const consumed = proto.consumedContexts || []
92+
for (const context of consumed)
93+
host.set(String(context), undefined, false)
94+
setTimeout(() => { // wait for all custom elements to be defined
95+
for (const context of consumed)
96+
host.dispatchEvent(new ContextRequestEvent(
97+
context,
98+
(value: unknown) => host.set(String(context), value)
99+
))
100+
})
101+
102+
// context providers
103+
const provided = proto.providedContexts || []
104+
if (!provided.length) return
105+
host.addEventListener(CONTEXT_REQUEST, (e: ContextRequestEvent<UnknownContext>) => {
106+
const { context, callback } = e
107+
if (!provided.includes(context) || !isFunction(callback)) return
108+
e.stopPropagation()
109+
callback(host.get(String(context)))
110+
})
111+
}
80112

81113
export {
82-
type Context, type UnknownContext,
83-
CONTEXT_REQUEST, ContextRequestEvent, createContext
114+
type Context, type UnknownContext,
115+
CONTEXT_REQUEST, ContextRequestEvent, initContext
84116
}

src/lib/event.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { effect } from '../cause-effect'
22
import type { UI, StateLike } from '../ui-element'
33

4+
/* === Exported Functions === */
5+
46
/**
57
* Add event listener to a target element
68
*

src/ui-element.ts

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { isFunction } from './core/is-type'
22
import { maybe } from './core/maybe'
33
import { type Signal, isState, isSignal, cause, effect } from './cause-effect'
4-
import { type UnknownContext, CONTEXT_REQUEST, ContextRequestEvent } from './core/context-request'
4+
import { type UnknownContext, initContext } from './core/context'
55
import { log, LOG_ERROR } from './core/log'
66
import { type StateMap, pass } from './lib/pass'
77
import { on, off, emit } from './lib/event'
@@ -99,26 +99,7 @@ class UIElement extends HTMLElement {
9999
* @since 0.7.0
100100
*/
101101
connectedCallback(): void {
102-
const proto = this.constructor as typeof UIElement
103-
104-
// context consumer
105-
const consumed = proto.consumedContexts || []
106-
for (const context of consumed) this.set(String(context), undefined)
107-
setTimeout(() => { // wait for all custom elements to be defined
108-
for (const context of consumed)
109-
this.dispatchEvent(new ContextRequestEvent(context, (value: unknown) =>
110-
this.set(String(context), value)))
111-
})
112-
113-
// context provider: listen to context request events
114-
const provided = proto.providedContexts || []
115-
if (!provided.length) return
116-
this.addEventListener(CONTEXT_REQUEST, (e: ContextRequestEvent<UnknownContext>) => {
117-
const { context, callback } = e
118-
if (!provided.includes(context) || !isFunction(callback)) return
119-
e.stopPropagation()
120-
callback(this.#states.get(String(context)))
121-
})
102+
initContext(this)
122103
}
123104

124105
disconnectedCallback(): void {}

types/core/context-request.d.ts renamed to types/core/context.d.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { UIElement } from "../ui-element";
12
/** @see https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/context.md */
23
/**
34
* A context key.
@@ -58,7 +59,9 @@ declare class ContextRequestEvent<T extends UnknownContext> extends Event {
5859
constructor(context: T, callback: ContextCallback<ContextType<T>>, subscribe?: boolean);
5960
}
6061
/**
61-
* A function which creates a Context value object
62+
* Initialize context provider / consumer for a UIElement instance
63+
*
64+
* @param {UIelement} host - UIElement instance to initialize context for
6265
*/
63-
declare const createContext: <V>(key: unknown) => Context<typeof key, V>;
64-
export { type Context, type UnknownContext, CONTEXT_REQUEST, ContextRequestEvent, createContext };
66+
declare const initContext: (host: UIElement) => void;
67+
export { type Context, type UnknownContext, CONTEXT_REQUEST, ContextRequestEvent, initContext };

types/core/ui.d.ts

Lines changed: 0 additions & 17 deletions
This file was deleted.

types/ui-element.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { maybe } from './core/maybe';
22
import { type Signal, effect } from './cause-effect';
3-
import { type UnknownContext } from './core/context-request';
3+
import { type UnknownContext } from './core/context';
44
import { log } from './core/log';
55
import { type StateMap, pass } from './lib/pass';
66
import { on, off, emit } from './lib/event';

0 commit comments

Comments
 (0)