lexgui 0.5.3 → 0.5.4

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.
@@ -11,14 +11,33 @@
11
11
  .bg-error { background-color: var(--global-color-error) !important }
12
12
  .bg-none { background: none !important }
13
13
 
14
+ .hover\:bg-primary:hover { background-color: var(--global-color-primary) !important }
15
+ .hover\:bg-secondary:hover { background-color: var(--global-color-secondary) !important }
16
+ .hover\:bg-tertiary:hover { background-color: var(--global-color-tertiary) !important }
17
+ .hover\:bg-quaternary:hover { background-color: var(--global-color-quaternary) !important }
18
+ .hover\:bg-accent:hover { background-color: var(--global-color-accent) !important }
19
+ .hover\:bg-contrast:hover { background-color: var(--global-text-primary) !important }
20
+ .hover\:bg-warning:hover { background-color: var(--global-color-warning) !important }
21
+ .hover\:bg-error:hover { background-color: var(--global-color-error) !important }
22
+ .hover\:bg-none:hover { background: none !important }
23
+
14
24
  .fg-primary { color: var(--global-text-primary) !important }
15
25
  .fg-secondary { color: var(--global-text-secondary) !important }
16
26
  .fg-tertiary { color: var(--global-text-tertiary) !important }
17
27
  .fg-quaternary { color: var(--global-text-quaternary) !important }
18
- .fg-accent { color: var(--global-text-accent) !important }
19
- .fg-contrast { color: var(--global-text-primary) !important }
20
- .fg-warning { color: var(--global-text-warning) !important }
21
- .fg-error { color: var(--global-text-error) !important }
28
+ .fg-accent { color: var(--global-color-accent) !important }
29
+ .fg-contrast { color: var(--global-color-primary) !important }
30
+ .fg-warning { color: var(--global-color-warning) !important }
31
+ .fg-error { color: var(--global-color-error) !important }
32
+
33
+ .hover\:fg-primary:hover { color: var(--global-text-primary) !important }
34
+ .hover\:fg-secondary:hover { color: var(--global-text-secondary) !important }
35
+ .hover\:fg-tertiary:hover { color: var(--global-text-tertiary) !important }
36
+ .hover\:fg-quaternary:hover { color: var(--global-text-quaternary) !important }
37
+ .hover\:fg-accent:hover { color: var(--global-color-accent) !important }
38
+ .hover\:fg-contrast:hover { color: var(--global-color-primary) !important }
39
+ .hover\:fg-warning:hover { color: var(--global-color-warning) !important }
40
+ .hover\:fg-error:hover { color: var(--global-color-error) !important }
22
41
 
23
42
  /* Layout */
24
43
 
@@ -29,13 +48,32 @@
29
48
  .inline-block { display: inline-block }
30
49
  .hidden { display: none !important }
31
50
 
51
+ .overflow-auto { overflow: auto }
52
+ .overflow-scroll { overflow: scroll }
53
+ .overflow-hidden { overflow: hidden }
54
+ .overflow-x-auto { overflow-x: auto }
55
+ .overflow-y-auto { overflow-y: auto }
56
+ .overflow-x-hidden { overflow-x: hidden }
57
+
58
+ .truncate { overflow: hidden; text-overflow: ellipsis }
59
+ .truncate, .whitespace-nowrap { white-space: nowrap }
60
+ .whitespace-pre-wrap { white-space: pre-wrap }
61
+ .whitespace-break-spaces { white-space: break-spaces }
62
+
63
+ .text-balance { text-wrap: balance }
64
+ .break-words { overflow-wrap: break-word }
65
+
66
+ .line-clamp-1, .line-clamp-2 { overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical }
67
+ .line-clamp-1 { -webkit-line-clamp: 1; line-clamp: 1 }
68
+ .line-clamp-2 { -webkit-line-clamp: 2; line-clamp: 2 }
69
+
32
70
  .flex-col { flex-direction: column }
33
71
  .flex-row { flex-direction: row }
34
72
  .flex-wrap { flex-wrap: wrap }
35
73
 
36
- .items-center { align-items: center }
37
- .items-start { align-items: flex-start }
38
- .items-end { align-items: flex-end }
74
+ .items-start { place-items: start }
75
+ .items-center { place-items: center }
76
+ .items-end { place-items: end }
39
77
 
40
78
  .justify-start { justify-content: start }
41
79
  .justify-center { justify-content: center }
