11// === exports =======================================================
22
33// functions and singletons
4- export {
5- component ,
6- createCtx ,
7- defineProvider ,
8- elem ,
9- intercept ,
10- prop ,
11- setMethods ,
12- Attrs
13- }
4+ export { component , createCtx , elem , intercept , prop , setMethods , Attrs }
145
156// types
167export { Context , Ctrl , MethodsOf }
@@ -76,10 +67,10 @@ type Ctrl = {
7667
7768type InterceptFn = ( ctrl : Ctrl , next : ( ) => void ) => void
7869
79- type Context < T > = {
70+ type Context < T > = Readonly < {
8071 kind : 'context'
8172 defaultValue : T
82- }
73+ } >
8374
8475// === decorators (all public) =======================================
8576
@@ -91,10 +82,29 @@ function elem<E extends Component, C>(params: {
9182 }
9283 styles ?: string | string [ ] | ( ( ) => string | string [ ] )
9384 uses ?: any [ ]
94- } ) {
85+ } ) : ( clazz : new ( ) => E ) => void
86+
87+ function elem < T , E extends Component & { value ?: T } > ( params : {
88+ tag : `${string } -provider`
89+ ctx : Context < T >
90+ } ) : ( clazz : new ( ) => E ) => void
91+
92+ function elem < E extends Component > ( params : any ) {
9593 return ( clazz : new ( ) => E ) : void => {
9694 definePropValue ( clazz , 'tagName' , params . tag )
9795
96+ if ( params . ctx ) {
97+ const ctx = params . ctx
98+ console . log ( params )
99+ params = {
100+ tag : params . tag ,
101+ impl : {
102+ init : ( self : E , ctrl : Ctrl ) => initProvider ( self , ctrl , ctx ) ,
103+ patch : ( ) => { }
104+ }
105+ }
106+ }
107+
98108 let elemConfig = elemConfigByClass . get ( clazz )
99109
100110 if ( ! elemConfig ) {
@@ -188,9 +198,10 @@ class BaseElement extends HTMLElement {
188198
189199 constructor ( ) {
190200 super ( )
191- const { init, patch } = elemConfigByClass . get ( this . constructor ) ! . impl
192201
193- let styles = elemConfigByClass . get ( this . constructor ) ! . styles
202+ const elemConfig = elemConfigByClass . get ( this . constructor ) !
203+ const { init, patch } = elemConfig . impl
204+ let styles = elemConfig . styles
194205
195206 if ( typeof styles !== 'string' ) {
196207 styles = typeof styles === 'function' ? styles ( ) : styles
@@ -207,6 +218,7 @@ class BaseElement extends HTMLElement {
207218 }
208219
209220 const stylesElement = document . createElement ( 'span' )
221+ stylesElement . setAttribute ( 'data-role' , 'styles' )
210222
211223 if ( styles ) {
212224 const styleElem = document . createElement ( 'style' )
@@ -215,8 +227,9 @@ class BaseElement extends HTMLElement {
215227 }
216228
217229 const contentElement = document . createElement ( 'span' )
230+ contentElement . setAttribute ( 'data-role' , 'content' )
218231 this . attachShadow ( { mode : 'open' } )
219- contentElement . append ( document . createElement ( 'span' ) )
232+ // contentElement.append(document.createElement('span'))
220233 this . shadowRoot ! . append ( stylesElement , contentElement )
221234
222235 let initialized = false
@@ -510,64 +523,39 @@ function createCtx<T>(defaultValue?: T): Context<T> {
510523 } )
511524}
512525
513- function defineProvider < T > (
514- tagName : string ,
515- ctx : Context < T >
516- ) : { new ( ) : HTMLElement & { value : T | undefined } } {
517- const eventName = `$$context$$`
518-
519- class CtxProviderElement extends HTMLElement {
520- private __value ?: T = undefined
521- private __subscribers : ( ( value : T ) => void ) [ ] = [ ]
522- private __cleanup : ( ( ) => void ) | null = null
526+ function initProvider ( self : any , ctrl : Ctrl , ctx : Context < any > ) : ( ) => null {
527+ const subscribers = new Set < any > ( ) // TODO
528+ let cleanup : any = null // TODO
529+ let value = ctx . defaultValue
523530
524- constructor ( ) {
525- super ( )
526- this . attachShadow ( { mode : 'open' } )
531+ const eventListener = ( ev : any ) => {
532+ if ( ev . detail . context !== ctx ) {
533+ return
527534 }
528535
529- get value ( ) : T | undefined {
530- return this . __value
531- }
532-
533- set value ( val : T | undefined ) {
534- if ( val !== this . __value ) {
535- this . __value = val
536- this . __subscribers . forEach ( ( subscriber ) => subscriber ( val ! ) )
537- }
538- }
539-
540- connectedCallback ( ) {
541- this . shadowRoot ! . innerHTML = '<slot></slot>'
536+ const callback = ev . detail . callback
542537
543- const eventListener = ( ev : any ) => {
544- if ( ev . detail . context !== ctx ) {
545- return
546- }
538+ ev . stopPropagation ( )
539+ subscribers . add ( callback )
547540
548- ev . stopPropagation ( )
549- this . __subscribers . push ( ev . detail . callback )
541+ ev . detail . cancelled . then ( ( ) => {
542+ subscribers . delete ( callback )
543+ } )
544+ }
550545
551- ev . detail . cancelled . then ( ( ) => {
552- this . __subscribers . splice (
553- this . __subscribers . indexOf ( ev . detail . callback ) ,
554- 1
555- )
556- } )
557- }
546+ self . addEventListener ( '$$context$$' , eventListener )
558547
559- this . addEventListener ( eventName , eventListener )
560- this . __cleanup = ( ) => this . removeEventListener ( eventName , eventListener )
561- }
548+ cleanup = ( ) => self . removeEventListener ( '$$context$$' , eventListener )
562549
563- disconnectCallback ( ) {
564- this . __subscribers . length === 0
565- this . __cleanup ! ( )
566- this . __cleanup = null
550+ ctrl . afterUpdate ( ( ) => {
551+ if ( self . value !== value ) {
552+ value = self . value
553+ subscribers . forEach ( ( subscriber ) => subscriber ( value ) )
567554 }
568- }
555+ } )
569556
570- registerElement ( tagName , CtxProviderElement )
557+ const contentContainer = self . shadowRoot . lastChild
558+ contentContainer . appendChild ( document . createElement ( 'slot' ) )
571559
572- return CtxProviderElement
560+ return ( ) => null
573561}
0 commit comments