x4js 2.0.28 → 2.0.30

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.
Files changed (70) hide show
  1. package/.vscode/launch.json +14 -0
  2. package/.vscode/settings.json +2 -0
  3. package/ai-comments.txt +97 -0
  4. package/demo/assets/house-light.svg +1 -0
  5. package/demo/assets/radio.svg +4 -0
  6. package/demo/index.html +12 -0
  7. package/demo/main.scss +23 -0
  8. package/demo/main.ts +324 -0
  9. package/demo/package.json +26 -0
  10. package/demo/scss.d.ts +4 -0
  11. package/demo/svg.d.ts +1 -0
  12. package/demo/tsconfig.json +14 -0
  13. package/lib/types/x4js.d.ts +0 -2374
  14. package/package.json +23 -47
  15. package/prepack.mjs +3 -0
  16. package/scripts/prepack.mjs +342 -0
  17. package/src/colors.scss +246 -0
  18. package/src/components/boxes/boxes.module.scss +1 -1
  19. package/src/components/boxes/boxes.ts +139 -28
  20. package/src/components/button/button.ts +80 -33
  21. package/src/components/combobox/combobox.ts +1 -1
  22. package/src/components/dialog/dialog.ts +4 -0
  23. package/src/components/gridview/gridview.ts +104 -6
  24. package/src/components/icon/icon.ts +42 -14
  25. package/src/components/input/input.ts +146 -74
  26. package/src/components/keyboard/keyboard.module.scss +1 -1
  27. package/src/components/keyboard/keyboard.ts +31 -9
  28. package/src/components/label/label.module.scss +9 -0
  29. package/src/components/label/label.ts +10 -6
  30. package/src/components/link/link.module.scss +44 -0
  31. package/src/components/link/link.ts +7 -1
  32. package/src/components/listbox/listbox.module.scss +18 -4
  33. package/src/components/listbox/listbox.ts +32 -12
  34. package/src/components/menu/menu.module.scss +14 -2
  35. package/src/components/menu/menu.ts +1 -1
  36. package/src/components/messages/messages.ts +13 -5
  37. package/src/components/panel/panel.module.scss +7 -0
  38. package/src/components/popup/popup.ts +14 -10
  39. package/src/components/propgrid/propgrid.ts +1 -1
  40. package/src/components/shared.scss +4 -0
  41. package/src/components/spreadsheet/spreadsheet.ts +81 -34
  42. package/src/components/tabs/tabs.module.scss +1 -0
  43. package/src/components/textarea/textarea.ts +8 -2
  44. package/src/components/textedit/textedit.ts +7 -0
  45. package/src/components/themes.scss +2 -0
  46. package/src/components/tooltips/tooltips.ts +15 -3
  47. package/src/core/component.ts +358 -162
  48. package/src/core/core_application.ts +129 -32
  49. package/src/core/core_colors.ts +382 -119
  50. package/src/core/core_data.ts +73 -86
  51. package/src/core/core_dom.ts +10 -0
  52. package/src/core/core_dragdrop.ts +32 -7
  53. package/src/core/core_element.ts +111 -4
  54. package/src/core/core_events.ts +48 -11
  55. package/src/core/core_i18n.ts +2 -0
  56. package/src/core/core_pdf.ts +454 -0
  57. package/src/core/core_router.ts +64 -5
  58. package/src/core/core_state.ts +1 -0
  59. package/src/core/core_styles.ts +11 -12
  60. package/src/core/core_svg.ts +346 -51
  61. package/src/core/core_tools.ts +105 -17
  62. package/src/x4.ts +1 -0
  63. package/src/x4tsx.d.ts +2 -1
  64. package/tsconfig.json +11 -0
  65. package/lib/README.txt +0 -20
  66. package/lib/cjs/x4.css +0 -1
  67. package/lib/cjs/x4.js +0 -2
  68. package/lib/esm/x4.css +0 -1
  69. package/lib/esm/x4.mjs +0 -2
  70. package/lib/styles/x4.css +0 -1
