From 28d25e68570254856e5b1f986047e76395a3a832 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Thu, 28 Sep 2023 18:35:50 +0300 Subject: [PATCH 01/21] $mol_form_draft: array support --- form/draft/draft.view.ts | 55 ++++++++++++++++++++++++++++++--------- infinite/infinite.view.ts | 5 ++++ select/list/list.view.ts | 2 +- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 025fea04a42..baf2ae3fc68 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -1,33 +1,64 @@ namespace $.$$ { + type Primitive = string | number | boolean + + type Value = readonly Primitive[] | Primitive + type Model = Record Value> + + function norm_string(val: unknown) { + return String(val) ?? '' + } + + function norm_number(val: unknown) { + return Number(val) ?? 0 + } + + function norm_bool(val: unknown) { + return Boolean(val) ?? false + } + /** * @see https://mol.hyoo.ru/#!section=demos/demo=mol_form_draft_demo */ export class $mol_form_draft extends $.$mol_form_draft { - + @ $mol_mem_key + value_arr_str( field: string, next? : readonly string[] | null ) { + return this.value( field, next )?.map(norm_string) ?? [] + } + + @ $mol_mem_key + value_arr_num( field: string, next? : readonly number[] | null ) { + return this.value( field, next )?.map(norm_number) ?? [] + } + + @ $mol_mem_key + value_arr_bool( field: string, next? : readonly boolean[] | null ) { + return this.value( field, next )?.map(norm_bool) ?? [] + } + @ $mol_mem_key value_str( field: string, next? : string | null ) { - return String( this.value( field, next ) ?? '' ) + return norm_string( this.value( field, next ) ) } @ $mol_mem_key value_numb( field: string, next? : boolean | null ) { - return Number( this.value( field, next ) ?? 0 ) + return norm_number( this.value( field, next ) ) } @ $mol_mem_key value_bool( field: string, next? : boolean | null ) { - return Boolean( this.value( field, next ) ?? false ) + return norm_bool( this.value( field, next ) ) } @ $mol_mem_key - value( field: string, next?: string | number | boolean | null ) { - return this.state( next?.valueOf && { ... this.state(), [ field ]: next } )[ field ] - ?? ( this.model() as any )[ field ]() + value( field: string, next?: T | null ) { + return this.state( next?.valueOf && { ... this.state(), [ field ]: next } )[ field ] as T | undefined + ?? ( this.model() as unknown as Model )[ field ]() as T } @ $mol_mem - state( next?: Record< string, string | number | boolean | null > | null ) { + state( next?: Record< string, Value | null > | null ) { return $mol_state_local.value( `${ this }.state()`, next ) ?? {} } @@ -39,20 +70,20 @@ namespace $.$$ { submit_allowed() { return this.changed() && super.submit_allowed() } - + @ $mol_action submit( next? : Event ) { - const model = this.model() + const model = this.model() as unknown as Model for( let [ field, next ] of Object.entries( this.state() ) ) { - const prev = ( model as any )[ field ]() + const prev = model[ field ]() switch( typeof prev ) { case 'boolean': next = String( next ) === 'true'; break case 'number': next = Number( next ); break case 'string': next = String( next ); break } - ;( model as any )[ field ]( next ) + model[ field ]( next ) } this.state( null ) diff --git a/infinite/infinite.view.ts b/infinite/infinite.view.ts index 929b3ac6fff..c814adfdc49 100644 --- a/infinite/infinite.view.ts +++ b/infinite/infinite.view.ts @@ -60,7 +60,12 @@ namespace $.$$ { this.After( ids.at(-1) ?? null ), ] + } tmp_after_add(criteria: Criteria, item: Item) { + const chunk = this.nearest_chunk(criteria) + if (! chunk) return + this.after(criteria, [ ...chunk, item ]) } + } diff --git a/select/list/list.view.ts b/select/list/list.view.ts index a7bdb457ef4..0895f88edc8 100644 --- a/select/list/list.view.ts +++ b/select/list/list.view.ts @@ -6,7 +6,7 @@ namespace $.$$ { */ export class $mol_select_list extends $.$mol_select_list { - override value( val? : string[] ) { + override value( val? : readonly string[] ) { return super.value( val ) as readonly string[] } From 57ec861b3fbce0eb66c1c030f52de8a10b1e4de4 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Thu, 28 Sep 2023 18:36:56 +0300 Subject: [PATCH 02/21] $mol_infinite: remove garbage --- infinite/infinite.view.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/infinite/infinite.view.ts b/infinite/infinite.view.ts index c814adfdc49..929b3ac6fff 100644 --- a/infinite/infinite.view.ts +++ b/infinite/infinite.view.ts @@ -60,12 +60,7 @@ namespace $.$$ { this.After( ids.at(-1) ?? null ), ] - } tmp_after_add(criteria: Criteria, item: Item) { - const chunk = this.nearest_chunk(criteria) - if (! chunk) return - this.after(criteria, [ ...chunk, item ]) } - } From 6481fb2db5a4941e4e9b780b4da143db924ddca0 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Thu, 28 Sep 2023 23:00:12 +0300 Subject: [PATCH 03/21] $mol_form_draft, rec --- form/draft/draft.view.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index baf2ae3fc68..97d9b49f2b6 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -2,7 +2,7 @@ namespace $.$$ { type Primitive = string | number | boolean - type Value = readonly Primitive[] | Primitive + type Value = readonly Primitive[] | Primitive | Record type Model = Record Value> function norm_string(val: unknown) { @@ -27,13 +27,8 @@ namespace $.$$ { } @ $mol_mem_key - value_arr_num( field: string, next? : readonly number[] | null ) { - return this.value( field, next )?.map(norm_number) ?? [] - } - - @ $mol_mem_key - value_arr_bool( field: string, next? : readonly boolean[] | null ) { - return this.value( field, next )?.map(norm_bool) ?? [] + value_rec_str( field: string, next? : Record | null ) { + return this.value( field, next ) ?? {} } @ $mol_mem_key From a010359c96fcad82eb3e385cdef536106fcc8600 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 09:35:41 +0300 Subject: [PATCH 04/21] $mol_form_draft select list demo --- form/draft/demo/demo.view.tree | 16 ++++++++++++++++ form/draft/demo/demo.view.ts | 1 + 2 files changed, 17 insertions(+) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index e5c964ae24f..b50701f871a 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -3,6 +3,7 @@ $mol_form_draft_demo_article $mol_object2 type? \ adult? false content? \ + friends? /string $mol_form_draft_demo $mol_example title \Article draft form demo @@ -19,6 +20,7 @@ $mol_form_draft_demo $mol_example submit? => publish? submit_allowed => publish_allowed value_str*? => value_str*? + value_arr_str*? => value_arr_str*? changed => changed form_fields / <= Title_field $mol_form_field @@ -54,12 +56,26 @@ $mol_form_draft_demo $mol_example Content <= Content $mol_textarea hint \Long long story.. value? <=> value_str*content? + <= Friends_field $mol_form_field + name \Friends + Content <= Friends $mol_select_list + dictionary <= friends_suggestions * + jocker \Jocker + harley \Harley Quinn + penguin \Penguin + riddler \Riddler + bane \Bane + freeze \Mister Freeze + clay \Clayface + mask \Black Mask + value? <=> value_arr_str*friends? body <= form_body / <= Title_field <= Config $mol_form_group sub / <= Adult_field <= Type_field <= Content_field + <= Friends_field buttons / <= Publish $mol_button_major title \Publish diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index 16c4c604b76..bc77cff0e46 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -8,6 +8,7 @@ namespace $.$$ { this.Title_field(), this.Config(), ... this.value_str( 'type' ) ? [ this.Content_field() ] : [], + this.Friends_field(), ] } From 0389d69e1a4515f15f9d60081a932e85ce4c0b31 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 12:08:28 +0300 Subject: [PATCH 05/21] $mol_form_draft: record of bool support, batching friendly --- check/list/list.view.tree | 1 + check/list/list.view.ts | 14 ++++++++++++++ form/draft/demo/demo.view.tree | 10 ++++++++++ form/draft/demo/demo.view.ts | 1 + form/draft/draft.view.ts | 35 ++++++++++++++++++++++++---------- 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/check/list/list.view.tree b/check/list/list.view.tree index a79c5591e57..14dc9ec2c60 100644 --- a/check/list/list.view.tree +++ b/check/list/list.view.tree @@ -1,4 +1,5 @@ $mol_check_list $mol_view + options_checked * Option* $mol_check checked? <=> option_checked*? false label <= option_label* / diff --git a/check/list/list.view.ts b/check/list/list.view.ts index d338b08fce1..40d9b854a62 100644 --- a/check/list/list.view.ts +++ b/check/list/list.view.ts @@ -10,6 +10,20 @@ namespace $.$$ { return {} } + override options_checked(next?: Record) { + return next ?? {} + } + + override option_checked(id: string, next?: boolean | null) { + const prev = this.options_checked() + if (next === undefined) return prev[id] + + const next_rec = { ... prev, [id]: next } as Record + if (next === null) delete next_rec[id] + + return this.options_checked(next_rec)[id] + } + @ $mol_mem keys(): readonly string[] { return Object.keys( this.options() ) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index b50701f871a..9015e7a88ac 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -4,6 +4,7 @@ $mol_form_draft_demo_article $mol_object2 adult? false content? \ friends? /string + hobbies? * $mol_form_draft_demo $mol_example title \Article draft form demo @@ -21,6 +22,7 @@ $mol_form_draft_demo $mol_example submit_allowed => publish_allowed value_str*? => value_str*? value_arr_str*? => value_arr_str*? + value_rec_bool*? => value_rec_bool*? changed => changed form_fields / <= Title_field $mol_form_field @@ -56,6 +58,14 @@ $mol_form_draft_demo $mol_example Content <= Content $mol_textarea hint \Long long story.. value? <=> value_str*content? + <= Hobbies_field $mol_form_field + name \Hobbies + Content <= Hobbies $mol_check_list + options_checked? <=> value_rec_bool*hobbies? + options * + programming \Programming + bikinkg \Biking + fishing \Fishing <= Friends_field $mol_form_field name \Friends Content <= Friends $mol_select_list diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index bc77cff0e46..230eede1c54 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -7,6 +7,7 @@ namespace $.$$ { return [ this.Title_field(), this.Config(), + this.Hobbies_field(), ... this.value_str( 'type' ) ? [ this.Content_field() ] : [], this.Friends_field(), ] diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 97d9b49f2b6..2aacd89d06a 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -17,6 +17,16 @@ namespace $.$$ { return Boolean(val) ?? false } + function normalize_val(prev: Value, next: Value | null) { + switch( typeof prev ) { + case 'boolean': return String( next ) === 'true' + case 'number': return Number( next ) + case 'string': return String( next ) + } + + return next + } + /** * @see https://mol.hyoo.ru/#!section=demos/demo=mol_form_draft_demo */ @@ -27,7 +37,7 @@ namespace $.$$ { } @ $mol_mem_key - value_rec_str( field: string, next? : Record | null ) { + value_rec_bool( field: string, next? : Record | null ) { return this.value( field, next ) ?? {} } @@ -70,16 +80,21 @@ namespace $.$$ { submit( next? : Event ) { const model = this.model() as unknown as Model - - for( let [ field, next ] of Object.entries( this.state() ) ) { - const prev = model[ field ]() - switch( typeof prev ) { - case 'boolean': next = String( next ) === 'true'; break - case 'number': next = Number( next ); break - case 'string': next = String( next ); break + + const tasks = Object.entries( this.state() ).map( + ([ field, next ]) => () => { + const prev = model[ field ]() + + return { + field, + next: normalize_val(prev, next) + } } - model[ field ]( next ) - } + ) + + const normalized = $mol_wire_race(...tasks) + + $mol_wire_race(...normalized.map(({ field, next }) => () => model[ field ]( next ))) this.state( null ) From 91575b72d13e5825d9b2eddb1d5c52d876db7c39 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 13:58:15 +0300 Subject: [PATCH 06/21] $mol_select_list pass filter_pattern and hint --- select/list/list.view.tree | 2 ++ select/select.view.tree | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/select/list/list.view.tree b/select/list/list.view.tree index cf74546842b..ef298b530b4 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -15,5 +15,7 @@ $mol_select_list $mol_view option_label* <= option_title* \ trigger_enabled <= pick_enabled <= enabled true hint <= pick_hint @ \Add.. + filter_pattern? <=> filter_pattern? \ + filter_hint <= filter_hint @ \Filter.. Trigger_icon <= Pick_icon $mol_icon_plus ^ badges_list diff --git a/select/select.view.tree b/select/select.view.tree index d2d94a76c00..87aeaf0a208 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -26,7 +26,7 @@ $mol_select $mol_pick rows <= menu_content /$mol_view Filter $mol_string value? <=> filter_pattern? \ - hint @ \Filter.. + hint <= filter_hint @ \Filter.. submit?event <=> submit?event null enabled <= enabled true Trigger_icon $mol_icon_dots_vertical From 1454905161d2ceac01fed392bbe128bb75841798 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 15:49:46 +0300 Subject: [PATCH 07/21] $mol_select_list, badge index to id --- select/list/list.view.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/select/list/list.view.ts b/select/list/list.view.ts index 0895f88edc8..2dc33859a48 100644 --- a/select/list/list.view.ts +++ b/select/list/list.view.ts @@ -46,8 +46,8 @@ namespace $.$$ { return value == null ? key : value } - override badge_title( index: number ) { - return this.option_title( this.value()[ index ] ) + override badge_title( key: string ) { + return this.option_title( key ) } @ $mol_mem @@ -57,7 +57,7 @@ namespace $.$$ { override Badges() { return this.value() - .map( ( _, index )=> this.Badge( index ) ) + .map( id => this.Badge( id ) ) .reverse() } @@ -67,12 +67,8 @@ namespace $.$$ { } @ $mol_action - override remove( index: number ) { - const value = this.value() - this.value([ - ... value.slice( 0 , index ), - ... value.slice( index + 1 ), - ]) + override remove( key: string ) { + this.value(this.value().filter(id => id !== key)) } } From 9faa4eccfdcf8bbf3e7bb1eaf90db8e4a5f32da5 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 15:53:36 +0300 Subject: [PATCH 08/21] $mol_select_list, review fixes --- check/list/list.view.tree | 2 +- check/list/list.view.ts | 8 ++++---- form/draft/demo/demo.view.tree | 6 +++--- form/draft/draft.view.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/check/list/list.view.tree b/check/list/list.view.tree index 14dc9ec2c60..34eaea9d37a 100644 --- a/check/list/list.view.tree +++ b/check/list/list.view.tree @@ -1,5 +1,5 @@ $mol_check_list $mol_view - options_checked * + dictionary_checked * Option* $mol_check checked? <=> option_checked*? false label <= option_label* / diff --git a/check/list/list.view.ts b/check/list/list.view.ts index 40d9b854a62..d6399ebfaed 100644 --- a/check/list/list.view.ts +++ b/check/list/list.view.ts @@ -10,18 +10,18 @@ namespace $.$$ { return {} } - override options_checked(next?: Record) { + override dictionary_checked(next?: Record) { return next ?? {} } override option_checked(id: string, next?: boolean | null) { - const prev = this.options_checked() - if (next === undefined) return prev[id] + const prev = this.dictionary_checked() + if (next === undefined) return prev[id] ?? null const next_rec = { ... prev, [id]: next } as Record if (next === null) delete next_rec[id] - return this.options_checked(next_rec)[id] + return this.dictionary_checked(next_rec)[id] ?? null } @ $mol_mem diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index 9015e7a88ac..52826111af5 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -21,7 +21,7 @@ $mol_form_draft_demo $mol_example submit? => publish? submit_allowed => publish_allowed value_str*? => value_str*? - value_arr_str*? => value_arr_str*? + list_string*? => list_string*? value_rec_bool*? => value_rec_bool*? changed => changed form_fields / @@ -61,7 +61,7 @@ $mol_form_draft_demo $mol_example <= Hobbies_field $mol_form_field name \Hobbies Content <= Hobbies $mol_check_list - options_checked? <=> value_rec_bool*hobbies? + dictionary_checked? <=> value_rec_bool*hobbies? options * programming \Programming bikinkg \Biking @@ -78,7 +78,7 @@ $mol_form_draft_demo $mol_example freeze \Mister Freeze clay \Clayface mask \Black Mask - value? <=> value_arr_str*friends? + value? <=> list_string*friends? body <= form_body / <= Title_field <= Config $mol_form_group sub / diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 2aacd89d06a..f3cf5c4f154 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -32,7 +32,7 @@ namespace $.$$ { */ export class $mol_form_draft extends $.$mol_form_draft { @ $mol_mem_key - value_arr_str( field: string, next? : readonly string[] | null ) { + list_string( field: string, next? : readonly string[] | null ) { return this.value( field, next )?.map(norm_string) ?? [] } From 7df44be8e56943e58afe33ad287e689b89a09603 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 17:36:15 +0300 Subject: [PATCH 09/21] $mol_select_list, auto clean disable, filter from $mol_string to $mol_search --- select/list/list.view.tree | 1 + select/list/list.view.ts | 2 +- select/select.view.tree | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/select/list/list.view.tree b/select/list/list.view.tree index ef298b530b4..e9cf2339dea 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -7,6 +7,7 @@ $mol_select_list $mol_view click?event <=> remove*?event null hint <= badge_hint @ \Drop enabled <= drop_enabled <= enabled true + filter_auto_clean true sub /$mol_view <= Pick $mol_select align_hor <= align_hor \right diff --git a/select/list/list.view.ts b/select/list/list.view.ts index 2dc33859a48..919afea4b9e 100644 --- a/select/list/list.view.ts +++ b/select/list/list.view.ts @@ -18,7 +18,7 @@ namespace $.$$ { new $mol_after_frame(()=> { if( !this.pick_enabled() ) return - this.Pick().filter_pattern( '' ) + if (this.filter_auto_clean()) this.Pick().filter_pattern( '' ) this.Pick().Trigger().focused( true ) this.Pick().open() }) diff --git a/select/select.view.tree b/select/select.view.tree index 87aeaf0a208..8f8d01f1901 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -24,8 +24,8 @@ $mol_select $mol_pick <= Bubble_pane $mol_scroll sub / <= Menu $mol_list rows <= menu_content /$mol_view - Filter $mol_string - value? <=> filter_pattern? \ + Filter $mol_search + query? <=> filter_pattern? \ hint <= filter_hint @ \Filter.. submit?event <=> submit?event null enabled <= enabled true From 4ff91b1e9bbb4dc99fac6505d6f9d789d689a4b8 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 20:06:18 +0300 Subject: [PATCH 10/21] $mol_select_list, $mol_select expose bubble_minimal_width --- select/list/list.view.tree | 2 ++ select/select.view.tree | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/select/list/list.view.tree b/select/list/list.view.tree index e9cf2339dea..e7847975ed0 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -10,6 +10,8 @@ $mol_select_list $mol_view filter_auto_clean true sub /$mol_view <= Pick $mol_select + bubble_minimal_width <= bubble_minimal_width 200 + bubble_minimal_height <= bubble_minimal_height 200 align_hor <= align_hor \right options <= options_pickable <= options /string value? <=> pick? \ diff --git a/select/select.view.tree b/select/select.view.tree index 8f8d01f1901..72fa2033e8a 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -21,9 +21,12 @@ $mol_select $mol_pick hint @ \Pick.. bubble_content / <= Filter - <= Bubble_pane $mol_scroll sub / - <= Menu $mol_list - rows <= menu_content /$mol_view + <= Bubble_pane $mol_scroll + sub / + <= Menu $mol_list + minimal_width <= bubble_minimal_width 200 + minimal_height <= bubble_minimal_height 200 + rows <= menu_content /$mol_view Filter $mol_search query? <=> filter_pattern? \ hint <= filter_hint @ \Filter.. From be657ecd490a4278194704c9b49ae5e8cf441441 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 20:56:29 +0300 Subject: [PATCH 11/21] $mol_form_draft improve changed, reset button --- form/draft/demo/demo.view.tree | 5 +++++ form/draft/draft.view.ts | 34 ++++++++++++++++++++++++---------- select/list/list.view.tree | 2 +- select/select.view.tree | 2 +- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index 52826111af5..e421673126c 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -24,6 +24,7 @@ $mol_form_draft_demo $mol_example list_string*? => list_string*? value_rec_bool*? => value_rec_bool*? changed => changed + reset? => reset? form_fields / <= Title_field $mol_form_field name \Title @@ -93,6 +94,10 @@ $mol_form_draft_demo $mol_example enabled <= publish_allowed <= Result $mol_status message <= result? \ + <= Reset $mol_button_minor + title \Сбросить + click? <=> reset? + enabled <= changed tags / \$mol_form_field \$mol_button diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index f3cf5c4f154..86ae5da424c 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -55,11 +55,23 @@ namespace $.$$ { value_bool( field: string, next? : boolean | null ) { return norm_bool( this.value( field, next ) ) } - + + model_pick(field: string, next?: Value | null) { + return (this.model() as unknown as Model)[field](next) + } + + state_pick(field: string, next?: Value | null) { + return this.state( next === undefined ? next : { ... this.state(), [ field ]: next } )[ field ] + } + @ $mol_mem_key - value( field: string, next?: T | null ) { - return this.state( next?.valueOf && { ... this.state(), [ field ]: next } )[ field ] as T | undefined - ?? ( this.model() as unknown as Model )[ field ]() as T + value( field: string, next?: T | null ): T { + return this.state_pick(field, next) as T ?? this.model_pick(field) + } + + @ $mol_mem_key + value_changed(field: string) { + return ! $mol_compare_deep(this.state_pick(field), this.model_pick(field)) } @ $mol_mem @@ -69,21 +81,23 @@ namespace $.$$ { @ $mol_mem changed() { - return Object.keys( this.state() ).length > 0 + return Object.keys(this.state()).some(field => this.value_changed(field)) } submit_allowed() { return this.changed() && super.submit_allowed() } + reset() { + this.state(null) + } + @ $mol_action submit( next? : Event ) { - const model = this.model() as unknown as Model - const tasks = Object.entries( this.state() ).map( ([ field, next ]) => () => { - const prev = model[ field ]() + const prev = this.model_pick(field) return { field, @@ -94,9 +108,9 @@ namespace $.$$ { const normalized = $mol_wire_race(...tasks) - $mol_wire_race(...normalized.map(({ field, next }) => () => model[ field ]( next ))) + $mol_wire_race(...normalized.map(({ field, next }) => () => this.model_pick( field, next ))) - this.state( null ) + this.reset() } diff --git a/select/list/list.view.tree b/select/list/list.view.tree index e7847975ed0..87a9f61ac73 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -11,7 +11,7 @@ $mol_select_list $mol_view sub /$mol_view <= Pick $mol_select bubble_minimal_width <= bubble_minimal_width 200 - bubble_minimal_height <= bubble_minimal_height 200 + bubble_minimal_height <= bubble_minimal_height 30 align_hor <= align_hor \right options <= options_pickable <= options /string value? <=> pick? \ diff --git a/select/select.view.tree b/select/select.view.tree index 72fa2033e8a..5ab72912581 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -25,7 +25,7 @@ $mol_select $mol_pick sub / <= Menu $mol_list minimal_width <= bubble_minimal_width 200 - minimal_height <= bubble_minimal_height 200 + minimal_height <= bubble_minimal_height 30 rows <= menu_content /$mol_view Filter $mol_search query? <=> filter_pattern? \ From a3e3580a5c589c08f82fe7394c8637c0dddac1ff Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 21:41:19 +0300 Subject: [PATCH 12/21] $mol_form_draft fix changed for array and records --- form/draft/draft.view.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 86ae5da424c..87a91fd203c 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -6,15 +6,15 @@ namespace $.$$ { type Model = Record Value> function norm_string(val: unknown) { - return String(val) ?? '' + return String(val ?? '') } function norm_number(val: unknown) { - return Number(val) ?? 0 + return Number(val ?? 0) } function norm_bool(val: unknown) { - return Boolean(val) ?? false + return Boolean(val ?? false) } function normalize_val(prev: Value, next: Value | null) { @@ -38,7 +38,17 @@ namespace $.$$ { @ $mol_mem_key value_rec_bool( field: string, next? : Record | null ) { - return this.value( field, next ) ?? {} + if (next) { + const prev = this.model_pick(field) as Record + const normalized = {} as typeof next + for (const key in next) { + if (next[key] || key in prev ) normalized[key] = next[key] + } + + return this.value( field, normalized ) ?? {} + } + + return this.value( field ) ?? {} } @ $mol_mem_key @@ -66,12 +76,17 @@ namespace $.$$ { @ $mol_mem_key value( field: string, next?: T | null ): T { + if (Array.isArray(next) && next.length === 0 && ! this.model_pick(field)) next = null return this.state_pick(field, next) as T ?? this.model_pick(field) } @ $mol_mem_key value_changed(field: string) { - return ! $mol_compare_deep(this.state_pick(field), this.model_pick(field)) + const next = this.state_pick(field) + const prev = this.model_pick(field) + const next_norm = normalize_val(prev, next) + + return ! $mol_compare_deep(next_norm, prev) } @ $mol_mem From 8db37360a4e6803c59d95f6285f3773433def23c Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 22:58:36 +0300 Subject: [PATCH 13/21] $mol_form_draft fix types --- form/draft/draft.view.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 87a91fd203c..092e90c02c5 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -37,7 +37,7 @@ namespace $.$$ { } @ $mol_mem_key - value_rec_bool( field: string, next? : Record | null ) { + value_rec_bool( field: string, next? : Record | null ): Record { if (next) { const prev = this.model_pick(field) as Record const normalized = {} as typeof next @@ -103,7 +103,7 @@ namespace $.$$ { return this.changed() && super.submit_allowed() } - reset() { + reset(next?: unknown) { this.state(null) } From 801c99be03b5f5a287e0af7b76ea592ff6dbde81 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Fri, 29 Sep 2023 23:04:12 +0300 Subject: [PATCH 14/21] $mol_form_draft review fix 2 --- form/draft/demo/demo.view.tree | 4 ++-- form/draft/draft.view.ts | 2 +- select/list/list.view.tree | 2 -- select/select.view.tree | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index e421673126c..4208f7bf48e 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -22,7 +22,7 @@ $mol_form_draft_demo $mol_example submit_allowed => publish_allowed value_str*? => value_str*? list_string*? => list_string*? - value_rec_bool*? => value_rec_bool*? + dictionary_bool*? => dictionary_bool*? changed => changed reset? => reset? form_fields / @@ -62,7 +62,7 @@ $mol_form_draft_demo $mol_example <= Hobbies_field $mol_form_field name \Hobbies Content <= Hobbies $mol_check_list - dictionary_checked? <=> value_rec_bool*hobbies? + dictionary_checked? <=> dictionary_bool*hobbies? options * programming \Programming bikinkg \Biking diff --git a/form/draft/draft.view.ts b/form/draft/draft.view.ts index 092e90c02c5..07e3be0634d 100644 --- a/form/draft/draft.view.ts +++ b/form/draft/draft.view.ts @@ -37,7 +37,7 @@ namespace $.$$ { } @ $mol_mem_key - value_rec_bool( field: string, next? : Record | null ): Record { + dictionary_bool( field: string, next? : Record | null ): Record { if (next) { const prev = this.model_pick(field) as Record const normalized = {} as typeof next diff --git a/select/list/list.view.tree b/select/list/list.view.tree index 87a9f61ac73..e9cf2339dea 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -10,8 +10,6 @@ $mol_select_list $mol_view filter_auto_clean true sub /$mol_view <= Pick $mol_select - bubble_minimal_width <= bubble_minimal_width 200 - bubble_minimal_height <= bubble_minimal_height 30 align_hor <= align_hor \right options <= options_pickable <= options /string value? <=> pick? \ diff --git a/select/select.view.tree b/select/select.view.tree index 5ab72912581..450d4968916 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -24,8 +24,7 @@ $mol_select $mol_pick <= Bubble_pane $mol_scroll sub / <= Menu $mol_list - minimal_width <= bubble_minimal_width 200 - minimal_height <= bubble_minimal_height 30 + minimal_height 30 rows <= menu_content /$mol_view Filter $mol_search query? <=> filter_pattern? \ From adf2555824262692d3762030d60cc8dfdee7c628 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sat, 30 Sep 2023 20:45:43 +0300 Subject: [PATCH 15/21] $mol_select_list do not close --- form/draft/demo/demo.view.tree | 2 ++ form/draft/demo/demo.view.ts | 6 ++++++ select/list/list.view.tree | 3 ++- select/list/list.view.ts | 12 +++++------- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index 4208f7bf48e..eabc96b066a 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -70,6 +70,8 @@ $mol_form_draft_demo $mol_example <= Friends_field $mol_form_field name \Friends Content <= Friends $mol_select_list + pick_enabled true + showed => friends_showed dictionary <= friends_suggestions * jocker \Jocker harley \Harley Quinn diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index 230eede1c54..2943b374c0b 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -44,6 +44,12 @@ namespace $.$$ { super.publish() this.result( this.message_done() ) } + + override friends_suggestions() { + if (! this.friends_showed()) return {} + this.$.$mol_wait_timeout(1000) + return super.friends_suggestions() + } } } diff --git a/select/list/list.view.tree b/select/list/list.view.tree index e9cf2339dea..74e747c4764 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -7,9 +7,10 @@ $mol_select_list $mol_view click?event <=> remove*?event null hint <= badge_hint @ \Drop enabled <= drop_enabled <= enabled true - filter_auto_clean true sub /$mol_view <= Pick $mol_select + showed? <=> showed? false + event_select*? <=> event_select*? null align_hor <= align_hor \right options <= options_pickable <= options /string value? <=> pick? \ diff --git a/select/list/list.view.ts b/select/list/list.view.ts index 919afea4b9e..40222b4764d 100644 --- a/select/list/list.view.ts +++ b/select/list/list.view.ts @@ -16,16 +16,14 @@ namespace $.$$ { if( !key ) return '' this.value([ ... this.value() , key ]) - new $mol_after_frame(()=> { - if( !this.pick_enabled() ) return - if (this.filter_auto_clean()) this.Pick().filter_pattern( '' ) - this.Pick().Trigger().focused( true ) - this.Pick().open() - }) - return '' } + override event_select( id : string , event? : MouseEvent ) { + event?.preventDefault() + this.pick( id ) + } + @ $mol_mem override options() { return Object.keys( this.dictionary() ) as readonly string[] From 554efcc0b7de0ff5d3c0220458e8c290b273b276 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sat, 30 Sep 2023 20:47:57 +0300 Subject: [PATCH 16/21] $mol_form_draft added mem decorator --- form/draft/demo/demo.view.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index 2943b374c0b..1a5048df9e2 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -45,9 +45,10 @@ namespace $.$$ { this.result( this.message_done() ) } + @ $mol_mem override friends_suggestions() { if (! this.friends_showed()) return {} - this.$.$mol_wait_timeout(1000) + this.$.$mol_wait_timeout(500) return super.friends_suggestions() } From 64931fd0ebfb1c6010ae49e1c32e484d472592aa Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sat, 30 Sep 2023 20:55:56 +0300 Subject: [PATCH 17/21] $mol_select more min-height --- list/list.view.css | 2 +- select/select.view.tree | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/list/list.view.css b/list/list.view.css index 0c0ddfcd83d..f10cc16accf 100644 --- a/list/list.view.css +++ b/list/list.view.css @@ -8,7 +8,7 @@ align-items: stretch; align-content: stretch; */ transition: none; - min-height: .5rem; + min-height: 2rem; } [mol_list_gap_before] , diff --git a/select/select.view.tree b/select/select.view.tree index 450d4968916..67c675ccac3 100644 --- a/select/select.view.tree +++ b/select/select.view.tree @@ -24,7 +24,6 @@ $mol_select $mol_pick <= Bubble_pane $mol_scroll sub / <= Menu $mol_list - minimal_height 30 rows <= menu_content /$mol_view Filter $mol_search query? <=> filter_pattern? \ From 3948bb676b2fbba93ed30976b98f426d91a558c8 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sat, 30 Sep 2023 23:47:51 +0300 Subject: [PATCH 18/21] $mol_form_draft async select list example --- form/draft/demo/demo.view.tree | 3 ++- form/draft/demo/demo.view.ts | 7 ++++++- list/list.view.css | 2 +- select/list/list.view.tree | 1 - 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index eabc96b066a..36e0f25477f 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -71,7 +71,8 @@ $mol_form_draft_demo $mol_example name \Friends Content <= Friends $mol_select_list pick_enabled true - showed => friends_showed + filter_pattern => friends_filter_pattern + option_title* <= friends_option_title* \ dictionary <= friends_suggestions * jocker \Jocker harley \Harley Quinn diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index 1a5048df9e2..b2e33b3c832 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -47,10 +47,15 @@ namespace $.$$ { @ $mol_mem override friends_suggestions() { - if (! this.friends_showed()) return {} this.$.$mol_wait_timeout(500) + this.friends_filter_pattern() return super.friends_suggestions() } + + override friends_option_title(id: string) { + if (! id) return '' + return this.friends_suggestions()[id] + } } } diff --git a/list/list.view.css b/list/list.view.css index f10cc16accf..53c0104edcf 100644 --- a/list/list.view.css +++ b/list/list.view.css @@ -8,7 +8,7 @@ align-items: stretch; align-content: stretch; */ transition: none; - min-height: 2rem; + min-height: 1.5rem; } [mol_list_gap_before] , diff --git a/select/list/list.view.tree b/select/list/list.view.tree index 74e747c4764..45cce334814 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -9,7 +9,6 @@ $mol_select_list $mol_view enabled <= drop_enabled <= enabled true sub /$mol_view <= Pick $mol_select - showed? <=> showed? false event_select*? <=> event_select*? null align_hor <= align_hor \right options <= options_pickable <= options /string From 8ee9e9f69d1f20d7171833b473e27575d9deb2ce Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sun, 1 Oct 2023 13:19:24 +0300 Subject: [PATCH 19/21] $mol_check_list dictionary --- check/list/list.view.tree | 2 +- check/list/list.view.ts | 6 +++--- form/draft/demo/demo.view.tree | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/check/list/list.view.tree b/check/list/list.view.tree index 34eaea9d37a..4ea590a27d8 100644 --- a/check/list/list.view.tree +++ b/check/list/list.view.tree @@ -1,5 +1,5 @@ $mol_check_list $mol_view - dictionary_checked * + dictionary * Option* $mol_check checked? <=> option_checked*? false label <= option_label* / diff --git a/check/list/list.view.ts b/check/list/list.view.ts index d6399ebfaed..a739b1beb72 100644 --- a/check/list/list.view.ts +++ b/check/list/list.view.ts @@ -10,18 +10,18 @@ namespace $.$$ { return {} } - override dictionary_checked(next?: Record) { + override dictionary(next?: Record) { return next ?? {} } override option_checked(id: string, next?: boolean | null) { - const prev = this.dictionary_checked() + const prev = this.dictionary() if (next === undefined) return prev[id] ?? null const next_rec = { ... prev, [id]: next } as Record if (next === null) delete next_rec[id] - return this.dictionary_checked(next_rec)[id] ?? null + return this.dictionary(next_rec)[id] ?? null } @ $mol_mem diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index 36e0f25477f..067397110b5 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -62,7 +62,7 @@ $mol_form_draft_demo $mol_example <= Hobbies_field $mol_form_field name \Hobbies Content <= Hobbies $mol_check_list - dictionary_checked? <=> dictionary_bool*hobbies? + dictionary? <=> dictionary_bool*hobbies? options * programming \Programming bikinkg \Biking From d3a60caa83c64e7a3c4df49011cb4485744a3464 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sun, 1 Oct 2023 14:47:46 +0300 Subject: [PATCH 20/21] $mol_select_list_demo lazy, form_draft simple --- form/draft/demo/demo.view.tree | 5 +---- form/draft/demo/demo.view.ts | 12 ------------ select/list/demo/demo.view.tree | 4 ++++ select/list/demo/demo.view.ts | 15 +++++++++++++++ select/list/list.view.tree | 3 +-- 5 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 select/list/demo/demo.view.ts diff --git a/form/draft/demo/demo.view.tree b/form/draft/demo/demo.view.tree index 067397110b5..9f6e8501f95 100644 --- a/form/draft/demo/demo.view.tree +++ b/form/draft/demo/demo.view.tree @@ -70,10 +70,7 @@ $mol_form_draft_demo $mol_example <= Friends_field $mol_form_field name \Friends Content <= Friends $mol_select_list - pick_enabled true - filter_pattern => friends_filter_pattern - option_title* <= friends_option_title* \ - dictionary <= friends_suggestions * + dictionary * jocker \Jocker harley \Harley Quinn penguin \Penguin diff --git a/form/draft/demo/demo.view.ts b/form/draft/demo/demo.view.ts index b2e33b3c832..68f8884791f 100644 --- a/form/draft/demo/demo.view.ts +++ b/form/draft/demo/demo.view.ts @@ -45,17 +45,5 @@ namespace $.$$ { this.result( this.message_done() ) } - @ $mol_mem - override friends_suggestions() { - this.$.$mol_wait_timeout(500) - this.friends_filter_pattern() - return super.friends_suggestions() - } - - override friends_option_title(id: string) { - if (! id) return '' - return this.friends_suggestions()[id] - } - } } diff --git a/select/list/demo/demo.view.tree b/select/list/demo/demo.view.tree index f4e3ebce76d..2152b75b584 100644 --- a/select/list/demo/demo.view.tree +++ b/select/list/demo/demo.view.tree @@ -5,6 +5,9 @@ $mol_select_list_demo $mol_example_small rows / <= Friends $mol_select_list value? <=> friends? / + option_title* <= option_title* \ + filter_pattern? => filter_pattern? + pick_enabled true dictionary <= suggestions * jocker \Jocker harley \Harley Quinn @@ -16,6 +19,7 @@ $mol_select_list_demo $mol_example_small mask \Black Mask <= Friends_disabled $mol_select_list value? <=> friends? / + option_title* <= option_title* \ dictionary <= suggestions enabled false tags / diff --git a/select/list/demo/demo.view.ts b/select/list/demo/demo.view.ts new file mode 100644 index 00000000000..3bf0dd86117 --- /dev/null +++ b/select/list/demo/demo.view.ts @@ -0,0 +1,15 @@ +namespace $.$$ { + export class $mol_select_list_demo extends $.$mol_select_list_demo { + @ $mol_mem + override suggestions() { + this.$.$mol_wait_timeout(500) + this.filter_pattern() + return super.suggestions() + } + + override option_title(id: string) { + if (! id) return '' + return this.suggestions()[id] + } + } +} diff --git a/select/list/list.view.tree b/select/list/list.view.tree index 45cce334814..2965b04af34 100644 --- a/select/list/list.view.tree +++ b/select/list/list.view.tree @@ -16,7 +16,6 @@ $mol_select_list $mol_view option_label* <= option_title* \ trigger_enabled <= pick_enabled <= enabled true hint <= pick_hint @ \Add.. - filter_pattern? <=> filter_pattern? \ - filter_hint <= filter_hint @ \Filter.. + filter_pattern? => filter_pattern? Trigger_icon <= Pick_icon $mol_icon_plus ^ badges_list From 902a9f683b507dd5dfee3b77fdccb794ba5a2900 Mon Sep 17 00:00:00 2001 From: Stefan Zerkalica Date: Sun, 1 Oct 2023 14:59:45 +0300 Subject: [PATCH 21/21] $mol_select_list_demo separate lazy example --- select/list/demo/demo.view.tree | 10 ++++++---- select/list/demo/demo.view.ts | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/select/list/demo/demo.view.tree b/select/list/demo/demo.view.tree index 2152b75b584..27b3772f75f 100644 --- a/select/list/demo/demo.view.tree +++ b/select/list/demo/demo.view.tree @@ -5,9 +5,6 @@ $mol_select_list_demo $mol_example_small rows / <= Friends $mol_select_list value? <=> friends? / - option_title* <= option_title* \ - filter_pattern? => filter_pattern? - pick_enabled true dictionary <= suggestions * jocker \Jocker harley \Harley Quinn @@ -19,9 +16,14 @@ $mol_select_list_demo $mol_example_small mask \Black Mask <= Friends_disabled $mol_select_list value? <=> friends? / - option_title* <= option_title* \ dictionary <= suggestions enabled false + <= Friends_lazy $mol_select_list + value? <=> friends_lazy? / + option_title* <= option_title* \ + filter_pattern? => filter_pattern? + pick_enabled true + dictionary <= suggestions_lazy <= suggestions tags / \select \tags diff --git a/select/list/demo/demo.view.ts b/select/list/demo/demo.view.ts index 3bf0dd86117..3baf04b0035 100644 --- a/select/list/demo/demo.view.ts +++ b/select/list/demo/demo.view.ts @@ -1,7 +1,7 @@ namespace $.$$ { export class $mol_select_list_demo extends $.$mol_select_list_demo { @ $mol_mem - override suggestions() { + override suggestions_lazy() { this.$.$mol_wait_timeout(500) this.filter_pattern() return super.suggestions() @@ -9,7 +9,7 @@ namespace $.$$ { override option_title(id: string) { if (! id) return '' - return this.suggestions()[id] + return this.suggestions_lazy()[id] } } }