flexdesk 0.4.6 → 0.5.0
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/README.md +140 -0
- package/css/base.css +123 -2
- package/css/flexdesk.css +127 -4
- package/css/overrides.css +4 -2
- package/css/tokens.css +14 -0
- package/dist/charts.js +3 -3
- package/dist/{chunk-ELXVW542.js → chunk-24MS7W5Y.js} +2 -2
- package/dist/{chunk-LH5TSOZW.js → chunk-6JSOVNID.js} +42 -2
- package/dist/{chunk-LH5TSOZW.js.map → chunk-6JSOVNID.js.map} +3 -3
- package/dist/{chunk-HWCX5I4R.js → chunk-CNXP3SIN.js} +3 -3
- package/dist/{chunk-CYTWMP2Y.js → chunk-KH2GJTKR.js} +1112 -32
- package/dist/chunk-KH2GJTKR.js.map +7 -0
- package/dist/flexdesk.css +127 -4
- package/dist/tiles.js +3 -3
- package/dist/tokens.css +14 -0
- package/dist/widgets.js +31 -5
- package/dist/widgets.js.map +1 -1
- package/dist/wm.js +79 -19
- package/dist/wm.js.map +3 -3
- package/package.json +1 -1
- package/src/tiling/landing_table.js +13 -5
- package/src/tiling/tile_breadcrumb.js +21 -0
- package/src/tiling/tile_renderer.js +11 -0
- package/src/tiling/wm.js +62 -18
- package/src/ui/components/data_table.js +961 -37
- package/src/ui/components/row_activation.js +70 -0
- package/src/ui/components/table_values.js +423 -0
- package/dist/chunk-CYTWMP2Y.js.map +0 -7
- /package/dist/{chunk-ELXVW542.js.map → chunk-24MS7W5Y.js.map} +0 -0
- /package/dist/{chunk-HWCX5I4R.js.map → chunk-CNXP3SIN.js.map} +0 -0
package/package.json
CHANGED
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
* pattern used by SFC / Markets / Scenarios / KPIs landings (and the
|
|
4
4
|
* market-archetype instances table). Three responsibilities:
|
|
5
5
|
*
|
|
6
|
-
* 1. Single-click row → open the entity (handled by callers).
|
|
6
|
+
* 1. Single-click row → open the entity (handled by callers). Since 0.5.0
|
|
7
|
+
* the click is judged by the same rule as `DataTable`'s `onRowActivate`
|
|
8
|
+
* (`ui/components/row_activation.js`); a table that owns its rows can
|
|
9
|
+
* use that option directly instead of this helper.
|
|
7
10
|
* 2. Right-click row → custom context menu with Open / Edit / Delete
|
|
8
11
|
* (replaces DataTable's default copy-as-TSV menu for these tables;
|
|
9
12
|
* the default still applies to data tables outside this helper).
|
|
@@ -16,6 +19,7 @@
|
|
|
16
19
|
*/
|
|
17
20
|
|
|
18
21
|
import { showContextMenu } from '../ui/components/context_menu.js';
|
|
22
|
+
import { isRowActivation } from '../ui/components/row_activation.js';
|
|
19
23
|
import { registerPanelKeys } from './panel_keys.js';
|
|
20
24
|
|
|
21
25
|
/** Attach the navigation-table interactions to a host element that
|
|
@@ -85,10 +89,14 @@ export function attachLandingTableBehavior(host, getRow, entityActions, options
|
|
|
85
89
|
dispatch(actionBtn.dataset.twmAction, tr ? getRow(tr.__rowIndex) : null);
|
|
86
90
|
return;
|
|
87
91
|
}
|
|
88
|
-
// Plain row click → open
|
|
89
|
-
//
|
|
90
|
-
// (
|
|
91
|
-
|
|
92
|
+
// Plain row click → open — by THE row-activation rule DataTable's own
|
|
93
|
+
// `onRowActivate` uses (0.5.0, `ui/components/row_activation.js`), so
|
|
94
|
+
// the two cannot drift: not on a control (a button, a field, a link),
|
|
95
|
+
// not on the click that ends a drag selecting a cell's text, and not on
|
|
96
|
+
// the second click of a double-click, which used to open the row twice.
|
|
97
|
+
// Anything outside a body row (pagination strip, header, empty space)
|
|
98
|
+
// is not a row either.
|
|
99
|
+
if (!isRowActivation(ev, 'click', { scope: host })) return;
|
|
92
100
|
const tr = bodyRowFor(ev);
|
|
93
101
|
if (tr) dispatch('open', getRow(tr.__rowIndex));
|
|
94
102
|
};
|
|
@@ -206,6 +206,27 @@ function _segments(kind, props, taxonomy, rootCrumb, rootLabel, navigate, trail)
|
|
|
206
206
|
return segs;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
+
/**
|
|
210
|
+
* C37. THE SAME STRIP FOR A CONTENT'S OWN LEVELS — the markup every tile
|
|
211
|
+
* breadcrumb draws, with segments the caller routes itself.
|
|
212
|
+
*
|
|
213
|
+
* `mountTileBreadcrumb` names where the TILE is, and every one of its segments
|
|
214
|
+
* climbs through the window manager. A page with levels that are not tabs (a
|
|
215
|
+
* section's list, one record opened in its place) has a trail the taxonomy
|
|
216
|
+
* cannot know and segments the WM cannot route; it draws them here, in the same
|
|
217
|
+
* markup and so the same look, and pairs it with a `navigateBack()` from its
|
|
218
|
+
* mount so Backspace climbs the same levels (`wm.navigateBack`, step 0).
|
|
219
|
+
*
|
|
220
|
+
* `segments` is `[{label, icon?, onClick?}]`; the last one — and any with no
|
|
221
|
+
* `onClick` — is drawn as the current one, as text. Redraws `container` in full.
|
|
222
|
+
*
|
|
223
|
+
* @param {HTMLElement} container
|
|
224
|
+
* @param {Array<{label: string, icon?: string, onClick?: Function}>} segments
|
|
225
|
+
*/
|
|
226
|
+
export function renderBreadcrumb(container, segments) {
|
|
227
|
+
_renderInto(container, segments);
|
|
228
|
+
}
|
|
229
|
+
|
|
209
230
|
function _renderInto(container, segments) {
|
|
210
231
|
container.innerHTML = '';
|
|
211
232
|
if (!segments?.length) return;
|
|
@@ -839,6 +839,17 @@ export class TileRenderer {
|
|
|
839
839
|
return (leaf && leaf.kind === 'leaf') ? this._leafKindKey(leaf) : null;
|
|
840
840
|
}
|
|
841
841
|
|
|
842
|
+
/**
|
|
843
|
+
* C37. WHAT A LEAF'S CONTENT FACTORY RETURNED for the tab on screen, or
|
|
844
|
+
* `null` — so the window manager can ask the content a question about
|
|
845
|
+
* itself (`wm.navigateBack`: *"have you a level of your own to go up?"*)
|
|
846
|
+
* without reaching into the cache. Read-only; a leaf that has not been
|
|
847
|
+
* rendered yet has none.
|
|
848
|
+
*/
|
|
849
|
+
contentOf(leafId) {
|
|
850
|
+
return this._leafCache.get(leafId)?.content ?? null;
|
|
851
|
+
}
|
|
852
|
+
|
|
842
853
|
/**
|
|
843
854
|
* C34. ACCEPT A PROPS WRITE THE CONTENT MADE ABOUT ITSELF, WITHOUT
|
|
844
855
|
* REBUILDING THE TILE THAT MADE IT.
|
package/src/tiling/wm.js
CHANGED
|
@@ -259,10 +259,22 @@ export class WindowManager {
|
|
|
259
259
|
* Adding a new "Open from X" click that should be a back-able
|
|
260
260
|
* navigation just needs to use one of the in-tile routing
|
|
261
261
|
* methods (openFromContext / openInLeaf / navigateActiveTab) —
|
|
262
|
-
* they all record history by default.
|
|
262
|
+
* they all record history by default.
|
|
263
|
+
*
|
|
264
|
+
* (0) C37. BEFORE ALL OF THAT, THE CONTENT'S OWN LEVELS. A page can have
|
|
265
|
+
* levels that are not tabs — a settings page whose section opened one
|
|
266
|
+
* member in place of its list, an organization page showing one of its
|
|
267
|
+
* projects — and Backspace must climb those before it walks the tile. The
|
|
268
|
+
* content factory says so by returning `navigateBack()` from its mount: it
|
|
269
|
+
* is asked first, in the scope Backspace acts on (`_backScope`, so a
|
|
270
|
+
* floating window's content and the focused tile's alike), and `true`
|
|
271
|
+
* means it climbed. `false`, or no such function, and the walk below runs
|
|
272
|
+
* exactly as it always has. */
|
|
263
273
|
navigateBack() {
|
|
264
274
|
const scope = this._backScope();
|
|
265
275
|
if (!scope) return;
|
|
276
|
+
// (0) C37. The content's own levels, when it has one above it.
|
|
277
|
+
if (this._contentNavigateBack(scope)) return;
|
|
266
278
|
// (1) Per-tab history, browser-style. Tiles only: a window keeps none.
|
|
267
279
|
if (scope.leafId && this._popTabHistory(scope.leafId)) return;
|
|
268
280
|
// (2) C32. A record beside an open list of its section closes onto it.
|
|
@@ -308,24 +320,35 @@ export class WindowManager {
|
|
|
308
320
|
}
|
|
309
321
|
|
|
310
322
|
/** True when `navigateBack` would do something user-visible — i.e.
|
|
311
|
-
* the
|
|
312
|
-
*
|
|
313
|
-
*
|
|
323
|
+
* the content has a level of its own above the one it shows (C37), the
|
|
324
|
+
* active tab has per-tab history, OR the current kind has a taxonomy
|
|
325
|
+
* parent. Used by the breadcrumb to grey out / hide the Back button when
|
|
326
|
+
* there's nowhere to go.
|
|
327
|
+
*
|
|
328
|
+
* IT ANSWERS FOR THE SCOPE BACKSPACE ACTS ON — `_backScope`'s: a floating
|
|
329
|
+
* window last pressed in, else the focused content tile, else the primary
|
|
330
|
+
* one. It used to pick the tile alone, so after a press inside a window it
|
|
331
|
+
* reported on the tile BEHIND it while Backspace climbed the window, and
|
|
332
|
+
* C37's question went to the wrong content. For a tile the answer is
|
|
333
|
+
* exactly what it always was; only a window scope answers differently. */
|
|
314
334
|
canNavigateBack() {
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
335
|
+
const scope = this._backScope();
|
|
336
|
+
if (!scope) return false;
|
|
337
|
+
const content = this._scopeContent(scope);
|
|
338
|
+
if (typeof content?.canNavigateBack === 'function') {
|
|
339
|
+
try { if (content.canNavigateBack() === true) return true; }
|
|
340
|
+
catch (err) { console.warn('[wm] content canNavigateBack threw', err); }
|
|
341
|
+
}
|
|
342
|
+
if (scope.leafId) {
|
|
343
|
+
const tree = this._tree();
|
|
344
|
+
const history = tree.activeTabHistory?.(scope.leafId) || [];
|
|
345
|
+
if (history.length > 0) return true;
|
|
346
|
+
const kind = tree.get(scope.leafId)?.content?.kind;
|
|
347
|
+
return !!(kind && this.taxonomy.parentKindFor(kind));
|
|
348
|
+
}
|
|
349
|
+
// A window keeps no per-tab history (`navigateBack`'s step 1 is tiles
|
|
350
|
+
// only), so what is left to it is its active tab's taxonomy parent.
|
|
351
|
+
const kind = this._scopeActiveTab(scope)?.kind;
|
|
329
352
|
return !!(kind && this.taxonomy.parentKindFor(kind));
|
|
330
353
|
}
|
|
331
354
|
|
|
@@ -409,6 +432,27 @@ export class WindowManager {
|
|
|
409
432
|
return src ? src.tabs[src.activeIdx] || null : null;
|
|
410
433
|
}
|
|
411
434
|
|
|
435
|
+
/** C37. What the scope's content factory returned for what is on screen:
|
|
436
|
+
* a window's `mountInfo`, or the tile's mounted content. */
|
|
437
|
+
_scopeContent(scope) {
|
|
438
|
+
if (scope?.windowId) return this._windowToLeaf.get(scope.windowId)?.mountInfo || null;
|
|
439
|
+
return scope?.leafId ? this.renderer?.contentOf?.(scope.leafId) || null : null;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/** C37. Ask the content to climb one of its own levels; `true` if it did.
|
|
443
|
+
* A content that throws is treated as having nowhere to go, so Backspace
|
|
444
|
+
* still walks the tile rather than doing nothing. */
|
|
445
|
+
_contentNavigateBack(scope) {
|
|
446
|
+
const content = this._scopeContent(scope);
|
|
447
|
+
if (typeof content?.navigateBack !== 'function') return false;
|
|
448
|
+
try {
|
|
449
|
+
return content.navigateBack() === true;
|
|
450
|
+
} catch (err) {
|
|
451
|
+
console.warn('[wm] content navigateBack threw', err);
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
412
456
|
/** Replace what a scope shows, in place: the tile's active tab (recording
|
|
413
457
|
* history) or the window's content. */
|
|
414
458
|
_navigateInScope(scope, kind, props = {}) {
|