@@ -0,0 +1,14 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "node",
9
+ "request": "launch",
10
+ "name": "debug prepack",
11
+ "program": "${workspaceFolder}/scripts/prepack.mjs",
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,2 @@
1
+ {
2
+ }
@@ -0,0 +1,97 @@
1
+ x4 se distingue des approches réactives conventionnelles.
2
+ Il offre une expérience de développement qui met l'accent sur la simplicité, la performance et un contrôle affiné sur la manière dont l'interface utilisateur est construite et mise à jour.
3
+
4
+ Voici les avantages qui découlent de cette philosophie :
5
+
6
+ - Abstraction du DOM, mais avec une philosophie distincte :
7
+ Contrairement aux frameworks réactifs qui utilisent un Virtual DOM et des mécanismes de réconciliation
8
+ pour abstraire les manipulations du DOM, x4 propose une abstraction différente.
9
+ L'objectif n'est pas d'imiter le fonctionnement des frameworks populaires, mais de fournir une manière plus directe, plus légère et plus performante
10
+ d'interagir avec les concepts de l'interface utilisateur. Cette abstraction est conçue pour être moins "magique" et plus prévisible.
11
+
12
+ - Performance optimisée :
13
+ En concevant son propre modèle d'abstraction et de mise à jour du DOM, x4 vise à atteindre une performance brute supérieure.
14
+ Il peut s'affranchir de certaines complexités inhérentes aux approches réactives pour se concentrer sur l'essentiel,
15
+ offrant ainsi une expérience utilisateur fluide même dans des applications exigeantes.
16
+
17
+ - Un écosystème TypeScript pur :
18
+ Pour garantir une robustesse et une maintenabilité maximales, ce framework élimine tout mélange de syntaxe déclarative comme JSX/TSX avec du code JavaScript.
19
+ L'intégralité de la création d'interfaces et de la logique applicative est réalisée en TypeScript natif.
20
+ Cela permet de bénéficier pleinement des avantages du typage fort, de la vérification à la compilation, et d'une expérience de développement cohérente et sécurisée.
21
+
22
+ - Gestion de l'état et des références simplifiée :
23
+ Ce framework s'affranchit des concepts comme useRef ou des "hooks" tels qu'on les trouve dans d'autres écosystèmes.
24
+ La gestion des états et des références est intégrée de manière plus directe et idiomatique à sa propre architecture, favorisant une logique plus linéaire et plus facile à suivre.
25
+
26
+ - Conçu pour les applications complètes :
27
+ Plutôt que de se concentrer uniquement sur des composants UI isolés, ce framework est orienté vers la construction d'applications complètes.
28
+ Il offre les outils et la structure nécessaires pour gérer des architectures plus vastes, de la gestion des routes à l'état global.
29
+
30
+ - Compatibilité avec les Web Workers :
31
+ Afin d'optimiser les performances et de permettre des traitements asynchrones intensifs sans bloquer le thread principal,
32
+ ce framework est conçu pour être compatible avec les Web Workers. Cela ouvre la voie à des applications plus réactives et performantes, en déportant les tâches lourdes.
33
+
34
+ - Environnement de compilation et outils spécifiques :
35
+ Le développement avec ce framework est accéléré par un environnement de compilation ultra-rapide, basé sur esbuild.
36
+ De plus, il est livré avec un outils spécifiques X4Build qui améliore l'expérience développeur.
37
+ ainsi qu'une expérience de Hot Module Replacement (HMR) fluide et efficace pour des itérations rapides.
38
+
39
+ - Modèle de développement éprouvé :
40
+ L'architecture et les pratiques recommandées par ce framework constituent un modèle de développement éprouvé.
41
+ Il facilite notamment des scénarios avancés comme les evenements distribués via WebSocket directement intégré (si besoin) dans l'application,
42
+
43
+ - Création de composants intuitive :
44
+ La manière dont x4 abstrait le DOM et gère la réactivité rend la création de composants d'une simplicité déconcertante.
45
+ Vous pouvez construire des interfaces modulaires et réutilisables avec une facilité remarquable, en vous concentrant sur la logique métier plutôt
46
+ que sur la gestion complexe des interactions DOM.
47
+
48
+ - Accélération Drastique du Développement :
49
+ Avec plus de 50 composants prêts à l'emploi, les développeurs peuvent assembler des interfaces utilisateur complexes et fonctionnelles
50
+ à une vitesse remarquable. Plutôt que de passer du temps à concevoir et implémenter des éléments de base comme des buttons, des inputs, des checkboxes ou des sliders,
51
+ ils peuvent les utiliser directement. Ceci libère un temps précieux pour se concentrer sur la logique métier spécifique de l'application.
52
+
53
+ Le développement "from scratch" de tels composants est coûteux en temps et en ressources. La richesse de cette bibliothèque élimine ce fardeau,
54
+ réduisant ainsi les efforts de conception, de codage, de test et de maintenance de ces éléments d'interface fondamentaux.
55
+ Cela signifie moins de code à écrire, moins de bugs potentiels et une meilleure productivité globale.
56
+
57
+ - Richesse et Diversité des Interfaces Utilisateur :
58
+ La large gamme de composants permet de créer des expériences utilisateur très riches et interactives sans avoir à intégrer de bibliothèques
59
+ tierces supplémentaires pour des fonctionnalités de base. Des composants sophistiqués comme gridview (pour l'affichage de données tabulaires), spreadsheet (pour des fonctionnalités de tableur complètes),
60
+ calendar, colorpicker, dialog, treeview ou progress sont inclus, offrant une boîte à outils complète pour des applications métier complexes ou des tableaux de bord interactifs.
61
+
62
+ - Cohérence et Qualité :
63
+ L'utilisation de composants d'un même framework assure une cohérence visuelle et comportementale à travers toute l'application.
64
+ Ces composants sont testés et optimisés, garantissant une meilleure qualité et une expérience utilisateur plus fiable dès le départ.
65
+ En somme, cette collection de composants est un avantage concurrentiel énorme.
66
+
67
+
68
+
69
+
70
+
71
+
72
+ You are a TypeScript/JavaScript documentation assistant.
73
+ Your task is to generate **JSDoc comments** for public APIs in the provided code.
74
+ Follow these rules strictly:
75
+
76
+ ### Rules:
77
+ 1. **Only document public APIs**:
78
+ - Public classes, methods, properties, and events.
79
+ - Ignore private/protected/internal members (e.g., `_privateField`, `#privateMethod`).
80
+
81
+ 2. **Output format**:
82
+ - Generate **only JSDoc blocks** (no code repetition).
83
+ - Use **inline comments** (`/** ... */`) for brevity.
84
+ - Do not include `@class` or `@extends` (JSDoc infers these).
85
+ - Document in english
86
+
87
+ 3. **Content guidelines**:
88
+ - Describe **purpose, behavior, and usage** (not implementation).
89
+ - Mention auto-generated CSS classes (e.g., `Button → x4button`).
90
+ - Include `@example` where helpful.
91
+ - Be concise, clear, and professional.
92
+
93
+ Avoid:
94
+
95
+ Implementation details.
96
+ Private/protected members.
97
+ Redundant or repetitive descriptions.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" fill="currentColor"><!--!Font Awesome Pro 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.--><path d="M298.6 4c-6-5.3-15.1-5.3-21.2 0L5.4 244c-6.6 5.8-7.3 16-1.4 22.6s16 7.3 22.6 1.4L64 235l0 197c0 44.2 35.8 80 80 80l288 0c44.2 0 80-35.8 80-80l0-197 37.4 33c6.6 5.8 16.7 5.2 22.6-1.4s5.2-16.7-1.4-22.6L298.6 4zM96 432l0-225.3L288 37.3 480 206.7 480 432c0 26.5-21.5 48-48 48l-64 0 0-160c0-17.7-14.3-32-32-32l-96 0c-17.7 0-32 14.3-32 32l0 160-64 0c-26.5 0-48-21.5-48-48zm144 48l0-160 96 0 0 160-96 0z"/></svg>
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 5 5" aria-hidden="true">
2
+ <circle cx="2.5" cy="2.5" r="2.5" fill="currentColor"></circle>
3
+ <circle cx="2.5" cy="2.5" r="1.25" fill="white"></circle>
4
+ </svg>
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="stylesheet" href="./main.css">
7
+ </head>
8
+ <body>
9
+ <noscript>JavaScript required</noscript>
10
+ <script src="./main.js"></script>
11
+ </body>
12
+ </html>
package/demo/main.scss ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * @file main.scss
9
+ * @author Etienne Cochard
10
+ *
11
+ * @copyright (c) 2024 R-libre ingenierie
12
+ *
13
+ * Use of this source code is governed by an MIT-style license
14
+ * that can be found in the LICENSE file or at https://opensource.org/licenses/MIT.
15
+ **/
16
+
17
+ @use "./node_modules/x4js/src/x4.scss" ;
18
+
19
+
20
+
21
+ body {
22
+ padding: 16px;
23
+ }
package/demo/main.ts ADDED
@@ -0,0 +1,324 @@
1
+ /**
2
+ * ___ ___ __
3
+ * \ \/ / / _
4
+ * \ / /_| |_
5
+ * / \____ _|
6
+ * /__/\__\ |_|
7
+ *
8
+ * DEMO FILE
9
+ *
10
+ **/
11
+
12
+ import { wrapDOM, Component } from "../src/core/component";
13
+ import { unsafeHtml } from '../src/core/core_tools'
14
+ import { SvgBuilder, SvgComponent } from '../src/core/core_svg'
15
+
16
+ import { Button } from "../src/components/button/button.js"
17
+ import { Label } from "../src/components/label/label.js"
18
+ import { Checkbox } from "../src/components/checkbox/checkbox.js"
19
+ import { HBox, VBox } from "../src/components/boxes/boxes.js"
20
+
21
+ import { Listbox, ListItem } from '../src/components/listbox/listbox'
22
+ import { Panel } from '../src/components/panel/panel'
23
+ import { TextEdit } from '../src/components/textedit/textedit'
24
+ import { TextArea } from '../src/components/textarea/textarea'
25
+ import { Switch } from '../src/components/switch/switch'
26
+ import { Combobox } from '../src/components/combobox/combobox'
27
+ import { Slider } from '../src/components/slider/slider'
28
+ import { Progress } from '../src/components/progress/progress'
29
+ import { BtnGroup } from '../src/components/btngroup/btngroup'
30
+ import { Image } from '../src/components/image/image'
31
+ import { ColorInput } from '../src/components/colorinput/colorinput'
32
+ import { ColorPicker } from '../src/components/colorpicker/colorpicker'
33
+ import { Menu } from '../src/components/menu/menu'
34
+ import { initTooltips } from '../src/components/tooltips/tooltips'
35
+ import { Treeview, TreeItem } from '../src/components/treeview/treeview'
36
+ import { Dialog } from '../src/components/dialog/dialog'
37
+ import { Form } from '../src/components/form/form'
38
+ import { MessageBox } from '../src/components/messages/messages'
39
+ import { Calendar } from '../src/components/calendar/calendar'
40
+ import { Notification } from '../src/components/notification/notification'
41
+ import { Header } from '../src/components/header/header'
42
+ import { Tabs } from '../src/components/tabs/tabs'
43
+ import { Rating } from '../src/components/rating/rating'
44
+
45
+ import "@fontsource/montserrat"
46
+ import "./main.scss"
47
+
48
+ import def_icon from "./assets/house-light.svg";
49
+
50
+
51
+ function main( ) {
52
+
53
+ initTooltips( );
54
+
55
+ const testMenu = ( ev: MouseEvent ) => {
56
+ const sub = new Menu( { items: [
57
+ "Sub menu 1",
58
+ { text: "sub 1-1" }
59
+ ]
60
+ })
61
+
62
+ const sub3 = new Menu( { items: [
63
+ "Sub menu 3",
64
+ { text: "sub 3-1" }
65
+ ]
66
+ })
67
+
68
+ const sub2 = new Menu( { items: [
69
+ "Sub menu 2",
70
+ { text: "sub 2-1" },
71
+ { text: "menu e", menu: sub3 }
72
+ ]
73
+ })
74
+
75
+ const pop = new Menu( {items: [
76
+ "Title",
77
+ { text: "menu a", click: null, icon: def_icon },
78
+ "-",
79
+ { text: "menu b", click: null },
80
+ { text: "menu c", click: null, disabled: true },
81
+ "-",
82
+ { text: "menu d", menu: sub },
83
+ { text: "menu e", menu: sub2 },
84
+ ]
85
+ });
86
+
87
+ pop.displayAt( ev.pageX, ev.pageY );
88
+ ev.stopPropagation( );
89
+ ev.preventDefault( );
90
+ }
91
+
92
+ const items: ListItem[] = [
93
+ { id: 1, text: "Item 1" },
94
+ { id: 2, text: "Item 2" },
95
+ { id: 3, text: "Item 3" },
96
+ { id: 4, text: "Item 4" },
97
+ { id: 5, text: "Item 5" },
98
+ { id: 6, text: "Item 6" },
99
+ ];
100
+
101
+ const tree_items: TreeItem[] = [
102
+ { id: 1, text: "root", open: true, children: [
103
+ { id: 2, text: "folder 1", children: [
104
+ { id: 3, text: "folder 1.1", children: [
105
+ { id: 4, text: "value 1.1" },
106
+ { id: 5, text: "value 1.2", iconId: def_icon },
107
+ { id: 6, text: "value 1.3" }
108
+ ] }
109
+ ]},
110
+ { id: 10, text: "folder 2", open: true, children: [
111
+ { id: 11, text: "folder 2.1", open: true, children: [
112
+ { id: 12, text: "value 2.1" },
113
+ { id: 13, text: "value 2.2" },
114
+ { id: 14, text: "value 2.3" }
115
+ ] }
116
+ ]}
117
+ ]}
118
+ ]
119
+
120
+ const dialog = new Dialog( {
121
+ title: "Dialog",
122
+ modal: true,
123
+ movable: true,
124
+ sizable: true,
125
+ closable: true,
126
+ buttons: ['ok','cancel'],
127
+ form: new Form( {
128
+ content: [
129
+ new Label( { cls: "x4flex", text: unsafeHtml("<h1>Example dialog</h1><p>This dialog is <i>resizable</i>...") } ),
130
+ new TextEdit( { label: "title", value: "" } ),
131
+ ]
132
+ }),
133
+ });
134
+
135
+ const svg_builder = new SvgBuilder( );
136
+
137
+ svg_builder
138
+ .ellipse( 45, 45, 40 )
139
+ .stroke( "#ccc", 5 )
140
+ .fill( "transparent" );
141
+
142
+ svg_builder.path( )
143
+ .arc( 45, 45, 40, 0, 30*360/100 )
144
+ .stroke( "var( --accent-background )", 5 )
145
+ .fill( "none" )
146
+ .setAttr("tooltip","test")
147
+ .strokeCap( "round" )
148
+ .addDOMEvent( "mouseenter", ( ev ) => {
149
+ console.log( ev.target );
150
+ (ev.target as SVGElement).setAttribute( "stroke-width", "10px" );
151
+ })
152
+ .addDOMEvent( "mouseleave", ( ev ) => {
153
+ console.log( ev.target );
154
+ (ev.target as SVGElement).setAttribute( "stroke-width", "5px" );
155
+ });
156
+
157
+ svg_builder.text( 45, 42, "30%" )
158
+ .textAlign( "center" )
159
+ .verticalAlign( "baseline" )
160
+ .fontSize( "150%" )
161
+ .fontWeight( "bold" );
162
+
163
+ svg_builder.text( 45, 80, "custom control" )
164
+ .fontSize( "10px" )
165
+ .textAlign( "center" )
166
+
167
+ const t = new HBox( {
168
+ style: {
169
+ alignItems: "start",
170
+ gap: "8px",
171
+ flexWrap: "wrap",
172
+ },
173
+ content: [
174
+ new Panel( {
175
+ title: "Panel",
176
+ icon: def_icon,
177
+ width: 510,
178
+ content: [
179
+ new Label( { text: "label", icon: def_icon } ),
180
+ new HBox( { content: [
181
+ new Button( { label:'OK', icon:def_icon } ),
182
+ new Button( { label:'OK', icon:def_icon, disabled: true } ),
183
+ new Button( { cls: "outline", label:'OK', icon:def_icon } ),
184
+ ]}),
185
+ new VBox({ content: [
186
+ new HBox({ content: [
187
+ new Checkbox( { label: 'Unchecked', checked: false } ),
188
+ new Checkbox( { label: 'Checked', checked: true } ),
189
+ new Checkbox( { label: 'Disabled', disabled: true, checked: true } ),
190
+ ]}),
191
+ new HBox({ content: [
192
+ new Switch( { label: 'Unchecked', checked: false } ),
193
+ new Switch( { label: 'Checked', checked: true } ),
194
+ new Switch( { label: 'Disabled', checked: true, disabled: true } ),
195
+ ]}),
196
+ ]}),
197
+ new HBox( {content: [
198
+ new Listbox( {
199
+ width: 250,
200
+ height: 150,
201
+ items
202
+ }),
203
+ new Listbox( {
204
+ width: 250,
205
+ height: 150,
206
+ items,
207
+ disabled: true,
208
+ })
209
+ ]}),
210
+ new Treeview( {
211
+ items: tree_items,
212
+ height: 150,
213
+ }),
214
+ new Header( {
215
+ items: [
216
+ { title: "Column ", name: "a1" },
217
+ { title: "Column 66%", name: "a2", width: -2 },
218
+ { title: "Column 33%", name: "a3", width: -1 },
219
+ ]
220
+ } ),
221
+ ]}),
222
+ new Panel( {
223
+ title: "Panel",
224
+ icon: def_icon,
225
+ width: 510,
226
+ content: [
227
+ new TextEdit( { labelWidth: 90, label: "Login", value: "hello", required: true, disabled: true } ),
228
+ new TextEdit( { labelWidth: 90, label: "Password", value: "world", type: "password", inputGadgets: [
229
+ new Button( { icon: def_icon })
230
+ ] } ),
231
+ new TextEdit( { labelWidth: 90, label: "Email", value: "", type: "email", placeholder: "select your email contact" } ),
232
+ new TextArea( { label: "Demo", height: 140, tooltip: "This is a small tooltip" } ),
233
+ new Combobox( { label: 'ComboBox', items }),
234
+ new Combobox( { label: 'Readonly', items, readonly: true }),
235
+ new Combobox( { label: 'Disabled', items, disabled: true })
236
+ ]
237
+ }),
238
+ new Panel( {
239
+ title: "Another panel",
240
+ width: 610,
241
+ content: [
242
+ new Slider( {min: 0, max: 100, step: 10, value: 50 } ),
243
+ new Progress( { min: 0, max: 100, value: 45, cls: "indeterm" } ),
244
+ new BtnGroup( { cls: "x4flex", items: [ new Label({text:"group"} ), "ok","cancel","yes","no","-","retry","abort",new Button({cls:"danger",label:"custom"})]}),
245
+ new HBox( { content: [
246
+ new Image( { src:"https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/images/bg-7.png", lazy: true, width: 250, height: "100%", fit: "contain", position: "50% 50%", alt: "an image" } ),
247
+ new ColorPicker( { color: "red", } ),
248
+ ]}),
249
+ new ColorInput( { color: "red", } ),
250
+ new Rating( { value: 3 } ),
251
+ new SvgComponent( { svg: svg_builder, id: "", viewbox: "0 0 90 90", width: 90, height: 90, style: { margin: '16px'} } ),
252
+
253
+ new HBox( { content: [
254
+ new Button( { label:'Dialog...', click: ( ) => dialog.show() } ),
255
+ new Button( { label:'Message...', click: ( ) => {MessageBox.show( unsafeHtml( '<b>Care</b><br/>You will delete <i>all data</i>.' ) ) } } ),
256
+ new Button( { label:'Notification...', click: ( ) => { new Notification( { mode: "success", text: "Modification saved", title: "Backup" } ).display( 5 ) } } ),
257
+ ]}),
258
+ ]
259
+ }),
260
+ new Panel( {
261
+ title: "Another panel",
262
+ width: 410,
263
+ content: [
264
+ new Calendar( { } ),
265
+ ]
266
+ }),
267
+ new Tabs( {
268
+
269
+ width: 500,
270
+ height: 200,
271
+
272
+ default: "page1",
273
+ items: [
274
+ { name: "page1", title: "Tab 1", icon: def_icon, content: new Label( { text: unsafeHtml(`<h4>tab 1 content</h4><p>lorem ipsum</p>`)}) },
275
+ { name: "page2", title: "Tab 2", icon: def_icon, content: new Label( { text: unsafeHtml(`<h4>tab 2 content</h4><p>ipsum lorem</p>` )}) },
276
+ { name: "page3", title: "Tab 3", content: new Label( { text: unsafeHtml(`<h4>tab 3 content</h4><p>ipsum ++</p>` )}) },
277
+ ]
278
+ })
279
+ ]
280
+ } );
281
+
282
+ const body = wrapDOM( document.body );
283
+ body.appendContent( t );
284
+ body.addClass( "fit" );
285
+ body.addDOMEvent( "contextmenu", ( ev ) => { testMenu(ev) } );
286
+ }
287
+
288
+ function waitFontLoading(name: string) {
289
+
290
+ // tip for waiting font loading:
291
+ // by default, body is created invisible ((opacity = 0)
292
+ // we create a div inside with the font we need to wait the loading
293
+ // as soon as the font is loaded, it's size will change, the browser end font loading
294
+ // we can remove the div.
295
+ // pitfall: if the font is already loaded, ne never end.
296
+ // @review that
297
+
298
+ let ct = document.createElement('div');
299
+
300
+ ct.style.position = 'absolute';
301
+ ct.style.visibility = 'hidden';
302
+ ct.innerText = 'X';
303
+
304
+ document.body.appendChild(ct);
305
+
306
+ return new Promise<void>((resolve) => {
307
+
308
+ //let irc = ct.getBoundingClientRect();
309
+ const initialWidth = ct.offsetWidth;
310
+
311
+ let tm = setInterval(() => {
312
+
313
+ const newWidth = ct.offsetWidth;
314
+ if (newWidth!=initialWidth ) {
315
+ clearInterval(tm);
316
+ document.body.removeChild(ct);
317
+ resolve();
318
+ }
319
+ }, 0);
320
+ });
321
+ }
322
+
323
+ waitFontLoading( "montserrat" ).then( main );
324
+ //main( );
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "x4js_demo_app",
3
+ "version": "2.0.11",
4
+ "description": "X4 framework",
5
+ "author": "etienne cochard",
6
+ "main": "main.ts",
7
+ "scripts": {
8
+ "build": "node ../scripts/build.mjs --watch --hmr --serve",
9
+ "build-release": "node ../scripts/build.mjs --release"
10
+ },
11
+ "devDependencies": {
12
+ "x4js": "^2.0"
13
+ },
14
+ "x4build": {
15
+ "outdir": "build",
16
+ "copy": [
17
+ {
18
+ "from": "index.html",
19
+ "to": "index.html"
20
+ }
21
+ ]
22
+ },
23
+ "dependencies": {
24
+ "@fontsource/montserrat": "^5.1.0"
25
+ }
26
+ }
package/demo/scss.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare module '*.scss' {
2
+ const content: { [className: string]: string };
3
+ export default content;
4
+ }
package/demo/svg.d.ts ADDED
@@ -0,0 +1 @@
1
+ declare module '*.svg';
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "moduleResolution": "nodenext",
5
+ "module": "NodeNext",
6
+ "strictNullChecks": false,
7
+ "target": "ES2021",
8
+ "lib": [ "es2022", "DOM" ],
9
+ "paths": {
10
+ "@core/*": ["./src/core"],
11
+ "@comp/*": ["./src/components"]
12
+ }
13
+ }
14
+ }