@@ -43,8 +81,12 @@
43
81
  .justify-between { justify-content: space-between }
44
82
  .justify-around { justify-content: space-around }
45
83
 
46
- .self-center { align-self: center }
84
+ .self-start { place-self: start }
85
+ .self-center { place-self: center }
86
+ .self-end { place-self: end }
47
87
 
88
+ .gap-0 { gap: 0 }
89
+ .gap-0\.5 { gap: 0.125rem }
48
90
  .gap-1 { gap: 0.25rem }
49
91
  .gap-2 { gap: 0.5rem }
50
92
  .gap-3 { gap: 0.75rem }
@@ -71,10 +113,45 @@
71
113
  .m-7 { margin: 1.75rem }
72
114
  .m-8 { margin: 2rem }
73
115
 
116
+ .mt-0 { margin-top: 0 }
117
+ .mt-1 { margin-top: 0.25rem }
74
118
  .mt-2 { margin-top: 0.5rem }
119
+ .mt-3 { margin-top: 0.75rem }
120
+ .mt-4 { margin-top: 1rem }
121
+ .mt-5 { margin-top: 1.25rem }
122
+ .mt-6 { margin-top: 1.5rem }
123
+ .mt-7 { margin-top: 1.75rem }
124
+ .mt-8 { margin-top: 2rem }
125
+
126
+ .mb-0 { margin-bottom: 0 }
127
+ .mb-1 { margin-bottom: 0.25rem }
75
128
  .mb-2 { margin-bottom: 0.5rem }
129
+ .mb-3 { margin-bottom: 0.75rem }
130
+ .mb-4 { margin-bottom: 1rem }
131
+ .mb-5 { margin-bottom: 1.25rem }
132
+ .mb-6 { margin-bottom: 1.5rem }
133
+ .mb-7 { margin-bottom: 1.75rem }
134
+ .mb-8 { margin-bottom: 2rem }
135
+
136
+ .ml-0 { margin-left: 0 }
137
+ .ml-1 { margin-left: 0.25rem }
76
138
  .ml-2 { margin-left: 0.5rem }
139
+ .ml-3 { margin-left: 0.75rem }
140
+ .ml-4 { margin-left: 1rem }
141
+ .ml-5 { margin-left: 1.25rem }
142
+ .ml-6 { margin-left: 1.5rem }
143
+ .ml-7 { margin-left: 1.75rem }
144
+ .ml-8 { margin-left: 2rem }
145
+
146
+ .mr-0 { margin-right: 0 }
147
+ .mr-1 { margin-right: 0.25rem }
77
148
  .mr-2 { margin-right: 0.5rem }
149
+ .mr-3 { margin-right: 0.75rem }
150
+ .mr-4 { margin-right: 1rem }
151
+ .mr-5 { margin-right: 1.25rem }
152
+ .mr-6 { margin-right: 1.5rem }
153
+ .mr-7 { margin-right: 1.75rem }
154
+ .mr-8 { margin-right: 2rem }
78
155
 
79
156
  .p-0 { padding: 0 }
80
157
  .p-1 { padding: 0.25rem }
@@ -135,6 +212,8 @@
135
212
  .px-6 { padding-left: 1.5rem; padding-right: 1.5rem }
136
213
  .px-7 { padding-left: 1.75rem; padding-right: 1.75rem }
137
214
  .px-8 { padding-left: 2rem; padding-right: 2rem }
215
+ .px-10 { padding-left: 2.5rem; padding-right: 2.5rem }
216
+ .px-12 { padding-left: 3rem; padding-right: 3rem }
138
217
 
139
218
  .py-0 { padding-top: 0; padding-bottom: 0 }
140
219
  .py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem }
@@ -145,9 +224,18 @@
145
224
  .py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem }
146
225
  .py-7 { padding-top: 1.75rem; padding-bottom: 1.75rem }
147
226
  .py-8 { padding-top: 2rem; padding-bottom: 2rem }
227
+ .py-10 { padding-top: 2.5rem; padding-bottom: 2.5rem }
228
+ .py-12 { padding-top: 3rem; padding-bottom: 3rem }
148
229
 
149
230
  /* Typography */
150
231
 
