x4js 2.2.39 → 2.2.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/components.ts +1 -0
- package/src/components/listbox/listbox.ts +25 -2
- package/src/components/tag/tag.module.scss +30 -0
- package/src/components/tag/tag.ts +33 -0
- package/src/components/treeview/treeview.module.scss +1 -1
- package/src/components/treeview/treeview.ts +19 -2
- package/src/core/component.ts +2 -2
- package/src/core/core_tools.ts +5 -1
package/package.json
CHANGED
|
@@ -37,6 +37,7 @@ export * from "./slider/slider"
|
|
|
37
37
|
export * from "./spreadsheet/spreadsheet"
|
|
38
38
|
export * from "./switch/switch"
|
|
39
39
|
export * from "./tabs/tabs"
|
|
40
|
+
export * from "./tag/tag"
|
|
40
41
|
export * from "./textarea/textarea"
|
|
41
42
|
export * from "./textedit/textedit"
|
|
42
43
|
export * from "./tickline/tickline"
|
|
@@ -22,7 +22,7 @@ import { ScrollView, Viewport } from '../viewport/viewport';
|
|
|
22
22
|
import { Header } from '../header/header';
|
|
23
23
|
|
|
24
24
|
import { HBox } from '../boxes/boxes';
|
|
25
|
-
import { Label } from '../label/label';
|
|
25
|
+
import { Label, SimpleText } from '../label/label';
|
|
26
26
|
|
|
27
27
|
import "./listbox.module.scss"
|
|
28
28
|
|
|
@@ -31,6 +31,7 @@ export type ListboxID = number | string;
|
|
|
31
31
|
export interface ListItem {
|
|
32
32
|
id: ListboxID;
|
|
33
33
|
text: string | UnsafeHtml;
|
|
34
|
+
sub_cols?: (string | UnsafeHtml | Component)[]; // extra columns
|
|
34
35
|
|
|
35
36
|
iconId?: string;
|
|
36
37
|
data?: any;
|
|
@@ -477,9 +478,31 @@ export class Listbox extends Component<ListboxProps,ListboxEvents> {
|
|
|
477
478
|
*/
|
|
478
479
|
|
|
479
480
|
defaultRenderer( item: ListItem ): Component {
|
|
481
|
+
|
|
482
|
+
const mk_col = ( _: any, index: number ) => {
|
|
483
|
+
const c = item.sub_cols[index];
|
|
484
|
+
if( c===undefined || c===null ) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if( c instanceof Component ) {
|
|
489
|
+
return c;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return new SimpleText( { cls: `column ref-c${index+2}`, text: c } )
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
let cols: Component[] = null;
|
|
496
|
+
if( item.sub_cols ) {
|
|
497
|
+
cols = item.sub_cols.map( mk_col );
|
|
498
|
+
}
|
|
499
|
+
|
|
480
500
|
return new HBox( {
|
|
481
501
|
cls: item.cls,
|
|
482
|
-
content:
|
|
502
|
+
content: [
|
|
503
|
+
new Label( { cls: `column ref-c1`, icon: item.iconId, text: item.text } ),
|
|
504
|
+
...cols,
|
|
505
|
+
],
|
|
483
506
|
} )
|
|
484
507
|
}
|
|
485
508
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tag.module.scss
|
|
3
|
+
* @author Etienne Cochard
|
|
4
|
+
* @copyright (c) 2026 R-libre ingenierie, all rights reserved.
|
|
5
|
+
**/
|
|
6
|
+
|
|
7
|
+
.x4tag {
|
|
8
|
+
color: black;
|
|
9
|
+
border-radius: 16px;
|
|
10
|
+
border: 1px solid var( --border );
|
|
11
|
+
padding: 2px 8px;
|
|
12
|
+
gap: 4px;
|
|
13
|
+
font-weight: normal;
|
|
14
|
+
|
|
15
|
+
.x4icon:empty {
|
|
16
|
+
display: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.x4icon {
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.x4simpletext {
|
|
23
|
+
color: inherit;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&.alert {
|
|
27
|
+
color: var( --alert-color );
|
|
28
|
+
background-color: var( --alert-background );
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file tag.ts
|
|
3
|
+
* @author Etienne Cochard
|
|
4
|
+
* @copyright (c) 2026 R-libre ingenierie, all rights reserved.
|
|
5
|
+
**/
|
|
6
|
+
|
|
7
|
+
import { ComponentProps } from '../../core/component';
|
|
8
|
+
import { class_ns, UnsafeHtml } from '../../core/core_tools';
|
|
9
|
+
import { HBox } from '../boxes/boxes';
|
|
10
|
+
import { Icon } from '../icon/icon';
|
|
11
|
+
import { SimpleText } from '../label/label';
|
|
12
|
+
|
|
13
|
+
import "./tag.module.scss";
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export interface TagProps extends ComponentProps {
|
|
17
|
+
label?: string | UnsafeHtml;
|
|
18
|
+
icon?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@class_ns( "x4" )
|
|
23
|
+
export class Tag extends HBox<TagProps> {
|
|
24
|
+
|
|
25
|
+
constructor( props: TagProps ) {
|
|
26
|
+
super( props );
|
|
27
|
+
|
|
28
|
+
this.setContent( [
|
|
29
|
+
new Icon( { iconId: props.icon } ),
|
|
30
|
+
new SimpleText( { text: props.label } ),
|
|
31
|
+
])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -19,7 +19,7 @@ import { EventCallback } from '../../core/core_events';
|
|
|
19
19
|
import { Component, ComponentEvent, ComponentEvents, ComponentProps, EvClick, EvDblClick, EvSelectionChange, componentFromDOM } from '../../core/component';
|
|
20
20
|
|
|
21
21
|
import { ScrollView, Viewport } from '../viewport/viewport';
|
|
22
|
-
import { Label } from '../label/label';
|
|
22
|
+
import { Label, SimpleText } from '../label/label';
|
|
23
23
|
import { ListboxID, ListItem } from '../listbox/listbox';
|
|
24
24
|
import { Box, BoxProps, HBox, VBox } from '../boxes/boxes';
|
|
25
25
|
import { Icon } from '../icon/icon';
|
|
@@ -83,7 +83,7 @@ class CTreeViewItem extends Box {
|
|
|
83
83
|
|
|
84
84
|
if( item ) {
|
|
85
85
|
this._label = new HBox( {cls:"label item", content: [
|
|
86
|
-
this._icon = new Icon( { iconId: item.children ? folder_icon : undefined } ),
|
|
86
|
+
this._icon = new Icon( { cls: 'arrow', iconId: item.children ? folder_icon : undefined } ),
|
|
87
87
|
new Label( { tag: "span", cls: "", text: item.text, icon: item.iconId } ),
|
|
88
88
|
]});
|
|
89
89
|
|
|
@@ -91,6 +91,23 @@ class CTreeViewItem extends Box {
|
|
|
91
91
|
this._label.addClass( item.cls );
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
if( item.sub_cols ) {
|
|
95
|
+
const mk_col = ( _: any, index: number ) => {
|
|
96
|
+
const c = item.sub_cols[index];
|
|
97
|
+
if( c===undefined || c===null ) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if( c instanceof Component ) {
|
|
102
|
+
return c;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return new SimpleText( { cls: `column ref-c${index+2}`, text: c } )
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this._label.appendContent( item.sub_cols.map( mk_col ) );
|
|
109
|
+
}
|
|
110
|
+
|
|
94
111
|
this._label.setInternalData( "id", item.id );
|
|
95
112
|
|
|
96
113
|
if( item.children ) {
|
package/src/core/component.ts
CHANGED
|
@@ -416,8 +416,8 @@ export class Component<P extends ComponentProps = ComponentProps, E extends Comp
|
|
|
416
416
|
* @param name - The suffix of the `data-` attribute (e.g., for `data-foo`, use `"foo"`).
|
|
417
417
|
* @returns The string value of the `data-*` attribute, or `null` if not present.
|
|
418
418
|
*
|
|
419
|
-
* @cf setIntData
|
|
420
|
-
* @cf setInternalData
|
|
419
|
+
* @cf Component.setIntData, Component.getIntData (number)
|
|
420
|
+
* @cf Component.setInternalData, Component.getInternalData (typed data)
|
|
421
421
|
*/
|
|
422
422
|
|
|
423
423
|
getData( name: string ) : string {
|
package/src/core/core_tools.ts
CHANGED
|
@@ -115,7 +115,7 @@ export function unsafeHtml(x: string): UnsafeHtml {
|
|
|
115
115
|
|
|
116
116
|
export function unsafe(strings: TemplateStringsArray, ...values: any[]): UnsafeHtml {
|
|
117
117
|
const result = strings.reduce((acc, str, i) => {
|
|
118
|
-
return acc + str + (values[i] ?? '');
|
|
118
|
+
return acc + str + sanitizeHtml(values[i] ?? '');
|
|
119
119
|
}, '');
|
|
120
120
|
return unsafeHtml(result);
|
|
121
121
|
}
|
|
@@ -1032,6 +1032,10 @@ const _rx_escape = /[&<>"']/g;
|
|
|
1032
1032
|
*/
|
|
1033
1033
|
|
|
1034
1034
|
export function sanitizeHtml( input: string ): string {
|
|
1035
|
+
if( input===undefined || input===null || input==="" ) {
|
|
1036
|
+
return "";
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1035
1039
|
if( !_rx_escape.test( input ) ) {
|
|
1036
1040
|
return input;
|
|
1037
1041
|
}
|