flexdesk 0.1.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.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +195 -0
  3. package/THIRD_PARTY_LICENSES.md +53 -0
  4. package/css/base.css +3439 -0
  5. package/css/flexdesk.css +5797 -0
  6. package/css/overrides.css +2349 -0
  7. package/css/reset.css +46 -0
  8. package/css/tokens.css +137 -0
  9. package/dist/charts.js +780 -0
  10. package/dist/charts.js.map +7 -0
  11. package/dist/chunk-3PHCPZHT.js +222 -0
  12. package/dist/chunk-3PHCPZHT.js.map +7 -0
  13. package/dist/chunk-CT4YXXLP.js +1770 -0
  14. package/dist/chunk-CT4YXXLP.js.map +7 -0
  15. package/dist/chunk-DRYCDMEG.js +2217 -0
  16. package/dist/chunk-DRYCDMEG.js.map +7 -0
  17. package/dist/chunk-DVU44T77.js +855 -0
  18. package/dist/chunk-DVU44T77.js.map +7 -0
  19. package/dist/chunk-FL5KFNQH.js +640 -0
  20. package/dist/chunk-FL5KFNQH.js.map +7 -0
  21. package/dist/chunk-FOOS3T5L.js +117 -0
  22. package/dist/chunk-FOOS3T5L.js.map +7 -0
  23. package/dist/chunk-JYWURG5T.js +32 -0
  24. package/dist/chunk-JYWURG5T.js.map +7 -0
  25. package/dist/chunk-TLZUUFOE.js +276 -0
  26. package/dist/chunk-TLZUUFOE.js.map +7 -0
  27. package/dist/chunk-UCJ2WD4D.js +625 -0
  28. package/dist/chunk-UCJ2WD4D.js.map +7 -0
  29. package/dist/chunk-WVFGV5FT.js +205 -0
  30. package/dist/chunk-WVFGV5FT.js.map +7 -0
  31. package/dist/core.js +1098 -0
  32. package/dist/core.js.map +7 -0
  33. package/dist/editor.js +1661 -0
  34. package/dist/editor.js.map +7 -0
  35. package/dist/flexdesk.css +5797 -0
  36. package/dist/host.js +132 -0
  37. package/dist/host.js.map +7 -0
  38. package/dist/reset.css +46 -0
  39. package/dist/tile_registry-6WZPTUZV.js +28 -0
  40. package/dist/tile_registry-6WZPTUZV.js.map +7 -0
  41. package/dist/tiles.js +2068 -0
  42. package/dist/tiles.js.map +7 -0
  43. package/dist/tokens.css +137 -0
  44. package/dist/widgets.js +5438 -0
  45. package/dist/widgets.js.map +7 -0
  46. package/dist/wm.js +4830 -0
  47. package/dist/wm.js.map +7 -0
  48. package/package.json +80 -0
  49. package/src/charts/chart_types.js +699 -0
  50. package/src/charts/data_series_plot_window.js +761 -0
  51. package/src/charts/downsample.js +119 -0
  52. package/src/charts/plot_config.js +176 -0
  53. package/src/charts/plot_popout_window.js +1560 -0
  54. package/src/charts/plotly_wrapper.js +432 -0
  55. package/src/core/event_bus.js +230 -0
  56. package/src/core/logging.js +300 -0
  57. package/src/core/settings.js +813 -0
  58. package/src/core/state_guard.js +382 -0
  59. package/src/core/state_guard_config.js +309 -0
  60. package/src/core/state_machine.js +258 -0
  61. package/src/editor/editor_pane.js +264 -0
  62. package/src/editor/monaco_editor_factory.js +449 -0
  63. package/src/editor/monaco_loader.js +74 -0
  64. package/src/editor/notebook_search.js +460 -0
  65. package/src/editor/notebook_tab_bar.js +456 -0
  66. package/src/editor/notebook_undo_manager.js +108 -0
  67. package/src/editor/split_pane_container.js +197 -0
  68. package/src/help/help_modal.js +409 -0
  69. package/src/help/help_registry.js +65 -0
  70. package/src/host/host.js +69 -0
  71. package/src/host/pywebview_host.js +133 -0
  72. package/src/tiles/config_schema.js +256 -0
  73. package/src/tiles/layout_persistence.js +662 -0
  74. package/src/tiles/tile_base.js +785 -0
  75. package/src/tiles/tile_grid.js +905 -0
  76. package/src/tiles/tile_registry.js +136 -0
  77. package/src/tiling/command_palette.js +328 -0
  78. package/src/tiling/content_registry.js +110 -0
  79. package/src/tiling/desktops.js +133 -0
  80. package/src/tiling/entity_sources.js +179 -0
  81. package/src/tiling/keymap.js +156 -0
  82. package/src/tiling/kind_taxonomy.js +172 -0
  83. package/src/tiling/landing_table.js +717 -0
  84. package/src/tiling/loading_overlay.js +33 -0
  85. package/src/tiling/nav_panel.js +142 -0
  86. package/src/tiling/page_factory.js +215 -0
  87. package/src/tiling/panel_keys.js +145 -0
  88. package/src/tiling/shell.js +437 -0
  89. package/src/tiling/tile_breadcrumb.js +222 -0
  90. package/src/tiling/tile_renderer.js +459 -0
  91. package/src/tiling/tile_tab_menu.js +340 -0
  92. package/src/tiling/tile_tree.js +880 -0
  93. package/src/tiling/wm.js +1352 -0
  94. package/src/ui/base/component_base.js +30 -0
  95. package/src/ui/base/controller_base.js +48 -0
  96. package/src/ui/base/page_base.js +102 -0
  97. package/src/ui/components/about_dialog.js +224 -0
  98. package/src/ui/components/action_dropdown.js +389 -0
  99. package/src/ui/components/attribute_list_editor.js +652 -0
  100. package/src/ui/components/autocomplete_field.js +732 -0
  101. package/src/ui/components/computing_status_window.js +81 -0
  102. package/src/ui/components/confirm_dialog.js +307 -0
  103. package/src/ui/components/context_menu.js +87 -0
  104. package/src/ui/components/data_table.js +2228 -0
  105. package/src/ui/components/detail_header.js +177 -0
  106. package/src/ui/components/drag_reorder.js +0 -0
  107. package/src/ui/components/gallery_picker.js +147 -0
  108. package/src/ui/components/inline_renamer.js +129 -0
  109. package/src/ui/components/managed_window.js +804 -0
  110. package/src/ui/components/modal.js +512 -0
  111. package/src/ui/components/notification_history.js +264 -0
  112. package/src/ui/components/slide_out_panel.js +185 -0
  113. package/src/ui/components/slider_field.js +122 -0
  114. package/src/ui/components/sortable_list.js +309 -0
  115. package/src/ui/components/table_state_store.js +81 -0
  116. package/src/ui/components/toast.js +59 -0
  117. package/src/ui/components/tree_view.js +460 -0
  118. package/src/ui/components/window_taskbar.js +143 -0
  119. package/src/ui/controllers/panel_state_machine.js +634 -0
  120. package/src/ui/controllers/window_chrome_controller.js +659 -0
  121. package/src/ui/notification_center.js +576 -0
  122. package/src/ui/utils/overlay_scrollbar.js +492 -0
  123. package/src/ui/utils/raf_resize_observer.js +31 -0
  124. package/src/ui/utils/tooltip_service.js +406 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 nor-os
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # FlexDesk
2
+
3
+ A tiling window manager and widget set for desktop-class web applications.
4
+
5
+ Tiles that split and tab, a command palette, dockable panels, virtual desktops, a
6
+ DataTable with sticky headers and CSV export, managed windows, modals, toasts,
7
+ trees and context menus.
8
+
9
+ **Zero runtime dependencies.** No React, no framework, nothing. If you install
10
+ FlexDesk, you install FlexDesk.
11
+
12
+ FlexDesk was extracted from [EcoAgent](https://github.com/nor-os/EcoAgent), a
13
+ macroeconomic simulation platform, and it knows nothing about economics: no
14
+ application vocabulary, no import of anything application-specific, in any
15
+ shipped file.
16
+
17
+ ```bash
18
+ npm install flexdesk
19
+ ```
20
+
21
+ Or vendor `dist/` and load it through an import map — no bundler, no build step.
22
+ That is exactly what EcoAgent does:
23
+
24
+ ```html
25
+ <script type="importmap">
26
+ { "imports": {
27
+ "@flexdesk/core": "./vendor/flexdesk/core.js",
28
+ "@flexdesk/host": "./vendor/flexdesk/host.js",
29
+ "@flexdesk/wm": "./vendor/flexdesk/wm.js",
30
+ "@flexdesk/widgets": "./vendor/flexdesk/widgets.js"
31
+ } }
32
+ </script>
33
+ <link href="./vendor/flexdesk/flexdesk.css" rel="stylesheet" />
34
+ ```
35
+
36
+ ## Seven entry points
37
+
38
+ Because someone who wants a DataTable should not have to download a window
39
+ manager, and neither of them should drag in a plotting engine or a code editor.
40
+
41
+ | Entry | Size | What is in it |
42
+ |---|---|---|
43
+ | `@flexdesk/core` | 30 kB | Event bus, settings store, logging, state machine, state guard |
44
+ | `@flexdesk/host` | 5 kB | The host port (below) |
45
+ | `@flexdesk/wm` | 166 kB | Tiling window manager: tabs, splits, desktops, command palette, taxonomy, `createShell()` |
46
+ | `@flexdesk/widgets` | 192 kB | DataTable, modals, managed windows, toasts, trees, panels, context menus |
47
+ | `@flexdesk/charts` | 26 kB | Plotly wrapper, chart types, subplot layouts, downsampling, plot windows |
48
+ | `@flexdesk/tiles` | 67 kB | Draggable/resizable widget grid, tile base class, widget registry, layout persistence |
49
+ | `@flexdesk/editor` | 62 kB | Monaco loader + factory, multi-file tab bar, search, split panes, undo manager |
50
+
51
+ They share code through chunks, so importing two of them does **not** give you two
52
+ event buses — and therefore not two copies of every module-level singleton. A test
53
+ asserts each kernel symbol is defined exactly once across the whole `dist/`.
54
+
55
+ Two different things here are called "tiles", which is unfortunate but honest to
56
+ the code: `@flexdesk/wm` tiles the *window*; `@flexdesk/tiles` is a dashboard
57
+ *widget grid*.
58
+
59
+ ## Hello, shell
60
+
61
+ ```js
62
+ import { createShell, createTaxonomy, createEntityCatalog } from '@flexdesk/wm';
63
+ import { createHost } from '@flexdesk/host';
64
+ import { DataTable } from '@flexdesk/widgets';
65
+
66
+ const store = new Map();
67
+
68
+ const shell = await createShell({
69
+ root: document.getElementById('app'),
70
+
71
+ // YOUR ontology. FlexDesk has none.
72
+ taxonomy: createTaxonomy({
73
+ root: 'cosmos',
74
+ kinds: {
75
+ cosmos: { label: 'Cosmos', isTopNav: true, sources: ['planet'] },
76
+ planet: { label: 'Planet', icon: 'circle' },
77
+ moon: {
78
+ label: 'Moon',
79
+ // "jupiter/europa" — your naming convention, not the library's.
80
+ ancestors: ({ id }) => {
81
+ const i = String(id).indexOf('/');
82
+ return i > 0 ? [{ kind: 'planet', id: String(id).slice(0, i) }] : [];
83
+ },
84
+ },
85
+ },
86
+ }),
87
+
88
+ entities: createEntityCatalog({ sources: [/* what the palette searches */] }),
89
+ content: { planet: (hostEl, props) => { /* render a tile */ } },
90
+
91
+ // Where persistence goes. An in-memory Map is a perfectly good host.
92
+ host: createHost({
93
+ state: {
94
+ read: async (k) => store.get(k) ?? null,
95
+ write: async (k, v) => (store.set(k, v), true),
96
+ },
97
+ }),
98
+
99
+ // Chrome is ELEMENTS, not selectors. The library never guesses at your markup.
100
+ chrome: { topNav: document.getElementById('nav') },
101
+ });
102
+ ```
103
+
104
+ A working version of exactly this — planets and moons, a mock host, no backend —
105
+ lives in `demo/`.
106
+
107
+ ## The host port
108
+
109
+ FlexDesk never touches `pywebview`, `fetch`, `localStorage` or the filesystem. It
110
+ asks a **Host**, and you supply one. `createHost({...})` validates the capabilities
111
+ you pass and freezes the result; anything you leave out is simply absent, and the
112
+ library degrades rather than throwing.
113
+
114
+ ```js
115
+ createHost({
116
+ state: { read, write }, // layout persistence
117
+ dialogs: { saveFile }, // optional — CSV export falls back to a Blob
118
+ window: { minimize, maximize, ... }, // optional — no native chrome buttons without it
119
+ })
120
+ ```
121
+
122
+ `NULL_HOST` is a valid host with nothing behind it.
123
+
124
+ ## Peer dependencies
125
+
126
+ `@flexdesk/charts` needs Plotly (4.4 MB). `@flexdesk/editor` needs Monaco (14 MB).
127
+ Neither is bundled, and **neither is guessed at**:
128
+
129
+ ```js
130
+ import { setPlotlySource } from '@flexdesk/charts';
131
+ import { setMonacoBasePath, setDefaultLanguage } from '@flexdesk/editor';
132
+
133
+ setPlotlySource('/vendor/plotly/plotly.min.js');
134
+ setMonacoBasePath('/vendor/monaco');
135
+ setDefaultLanguage('my-dsl'); // default: 'plaintext'
136
+ ```
137
+
138
+ There is deliberately **no default path**. A hardcoded `'vendor/monaco'` is one
139
+ application's directory layout, and for everyone else it is a 404 that surfaces as
140
+ an editor which silently never appears. `initMonaco()` throws instead.
141
+
142
+ If you already load Plotly yourself (a `<script>` tag that sets `window.Plotly`),
143
+ the chart loader short-circuits and you can skip `setPlotlySource`.
144
+
145
+ ## Layouts are keyed by whatever you key them by
146
+
147
+ `@flexdesk/tiles` stores layouts under keys **you** choose and resolves a starting
148
+ layout through a callback **you** supply:
149
+
150
+ ```js
151
+ import { configureLayoutPersistence } from '@flexdesk/tiles';
152
+
153
+ configureLayoutPersistence({
154
+ layoutsKey: 'myapp.layouts', // default: 'twm.tiles.layouts'
155
+ resolveTemplate: (ctx) => pickTemplate(ctx) ?? null, // null => empty grid
156
+ });
157
+ ```
158
+
159
+ **Configure it before anything reads it.** The store is a singleton; built before
160
+ you supply your key, it is built with the default, and every layout your users have
161
+ saved becomes silently invisible. That is a data-loss bug that raises no error, so
162
+ the configuration step is explicit rather than lazy.
163
+
164
+ A layout is keyed by *something* — a document, a user, a run — and the library has
165
+ no opinion about which. It calls that a `contextId`.
166
+
167
+ ## Styling
168
+
169
+ Three stylesheets, and that is the whole CSS contract:
170
+
171
+ | | |
172
+ |---|---|
173
+ | `dist/tokens.css` | Every rule reads `var(--…)` from here. Swap this one file and the shell restyles. |
174
+ | `dist/reset.css` | The reset. |
175
+ | `dist/flexdesk.css` | The library. Every class is `twm-` prefixed (the original working name; the prefix is stable and not worth a breaking rename). |
176
+
177
+ Icons are rendered by applying the `material-symbols-outlined` class. FlexDesk does
178
+ not ship the font — supply it from Google Fonts or self-host. Without it, icons fall
179
+ back to their text names and nothing breaks.
180
+
181
+ ## Build
182
+
183
+ ```bash
184
+ npm install
185
+ npm run build # -> dist/
186
+ ```
187
+
188
+ `dist/` is committed. The packaging decision is *prebuilt dist*: this repo owns the
189
+ build so that a consumer with no bundler can load the library through a plain import
190
+ map. See `.gitignore` — it says so there too, because it is the kind of thing someone
191
+ "tidies up" later.
192
+
193
+ ## Licence
194
+
195
+ MIT. See [`LICENSE`](LICENSE) and [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md).
@@ -0,0 +1,53 @@
1
+ # Third-party licences
2
+
3
+ FlexDesk itself is MIT (see `LICENSE`).
4
+
5
+ ## Runtime dependencies: none
6
+
7
+ FlexDesk has **zero runtime dependencies**. Nothing is bundled into `dist/` except
8
+ FlexDesk's own source. The build declares `external: []`, so if a dependency were
9
+ ever introduced, the build would fail on an unresolved bare specifier rather than
10
+ quietly growing one.
11
+
12
+ If you install `flexdesk`, you install nothing else.
13
+
14
+ | | |
15
+ |---|---|
16
+ | Bare-specifier imports in `src/` | **0** |
17
+ | `dependencies` in `package.json` | **none** |
18
+ | External assets referenced by `dist/flexdesk.css` | **none** (its one image is an inline `data:` URI) |
19
+
20
+ ## Optional peer dependencies
21
+
22
+ These are **not installed, not bundled, and not required**. Each is needed only if
23
+ you import the entry point that uses it, and FlexDesk never guesses where you keep
24
+ it — you tell it (`setPlotlySource()`, `setMonacoBasePath()`).
25
+
26
+ | Package | Needed by | Licence | Copyright |
27
+ |---|---|---|---|
28
+ | [plotly.js](https://github.com/plotly/plotly.js) | `@flexdesk/charts` | MIT | Plotly, Inc. |
29
+ | [monaco-editor](https://github.com/microsoft/monaco-editor) | `@flexdesk/editor` | MIT | Microsoft Corporation |
30
+
31
+ ## Optional asset
32
+
33
+ FlexDesk's widgets render icons by applying the `material-symbols-outlined` class.
34
+ The font itself is **not shipped** — you supply it, from Google Fonts or self-hosted.
35
+ Without it, icons fall back to their text names; nothing breaks.
36
+
37
+ | Asset | Licence | Copyright |
38
+ |---|---|---|
39
+ | [Material Symbols](https://github.com/google/material-design-icons) | Apache-2.0 | Google LLC |
40
+
41
+ ## Build-time only
42
+
43
+ Not shipped, not a dependency of consumers.
44
+
45
+ | Package | Licence | Copyright |
46
+ |---|---|---|
47
+ | [esbuild](https://github.com/evanw/esbuild) | MIT | Evan Wallace |
48
+
49
+ ---
50
+
51
+ Every licence above was read from the package's own `LICENSE` file or from the
52
+ licence header in the distributed artifact — not from memory. Material Symbols was
53
+ confirmed against `google/material-design-icons/LICENSE`.