232
+ .text-xs { font-size: var(--global-font-size-xs); line-height: 0.9rem }
233
+ .text-sm { font-size: var(--global-font-size-sm); line-height: 1rem }
234
+ .text-md { font-size: var(--global-font-size); line-height: 1.2rem }
235
+ .text-lg { font-size: var(--global-font-size-lg); line-height: 1.3rem }
236
+ .text-xl { font-size: var(--global-font-size-xl); line-height: 1.4rem }
237
+ .text-xxl { font-size: var(--global-font-size-xxl); line-height: 1.6rem }
238
+
151
239
  .font-light { font-weight: 300 }
152
240
  .font-normal { font-weight: 400 }
153
241
  .font-medium { font-weight: 500 }
@@ -188,8 +276,19 @@
188
276
  /* Borders / Radius / Shadow */
189
277
 
190
278
  .border { border: 1px solid var(--global-color-tertiary) }
279
+
280
+ .border-top { border-top: 1px solid var(--global-color-tertiary) }
281
+ .border-bottom { border-bottom: 1px solid var(--global-color-tertiary) }
282
+ .border-left { border-left: 1px solid var(--global-color-tertiary) }
283
+ .border-right { border-right: 1px solid var(--global-color-tertiary) }
284
+
191
285
  .border-2 { border-width: 2px }
192
286
 
287
+ .border-t-0 { border-top-width: 0 }
288
+ .border-b-0 { border-bottom-width: 0 }
289
+ .border-l-0 { border-left-width: 0 }
290
+ .border-r-0 { border-right-width: 0 }
291
+
193
292
  .rounded-none { border-radius: 0 }
194
293
  .rounded { border-radius: 0.25rem }
195
294
  .rounded-lg { border-radius: 0.5rem }
package/changelog.md CHANGED
@@ -2,7 +2,22 @@
2
2
 
3
3
  ## dev
4
4
 
5
- ## 0.5.3 (master)
5
+ ## 0.5.4 (master)
6
+
7
+ Widgets:
8
+ - Added support for disabling resize in TextArea Widget `options.resize: false`.
9
+ - Added support for using LX.ICONS on Button Widgets.
10
+ - Tooltips supported in Button Widget `options.tooltip`. Uses either `options.title` or `name` as content.
11
+
12
+ `LX.makeContainer` now accepts `innerHTML` and `parent` params.
13
+ Started work on tooltips `LX.asTooltip(trigger, content)`.
14
+ Added support for adding a class to LexGUI root on init `options.rootClass`.
15
+ Added support for adding a class to Sidebar/Menubar areas on `Area.addSidebar` and `Area.addMenubar`.
16
+ Added `options.asElement` to return `LX.badge` as HTMLElement instead of html string.
17
+ Support for using LX.ICONS on sidebar entry icons. Keep FA icons as legacy by now.
18
+ Minor CSS improvements. Added more class utilities.
19
+
20
+ ## 0.5.3
6
21
 
7
22
  Widgets:
8
23
  - Fixed Select Widget filter issues.
package/demo.js CHANGED
@@ -5,21 +5,21 @@ import 'lexgui/components/audio.js';
5
5
 
6
6
  window.LX = LX;
7
7
 
8
- let area = LX.init( { strictViewport: false } );
8
+ const area = LX.init( { strictViewport: false, rootClass: "wrapper" } );
9
9
 
10
10
  // Menubar
11
11
  {
12
12
  area.addMenubar( m => {
13
-
13
+
14
14
  m.setButtonImage("lexgui.js", "images/icon.png", () => {window.open("https://jxarco.github.io/lexgui.js/")}, {float: "left"})
15
-
15
+
16
16
  m.add( "Docs", { icon: "fa-solid fa-magnifying-glass", short: "F1", callback: () => { window.open("./docs/") }});
17
-
17
+
18
18
  const commandButton = new LX.Button(null, "Search command...", () => { LX.setCommandbarState( true ) }, {
19
19
  width: "256px", className: "right", buttonClass: "outline left fg-tertiary bg-secondary" }
20
20
  );
21
21
  m.root.appendChild( commandButton.root );
22
-
22
+
23
23
  m.addButtons( [
24
24
  {
25
25
  title: "Github",
@@ -40,40 +40,379 @@ let area = LX.init( { strictViewport: false } );
40
40
 
41
41
  // Header
42
42
  {
43
- const header = LX.makeContainer( [ null, "auto" ], "col border gap-2 p-8" );
44
-
45
- header.innerHTML = `
43
+ const header = LX.makeContainer( [ null, "auto" ], "flex flex-col border-top border-bottom gap-2 px-6 py-12", `
46
44
  <a>Get started with LexGUI.js</a>
47
45
  <h1>Build your application interface</h1>
48
- <p style="max-width:32rem">A set of beautifully-designed, accessible widgets and components.
46
+ <p class="font-light" style="max-width:32rem">A set of beautifully-designed, accessible widgets and components.
49
47
  No complex frameworks. Pure JavaScript and CSS. Open Source.</p>
50
- `;
51
-
52
- area.attach( header );
48
+ `, area );
53
49
  }
54
50
 
55
51
  // Content
56
52
  {
57
- const tabs = area.addTabs( { sizes: [ "auto", "auto" ], contentClass: "p-6 pt-0" } );
58
- tabs.root.parentElement.classList.add( "p-4" );
53
+ const tabs = area.addTabs( { parentClass: "p-4", sizes: [ "auto", "auto" ], contentClass: "p-6 pt-0" } );
54
+
55
+ // Editor
56
+ {
57
+ const editorContainer = LX.makeContainer( [ null, "800px" ], "flex flex-col bg-primary border rounded-lg overflow-hidden" );
58
+ tabs.add( "Editor", editorContainer, { selected: true } );
59
+
60
+ const editorArea = new LX.Area({ className: "rounded-lg" });
61
+ editorContainer.appendChild( editorArea.root );
62
+
63
+ editorArea.addMenubar( m => {
64
+ m.add( "Scene/New Scene", () => { console.log("New scene created!") });
65
+ m.add( "Scene/Open Scene", { icon: "fa-solid fa-folder-open", short: "S" } );
66
+ m.add( "Scene/Open Recent/hello.scene" );
67
+ m.add( "Scene/Open Recent/goodbye.scene" );
68
+ m.add( "Project/Project Settings", { disabled: true } );
69
+ m.add( "Project/" );
70
+ m.add( "Project/Export", { icon: "fa-solid fa-download" });
71
+ m.add( "Project/Export/DAE", { icon: "fa-solid fa-cube", short: "D" } );
72
+ m.add( "Project/Export/GLTF", { short: "G" } );
73
+ m.add( "Account/Login", { icon: "fa-solid fa-user" } );
74
+ m.add( "Help/Search Help", { icon: "fa-solid fa-magnifying-glass", short: "F1" } );
75
+ m.add( "Help/Support LexGUI/Please", { icon: "fa-solid fa-heart" } );
76
+ m.add( "Help/Support LexGUI/Do it" );
77
+ m.addButtons( [
78
+ {
79
+ title: "Play",
80
+ icon: "fa-solid fa-play",
81
+ swap: "fa-solid fa-stop"
82
+ },
83
+ {
84
+ title: "Pause",
85
+ icon: "fa-solid fa-pause",
86
+ disabled: true
87
+ }
88
+ ]);
89
+ }, { sticky: false });
90
+
91
+ // split main area
92
+ const [ left, right ] = editorArea.split({ sizes:["70%","30%"], minimizable: true });
93
+
94
+ // add canvas to left upper part
95
+ const canvas = document.createElement('canvas');
96
+ canvas.style.width = "100%";
97
+ canvas.style.height = "100%";
98
+ canvas.width = left.root.offsetWidth;
99
+ canvas.height = left.root.offsetHeight
100
+
101
+ const resizeCanvas = ( bounding ) => {
102
+ canvas.width = bounding.width;
103
+ canvas.height = bounding.height;
104
+ };
105
+
106
+ left.attach( canvas );
107
+ left.onresize = resizeCanvas;
108
+ left.addOverlayButtons( [
109
+ [
110
+ { name: "Select", icon: "fa fa-arrow-pointer", selectable: true },
111
+ { name: "Move", icon: "fa-solid fa-arrows-up-down-left-right", selectable: true },
112
+ { name: "Rotate", icon: "fa-solid fa-rotate-right", selectable: true }
113
+ ],
114
+ { name: "Lit", options: ["Lit", "Unlit", "Wireframe"] },
115
+ [
116
+ { name: "Enable Snap", icon: "fa fa-table-cells", selectable: true },
117
+ { name: 10, options: [10, 100, 1000] }
118
+ ]
119
+ ], { float: "htc" } );
120
+
121
+ // add panels
122
+ var sidePanel = right.addPanel();
123
+ fillPanel( sidePanel );
124
+
125
+ function loop(dt) {
126
+
127
+ var ctx = canvas.getContext("2d");
128
+ ctx.fillStyle = sidePanel.getValue('Background');
129
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
130
+ ctx.font = `${ sidePanel.getValue('Font Size') }px ${ sidePanel.getValue('Font Family') }`;
131
+ ctx.fillStyle = sidePanel.getValue('Font Color');
132
+ const pos2D = sidePanel.getValue('2D Position');
133
+ ctx.fillText( sidePanel.getValue('Text'), pos2D[0], pos2D[1]);
134
+ requestAnimationFrame(loop);
135
+ }
136
+
137
+ requestAnimationFrame(loop);
138
+
139
+ // **** **** **** **** **** **** **** **** **** **** **** ****
140
+
141
+ function fillPanel( panel ) {
142
+
143
+ // Add data tree
144
+
145
+ let sceneData = {
146
+ 'id': 'root',
147
+ 'children': [
148
+ {
149
+ 'id': 'node_1',
150
+ 'children': [
151
+ {
152
+ 'id': 'node_1_1',
153
+ 'icon': 'fa-solid fa-cube',
154
+ 'children': [],
155
+ 'actions': [
156
+ {
157
+ 'name': 'Open script',
158
+ 'icon': 'fa-solid fa-scroll'
159
+ }
160
+ ]
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ 'id': 'node_2',
166
+ 'icon': 'fa-solid fa-circle-play',
167
+ 'children': []
168
+ }
169
+ ]
170
+ };
171
+
172
+ // This is optional!
173
+ const treeIcons = [
174
+ {
175
+ 'name':'Add node',
176
+ 'icon': 'fa-solid fa-plus'
177
+ },
178
+ {
179
+ 'name':'Instantiate scene',
180
+ 'icon': 'fa-solid fa-link'
181
+ }
182
+ ];
183
+
184
+ window.tree = panel.addTree("Scene Tree", sceneData, {
185
+ icons: treeIcons,
186
+ addDefault: true,
187
+ onevent: (event) => {
188
+ switch(event.type) {
189
+ case LX.TreeEvent.NODE_CONTEXTMENU:
190
+ const m = event.panel;
191
+ m.add( "Components/Transform");
192
+ m.add( "Components/MeshRenderer");
193
+ break;
194
+ }
195
+ }
196
+ });
197
+
198
+ // add widgets to panel branch
199
+ panel.branch("Canvas", {icon: "fa-solid fa-palette", filter: true});
200
+ panel.addColor("Background", "#b7a9b1", null);
201
+ panel.addText("Text", "LexGUI.js @jxarco", null, {placeholder: "e.g. ColorPicker", icon: "fa fa-font"});
202
+ panel.addColor("Font Color", "#303b8d", null);
203
+ panel.addNumber("Font Size", 36, null, { min: 1, max: 48, step: 1, units: "px"});
204
+ panel.addSelect("Font Family", ["Arial", "GeistSans", "Monospace"], "GeistSans");
205
+ panel.addVector2("2D Position", [300, 350], null, { min: 0, max: 1024 });
206
+ const opacityValues = [
207
+ [0.2, 0.3146875],
208
+ [0.417313915857606, 0.8946875000000003],
209
+ [0.5495145631067961, 0.6746875],
210
+ [1, 1]
211
+ ];
212
+ panel.addCurve("Opacity", opacityValues);
213
+ panel.addSize("Resolution", [1280, 720], null, { units: "p", precision: 0 });
214
+ panel.merge();
215
+
216
+ panel.branch("Node", { icon: "fa-solid fa-cube" });
217
+ panel.addText("Name", "node_1");
218
+ panel.addCheckbox("Visibility", true, null, { className: "accent" });
219
+ panel.addLayers("Layers", 10, null);
220
+
221
+ panel.addTitle( "Transform" );
222
+ panel.addVector3( "Position", [0.0, 0.0, 0.0] );
223
+ panel.addVector4( "Rotation", [0.0, 0.0, 0.0, 1.0] );
224
+ panel.addVector3( "Scale", [1.0, 1.0, 1.0] );
225
+ panel.addButton(null, "Export", null, { buttonClass: "contrast" });
226
+ panel.merge();
227
+ }
228
+ }
59
229
 
60
230
  // Mail
61
231
  {
62
- const mailContainer = LX.makeContainer( [ null, "auto" ], "col bg-primary border rounded-lg p-6" );
63
- tabs.add( "Mail", mailContainer, { selected: true } );
232
+ const mailContainer = LX.makeContainer( [ null, "800px" ], "flex flex-col bg-primary border rounded-lg overflow-hidden" );
233
+ tabs.add( "Mail", mailContainer, { xselected: true } );
234
+
235
+ const mailArea = new LX.Area();
236
+ mailContainer.appendChild( mailArea.root );
237
+ const badgeClass = "ml-auto no-bg font-medium";
238
+
239
+ const sidebar = mailArea.addSidebar( m => {
240
+ m.add( "Inbox", { selected: true, icon: "inbox", content: LX.badge("128", badgeClass, { asElement: true }) } );
241
+ m.add( "Drafts", { icon: "file", content: LX.badge("9", badgeClass, { asElement: true }) } );
242
+ m.add( "Sent", { icon: "paper-plane" } );
243
+ m.add( "Junk", { icon: "box-archive-x", content: LX.badge("23", badgeClass, { asElement: true }) } );
244
+ m.add( "Trash", { icon: "trash-can" } );
245
+ m.add( "Archive", { icon: "box-archive" } );
246
+ m.separator();
247
+ m.add( "Social", { icon: "user", content: LX.badge("972", badgeClass, { asElement: true }) } );
248
+ m.add( "Updates", { icon: "circle-info", content: LX.badge("342", badgeClass, { asElement: true }) } );
249
+ m.add( "Forums", { icon: "comments", content: LX.badge("96", badgeClass, { asElement: true }) } );
250
+ m.add( "Shopping ", { icon: "shopping-cart" } );
251
+ m.add( "Promotions", { icon: "flag", content: LX.badge("21", badgeClass, { asElement: true }) } );
252
+ }, {
253
+ // collapseToIcons: false,
254
+ className: "border-right",
255
+ headerTitle: "jxarco",
256
+ headerSubtitle: "alexroco.30@gmail.com",
257
+ headerImage: "https://raw.githubusercontent.com/jxarco/lexgui.js/refs/heads/master/images/icon.png",
258
+ skipFooter: true,
259
+ displaySelected: true,
260
+ onHeaderPressed: (e, element) => { }
261
+ });
262
+
263
+ const inboxArea = sidebar.siblingArea;
264
+
265
+ var [ left, right ] = inboxArea.split({ sizes:["40%","60%"] });
266
+ left.setLimitBox( 350, null, 650, null );
267
+
268
+ // Manage Inbox
269
+ {
270
+ const inboxTabs = left.addTabs({ parentClass: "flex p-3 items-end border-bottom", sizes: [ "auto", "auto" ], float: "end" });
271
+ const tabsRowContainer = inboxTabs.root.parentElement;
272
+
273
+ const mailSectionTitle = LX.makeContainer( [ "auto", "auto" ], "mr-auto ml-2 self-center text-xxl font-semibold", "Inbox" );
274
+ tabsRowContainer.prepend( mailSectionTitle );
275
+
276
+ window.__showMailList = ( container, unreadOnly = false ) => {
277
+
278
+ // Filter
279
+ {
280
+ const allMailFilter = LX.makeContainer( [ "100%", "50px" ], "flex p-2", "", container );
281
+ const filterInput = new LX.TextInput(null, "", null,
282
+ { inputClass: "outline", width: "100%", icon: "fa fa-magnifying-glass", placeholder: "Search..." }
283
+ );
284
+ allMailFilter.appendChild( filterInput.root );
285
+ }
286
+
287
+ // Content
288
+ {
289
+ const allMailContent = LX.makeContainer( [ "100%", "calc(100% - 50px)" ], "flex flex-col p-4 pt-0 gap-2 overflow-scroll", "", container );
290
+
291
+ window.__addMail = ( mail, mailContainer ) => {
292
+
293
+ const msgContent = LX.makeContainer( [ "100%", "auto" ],
294
+ "flex flex-col border p-3 rounded-lg gap-2 select-none hover:bg-secondary cursor-pointer", "", mailContainer );
295
+
296
+ // Name, subject, date
297
+ {
298
+ const msgInfo = LX.makeContainer( [ "100%", "auto" ], "flex flex-col gap-0.5", "", msgContent );
299
+ const msgNameDate = LX.makeContainer( [ "100%", "auto" ], "flex flex-row", "", msgInfo );
300
+
301
+ // Name + Date
302
+ {
303
+ const msgName = LX.makeContainer( [ "auto", "auto" ], "flex font-semibold text-md gap-2", "", msgNameDate );
304
+ msgName.innerHTML = mail.name;
305
+ msgName.innerHTML += ( mail.read ? "" : `<span class="rounded-full self-center bg-accent" style="width: 8px; height: 8px"></span>` );
306
+ const msgDate = LX.makeContainer( [ "auto", "auto" ], "fg-tertiary text-sm ml-auto self-center", mail.date, msgNameDate );
307
+ }
308
+
309
+ const msgSubject = LX.makeContainer( [ "100%", "auto" ], "font-semibold text-sm", mail.subject, msgInfo );
310
+ }
311
+
312
+ const msgText = LX.makeContainer( [ "100%", "auto" ], "text-sm line-clamp-2 fg-tertiary", mail.content, msgContent );
313
+ const msgTags = LX.makeContainer( [ "100%", "auto" ], "flex flex-row gap-0.5 font-semibold", "", msgContent );
314
+ for( const tag of mail.tags )
315
+ {
316
+ msgTags.appendChild( LX.badge( tag, "sm", { asElement: true } ) );
317
+ }
318
+
319
+ msgContent.listen( "click", () => {
320
+ window.__openMail( mail );
321
+ } );
322
+ };
323
+
324
+ LX.requestJSON( "data/example_mail_data.json", data => {
325
+ data.forEach( e => { if( !unreadOnly || ( unreadOnly && !e.read ) ) window.__addMail( e, allMailContent ) } );
326
+ window.__openMail( data[ 0 ] );
327
+ } )
328
+ }
329
+ }
330
+
331
+ const allMailContainer = LX.makeContainer( [ "100%", "100%" ], "flex flex-col" );
332
+ inboxTabs.add( "All mail", allMailContainer, { selected: true } );
333
+ window.__showMailList( allMailContainer );
334
+
335
+ const unreadMailContainer = LX.makeContainer( [ "100%", "100%" ], "flex flex-col" );
336
+ inboxTabs.add( "Unread", unreadMailContainer );
337
+ window.__showMailList( unreadMailContainer, true );
338
+ }
339
+
340
+ // Manage Message Preview
341
+ {
342
+ // Buttons
343
+ {
344
+ const mailPreviewHeader = LX.makeContainer( [ "100%", "59.59px" ], "flex flex-row border-bottom p-1", "", right );
345
+
346
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Archive", tooltip: true, buttonClass: "bg-none", icon: "box-archive" } ).root );
347
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Move to junk", tooltip: true, buttonClass: "bg-none", icon: "box-archive-x" } ).root );
348
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Move to trash", tooltip: true, buttonClass: "bg-none", icon: "trash-can" } ).root );
349
+ mailPreviewHeader.appendChild( LX.makeContainer( [ "1px", "35%" ], "border-right self-center ml-2 mr-2" ) );
350
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Snooze", tooltip: true, buttonClass: "bg-none", icon: "clock" } ).root );
351
+
352
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Reply", tooltip: true, buttonClass: "bg-none", className: "ml-auto", icon: "reply" } ).root );
353
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Reply all", tooltip: true, buttonClass: "bg-none", icon: "reply-all" } ).root );
354
+ mailPreviewHeader.appendChild( new LX.Button( null, "", null, { title: "Forward", tooltip: true, buttonClass: "bg-none", icon: "forward" } ).root );
355
+ mailPreviewHeader.appendChild( LX.makeContainer( [ "1px", "35%" ], "border-right self-center ml-2 mr-2" ) );
356
+ mailPreviewHeader.appendChild( new LX.Button( null, "", (value, event) => {
357
+ new LX.DropdownMenu( event.target, [
358
+ { name: "Mark as unread" },
359
+ { name: "Star thread" },
360
+ { name: "Add label" },
361
+ { name: "Mute thread" }
362
+ ], { side: "bottom", align: "end" });
363
+ }, { buttonClass: "bg-none", icon: "more" } ).root );
364
+ }
365
+
366
+ // Prewiew Info
367
+ {
368
+ const previewDataContent = LX.makeContainer( [ "100%", "100%" ], "", "", right );
369
+
370
+ window.__openMail = ( mail ) => {
371
+
372
+ previewDataContent.innerHTML = "";
373
+
374
+ const mailPreviewInfo = LX.makeContainer( [ "100%", "auto" ], "flex flex-row border-bottom p-6", "", previewDataContent );
375
+
376
+ const senderData = LX.makeContainer( [ "100%", "auto" ], "flex flex-col gap-0.5", `
377
+ <div class="text-md font-semibold">${ mail.name }</div>
378
+ <div class="text-sm">${ mail.subject }</div>
379
+ <div class="text-sm">Reply-To: ${ mail.email }</div>
380
+ `, mailPreviewInfo );
381
+
382
+ const exactDate = LX.makeContainer( [ "100%", "auto" ], "flex flex-row text-sm fg-tertiary justify-end", mail.exactDate, mailPreviewInfo );
383
+ const mailPreviewContent = LX.makeContainer( [ "100%", "505px" ], "flex flex-row border-bottom text-md whitespace-pre-wrap p-4", mail.content, previewDataContent );
384
+ const previewFooter = LX.makeContainer( [ "100%", "auto" ], "flex flex-col p-2", "", previewDataContent );
385
+
386
+ const msgReplyTextArea = new LX.TextArea(null, "", null,
387
+ { className: "mt-1", inputClass: "outline", width: "100%", resize: false, placeholder: `Reply ${ mail.name }` }
388
+ );
389
+ previewFooter.appendChild( msgReplyTextArea.root );
390
+
391
+ const previewButtons = LX.makeContainer( [ "100%", "auto" ], "flex flex-row p-1", "", previewFooter );
392
+
393
+ const muteToggle = new LX.Toggle( null, false, null, { label: "Mute this thread", className: "contrast" } );
394
+ previewButtons.appendChild( muteToggle.root );
395
+
396
+ const sendButton = new LX.Button( null, "Send", () => {
397
+ LX.toast( "Message sent!", "To:" + mail.email, { timeout: 5000, action: { name: "Undo", callback: ( toast, actionName, event ) => {
398
+ toast.close();
399
+ } } } );
400
+ }, { className: "ml-auto", buttonClass: "contrast" } );
401
+ previewButtons.appendChild( sendButton.root );
402
+ };
403
+ }
404
+ }
64
405
  }
65
406
 
66
407
  // Tasks
67
408
  {
68
- const tasksContainer = LX.makeContainer( [ null, "auto" ], "col bg-primary border rounded-lg p-6" );
409
+ const tasksContainer = LX.makeContainer( [ null, "auto" ], "col bg-primary border rounded-lg p-6 overflow-hidden" );
69
410
  tabs.add( "Tasks", tasksContainer, { xselected: true } );
70
411
 
71
- const header = LX.makeContainer( [ null, "auto" ], "col rounded-lg p-6" );
72
- header.innerHTML = `
412
+ const header = LX.makeContainer( [ null, "auto" ], "col p-4", `
73
413
  <h2>Welcome back!</h2>
74
414
  <p class="fg-tertiary">Here's a list of your tasks for this month!</p>
75
- `;
76
- tasksContainer.appendChild( header );
415
+ `, tasksContainer );
77
416
 
78
417
  const tableWidget = new LX.Table(null, {
79
418
  head: ["Name", "Status", "Priority"],
@@ -114,31 +453,22 @@ let area = LX.init( { strictViewport: false } );
114
453
  }
115
454
 
116
455
  // Code
117
- {
118
- const codeContainer = LX.makeContainer( [ "auto", "850px" ], "", {
119
- backgroundColor: "red"
120
- } );
456
+ // {
457
+ // const codeContainer = LX.makeContainer( [ "auto", "850px" ], "", {
458
+ // backgroundColor: "red"
459
+ // } );
121
460
 
122
- tabs.add( "Code", codeContainer );
123
- }
461
+ // tabs.add( "Code", codeContainer );
462
+ // }
124
463
 
125
464
  // Audio
126
- {
127
- const audioContainer = LX.makeContainer( [ "auto", "850px" ], "", {
128
- backgroundColor: "red"
129
- } );
465
+ // {
466
+ // const audioContainer = LX.makeContainer( [ "auto", "850px" ], "", {
467
+ // backgroundColor: "red"
468
+ // } );
130
469
 
131
- tabs.add( "Audio", audioContainer );
132
- }
133
-
134
- // Examples
135
- {
136
- const examplesContainer = LX.makeContainer( [ "auto", "850px" ], "", {
137
- backgroundColor: "red"
138
- } );
139
-
140
- tabs.add( "Examples", examplesContainer );
141
- }
470
+ // tabs.add( "Audio", audioContainer );
471
+ // }
142
472
  }
143
473
 
144
474
  // Footer