flexdesk 0.17.1 → 0.17.3
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/CHANGELOG.md +38 -0
- package/README.md +206 -1
- package/css/base.css +23 -1
- package/css/flexdesk.css +37 -1
- package/dist/flexdesk.css +37 -1
- package/dist/widgets.js +188 -74
- package/dist/widgets.js.map +2 -2
- package/dist/wm.js +90 -10
- package/dist/wm.js.map +2 -2
- package/package.json +1 -1
- package/src/tiling/command_palette.js +46 -7
- package/src/tiling/content_registry.js +3 -0
- package/src/tiling/entity_sources.js +10 -0
- package/src/tiling/wm.js +65 -3
- package/src/ui/components/notification_history.js +17 -24
- package/src/ui/components/settings_view.js +192 -51
- package/src/ui/notification_center.js +46 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.17.3 (2026-10-22)
|
|
4
|
+
|
|
5
|
+
A patch release: everything below is additive. Every entry is documented in a
|
|
6
|
+
README section headed "(0.17.3)"; each entry links to it.
|
|
7
|
+
|
|
8
|
+
### Added and changed
|
|
9
|
+
|
|
10
|
+
- [One toast, one history entry, one unread](README.md#one-toast-one-history-entry-one-unread-0173): `NotificationCenter.history` holds one entry per toast however it was raised (`show()`, `warn()` / `error()` / `info()` / `success()`, `toast:show`, `notification:show`, `log:entry`), and a toast that leaves marks its own entry `dismissed: true` with the `reason` instead of adding a second one. `nc.subscribe(fn)` calls `fn(entry, center)` once per entry added and answers the unsubscribe. `NotificationHistory` follows the centre through `subscribe()`, so every toast counts once on the bell, also one raised through the API (BUG-0034). It no longer watches the bus for toasts: its `notificationCenter` is a `NotificationCenter` (or anything with `history` and `subscribe`).
|
|
11
|
+
|
|
12
|
+
### Removed or renamed exports
|
|
13
|
+
|
|
14
|
+
None. Compared with 0.17.2, across every entry point (`core`, `widgets`, `wm`,
|
|
15
|
+
`host`, `canvas`, `flow`, `charts`, `tiles`, `editor`) and the package
|
|
16
|
+
`exports` map, no export was added, removed or renamed. Not an export but worth
|
|
17
|
+
knowing: `NotificationCenter` gained the `subscribe(fn)` method (see above).
|
|
18
|
+
|
|
19
|
+
## 0.17.2 (2026-10-22)
|
|
20
|
+
|
|
21
|
+
A patch release: everything below is additive. Every entry is documented in a
|
|
22
|
+
README section headed "(0.17.2)"; each entry links to it.
|
|
23
|
+
|
|
24
|
+
### Added and changed
|
|
25
|
+
|
|
26
|
+
- [An open single instance takes new props: `navigate(props)`](README.md#an-open-single-instance-takes-new-props-navigateprops-0172): opening a `single` kind that is already open with new props reveals it and calls its content's `navigate(props)` hook once; the props are recorded on the tab. An open that names no props only reveals.
|
|
27
|
+
- [A link to a kind nobody registered](README.md#a-link-to-a-kind-nobody-registered-0172): `wm.navigate` to a kind that is not registered logs one warning, changes nothing and returns `false`.
|
|
28
|
+
- [A palette row drawn disabled, with a reason](README.md#a-palette-row-drawn-disabled-with-a-reason-0172): a command with `enabled: () => false` is listed greyed (`aria-disabled`), does nothing when picked, and shows its `disabledReason` as a tooltip.
|
|
29
|
+
- [A catalog source only behind its prefix: `scopedOnly`](README.md#a-catalog-source-only-behind-its-prefix-scopedonly-0172): a catalog source with `scopedOnly: true` is searched only when its prefix is typed, in the flat and the grouped palette.
|
|
30
|
+
- [The settings categories outside the page: `SettingsCategories`](README.md#the-settings-categories-outside-the-page-settingscategories-0172): `SettingsView` can leave out its own category list and filter, and `SettingsCategories` (new export from `@flexdesk/widgets`) shows them anywhere, kept in step with the view.
|
|
31
|
+
- [Toast cards are styled and clickable](README.md#toast-cards-are-styled-and-clickable-0172): toast cards use `twm-notification` and `twm-notification--<severity>`, styled in flexdesk.css and base.css, with their entry animation defined there; cards take pointer events, so their buttons work (BUG-0033). A sheet that targeted `.notification` must target `.twm-notification`.
|
|
32
|
+
|
|
33
|
+
### Removed or renamed exports
|
|
34
|
+
|
|
35
|
+
None. Compared with 0.17.1, across every entry point (`core`, `widgets`, `wm`,
|
|
36
|
+
`host`, `canvas`, `flow`, `charts`, `tiles`, `editor`) and the package
|
|
37
|
+
`exports` map, exports were only added: `SettingsCategories` in `@flexdesk/widgets`.
|
|
38
|
+
Not an export but worth knowing: toast cards changed class from `notification`
|
|
39
|
+
to `twm-notification` (see above).
|
|
40
|
+
|
|
3
41
|
## 0.17.1 (2026-10-21)
|
|
4
42
|
|
|
5
43
|
A patch release: everything below is additive. Every entry is documented in a
|
package/README.md
CHANGED
|
@@ -237,6 +237,65 @@ with it. The taxonomy answers `isSingle(kind)`, `instanceKey(kind, props)` and
|
|
|
237
237
|
`singleReason(kind)`; the window manager answers `isSingleKind(kind)`,
|
|
238
238
|
`findInstance(kind, props)` and `revealInstance(kind, props)`.
|
|
239
239
|
|
|
240
|
+
### An open single instance takes new props: `navigate(props)` (0.17.2)
|
|
241
|
+
|
|
242
|
+
Revealing a `single` instance used to drop the props the open asked for: the
|
|
243
|
+
observatory kept showing the planet it was opened with. A content factory that
|
|
244
|
+
returns a `navigate(props)` hook from its mount is now handed them:
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
content: {
|
|
248
|
+
observatory: (el, props) => {
|
|
249
|
+
const view = mountObservatory(el, props);
|
|
250
|
+
return {
|
|
251
|
+
destroy: () => view.destroy(),
|
|
252
|
+
navigate: (next) => view.focusPlanet(next.planet), // already open: go there
|
|
253
|
+
};
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
wm.navigate('observatory', { planet: 'mars' }); // open: revealed, then navigate({ planet: 'mars' })
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
- **Every open path that reveals the instance calls it once**, after the
|
|
261
|
+
reveal, with a copy of the new props — `navigate`, the top nav,
|
|
262
|
+
`openInPrimary`, `openInTab*`, `splitLeafWith`, Back. The same props twice
|
|
263
|
+
are two calls; nothing is deduplicated, and no second instance is mounted.
|
|
264
|
+
- **The props are recorded on the instance's tab** (or its window's), so a
|
|
265
|
+
top-nav page restore or a reload mounts it with the latest. The tile is not
|
|
266
|
+
rebuilt by the write.
|
|
267
|
+
- **An open that names no props only reveals** — the top-nav button,
|
|
268
|
+
`openInPrimary(kind)`, `navigate(kind)`: it asks to see the instance, not to
|
|
269
|
+
empty it, so the hook is not called and the tab keeps its props.
|
|
270
|
+
- **A content without the hook is revealed as before**: its tab keeps its props
|
|
271
|
+
and nothing is called. A hook that throws is a console warning.
|
|
272
|
+
|
|
273
|
+
### A link to a kind nobody registered (0.17.2)
|
|
274
|
+
|
|
275
|
+
`wm.navigate(kind, props, opts)` returns `true` once it has routed the
|
|
276
|
+
navigation. A `kind` the shell's `content` map has no factory for is refused
|
|
277
|
+
instead, on every destination (`main`, `origin`, a new tab, a window, a split,
|
|
278
|
+
the legacy `target`):
|
|
279
|
+
|
|
280
|
+
```js
|
|
281
|
+
if (!wm.navigate(link.kind, link.props)) {
|
|
282
|
+
// nothing opened: tell the user the link is dead
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
- **One `console.warn` naming the kind**, per call, and `false` back.
|
|
287
|
+
- **Nothing changes**: no tile, tab, window or desktop, no per-tab history, no
|
|
288
|
+
`onChange` — and no "no factory registered yet" placeholder tile, which is
|
|
289
|
+
what such a link used to leave behind.
|
|
290
|
+
- **No exception reaches the caller**, whatever `kind` is (`undefined`, `null`
|
|
291
|
+
and `''` included).
|
|
292
|
+
|
|
293
|
+
A shell that only navigates to kinds it registered sees no change; the return
|
|
294
|
+
value is new, so code that ignored it is unaffected. A split destination used
|
|
295
|
+
to hand back the new leaf's id; it now returns `true` like the others — call
|
|
296
|
+
`wm.splitLeafWith(...)` for the id. A restored layout that names an
|
|
297
|
+
unregistered kind still draws its placeholder: only `navigate` refuses.
|
|
298
|
+
|
|
240
299
|
### A pane that names what it shows: `ctx.setTitle` (0.12.1)
|
|
241
300
|
|
|
242
301
|
A content factory receives `(hostEl, props, ctx)`, and `ctx` carries, per pane,
|
|
@@ -450,6 +509,60 @@ topic.* The fallback comes from `HelpModal.open(id, { fallback })`
|
|
|
450
509
|
(`@flexdesk/widgets`), and you can pass one yourself. A topic id that nobody
|
|
451
510
|
provides now shows *Help topic not found.* where it used to raise a load error.
|
|
452
511
|
|
|
512
|
+
### A palette row drawn disabled, with a reason (0.17.2)
|
|
513
|
+
|
|
514
|
+
A palette row (a command from `commands`, or any other row) may carry
|
|
515
|
+
`enabled: () => boolean` and `disabledReason`. While `enabled()` returns false
|
|
516
|
+
the row is still listed, so it can say why it does nothing:
|
|
517
|
+
|
|
518
|
+
```js
|
|
519
|
+
palette: {
|
|
520
|
+
commands: () => [
|
|
521
|
+
{ id: 'save', label: 'Save', action: save,
|
|
522
|
+
enabled: () => dirty, disabledReason: 'Nothing to save' },
|
|
523
|
+
],
|
|
524
|
+
},
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
- The row gets the class `twm-cmdpal__item--disabled` and `aria-disabled="true"`,
|
|
528
|
+
and `disabledReason`, when given, is its `title` (the tooltip). The stylesheet
|
|
529
|
+
greys it.
|
|
530
|
+
- Picking it with a click, Enter, Ctrl+Enter or Shift+Enter runs nothing: not
|
|
531
|
+
its `action`, not `onPick`. The palette stays open on it.
|
|
532
|
+
- The arrow keys still move onto it and past it.
|
|
533
|
+
- `enabled()` is called again on every draw and every pick, so the row follows
|
|
534
|
+
your state while the palette is open. An `enabled()` that throws counts as
|
|
535
|
+
false.
|
|
536
|
+
- A row without `enabled` is drawn and picked as before. Both layouts (flat and
|
|
537
|
+
`grouped`) behave the same way.
|
|
538
|
+
|
|
539
|
+
`tests/command_palette_disabled.test.mjs` drives it in jsdom.
|
|
540
|
+
|
|
541
|
+
### A catalog source only behind its prefix: `scopedOnly` (0.17.2)
|
|
542
|
+
|
|
543
|
+
A source can be too broad to compete with everything else in the palette: help
|
|
544
|
+
topics, say, which would crowd every query. Mark it `scopedOnly` and its rows are
|
|
545
|
+
listed only once its prefix has made the type chip:
|
|
546
|
+
|
|
547
|
+
```js
|
|
548
|
+
createEntityCatalog({
|
|
549
|
+
sources: [
|
|
550
|
+
{ navKind: 'model', list: listModels, shape: toRow },
|
|
551
|
+
{ navKind: 'topic', list: listTopics, shape: toRow, scopedOnly: true },
|
|
552
|
+
],
|
|
553
|
+
aliases: { help: ['topic'] },
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
A plain typed query (`solver`) lists no `topic` row, in the flat and the grouped
|
|
558
|
+
layout alike: no row, no group header, no *Show all*. `help: solver` or
|
|
559
|
+
`topic: solver` lists its rows as any source's, and `help:` alone lists them all.
|
|
560
|
+
The mark is the palette's business: `loadAll`, `loadGrouped` and the tile menu
|
|
561
|
+
still return every source, a picked row reaches `onPick` as its `shape` made it,
|
|
562
|
+
and commands and `empty()` rows of the same kind are not held back. A source
|
|
563
|
+
without the option, or with `scopedOnly: false`, is searched exactly as in
|
|
564
|
+
0.17.1. A value that is not a boolean is refused with a `TypeError`.
|
|
565
|
+
|
|
453
566
|
### Your keys, not the window manager's: `keymap` (0.17.0)
|
|
454
567
|
|
|
455
568
|
The window manager binds F1..F12, Backspace, Ctrl+K, Ctrl+Tab, Ctrl/Shift+Arrows,
|
|
@@ -3034,6 +3147,52 @@ title; default "Settings"). The markup is `.twm-settings` >
|
|
|
3034
3147
|
`.twm-settings__row` (`--modified`); `flexdesk.css` styles it from tokens.
|
|
3035
3148
|
`tests/settings_view.test.mjs` covers it in jsdom.
|
|
3036
3149
|
|
|
3150
|
+
## The settings categories outside the page: `SettingsCategories` (0.17.2)
|
|
3151
|
+
|
|
3152
|
+
A `SettingsView` made with `sidebar: false` draws no sidebar: no heading, no
|
|
3153
|
+
filter box, no category list and no *Reset all*, only the chosen category's
|
|
3154
|
+
settings (or the filter's matches). `new SettingsCategories({ view })` (in
|
|
3155
|
+
`@flexdesk/widgets`) draws those parts for that view wherever it is mounted,
|
|
3156
|
+
for example in an app's left navigator:
|
|
3157
|
+
|
|
3158
|
+
```js
|
|
3159
|
+
import { SettingsView, SettingsCategories } from '@flexdesk/widgets';
|
|
3160
|
+
|
|
3161
|
+
const view = new SettingsView({ store, eventBus: bus, sidebar: false });
|
|
3162
|
+
view.mount(pageHost);
|
|
3163
|
+
const cats = new SettingsCategories({ view });
|
|
3164
|
+
cats.mount(navigatorHost);
|
|
3165
|
+
|
|
3166
|
+
const off = view.subscribe(({ category, query }) => { /* e.g. a tab title */ });
|
|
3167
|
+
// …
|
|
3168
|
+
off();
|
|
3169
|
+
cats.dispose();
|
|
3170
|
+
view.dispose();
|
|
3171
|
+
```
|
|
3172
|
+
|
|
3173
|
+
It keeps no state of its own. Typing in its filter box is `view.setQuery()`,
|
|
3174
|
+
clicking a category is `view.selectCategory()` and its *Reset all* is
|
|
3175
|
+
`view.resetAll()`, which asks the view's `confirm` first and changes nothing
|
|
3176
|
+
unless it resolves true. It redraws from the view whenever the view's category,
|
|
3177
|
+
filter or registered categories change, so the two agree whichever side moved
|
|
3178
|
+
them: `view.selectCategory('window')` marks that category in the list, and
|
|
3179
|
+
`view.setQuery('shadow')` puts the text in its filter box. As in the view's own
|
|
3180
|
+
sidebar, choosing a category clears the filter, and no category is marked while
|
|
3181
|
+
the filter is in effect. Its clicks and keystrokes act once the view is mounted.
|
|
3182
|
+
|
|
3183
|
+
Two methods on `SettingsView` serve it and anything else that follows the view:
|
|
3184
|
+
`subscribe(fn)` calls `fn({ category, query })` after each such change and
|
|
3185
|
+
answers the unsubscribe; `isFiltering()` is true while the filter's trimmed
|
|
3186
|
+
text is not empty. `settingsViewContent({ …, sidebar: false })` passes the
|
|
3187
|
+
option through. A view made without `sidebar` (or with `sidebar: true`) draws
|
|
3188
|
+
exactly as in 0.17.1.
|
|
3189
|
+
|
|
3190
|
+
The markup is `.twm-settings-categories` > `.twm-settings__search`,
|
|
3191
|
+
`.twm-settings__nav` (`button.twm-settings__cat`, `--active`) and
|
|
3192
|
+
`.twm-settings__reset-all`, the same parts and classes as the sidebar's;
|
|
3193
|
+
`flexdesk.css` styles it, leaving its width and padding to the host.
|
|
3194
|
+
`tests/settings_view.test.mjs` §11–§14 cover it.
|
|
3195
|
+
|
|
3037
3196
|
## A step wizard: `Wizard` (0.17.0)
|
|
3038
3197
|
|
|
3039
3198
|
`new Wizard({ steps, data, onFinish, onCancel, labels })` (in `@flexdesk/widgets`)
|
|
@@ -3368,7 +3527,8 @@ again: its pane hears `onShow` and `onSelect` fires, and nothing is written back
|
|
|
3368
3527
|
Toasts, from `toast:show` on the bus (or `toastInfo` / `toastWarn` /
|
|
3369
3528
|
`toastError` / `toastSuccess`) or `show()`. A payload with `persistent: true`
|
|
3370
3529
|
stays until its × is clicked. `history` keeps every notification shown, and
|
|
3371
|
-
`NotificationHistory` puts it behind a bell in the bottom bar
|
|
3530
|
+
`NotificationHistory` puts it behind a bell in the bottom bar (one entry per toast;
|
|
3531
|
+
`subscribe(fn)` hears each one, 0.17.3).
|
|
3372
3532
|
|
|
3373
3533
|
*New in 0.11.0:* **`overflow: 'collapse'`.** By default, a toast past
|
|
3374
3534
|
`maxVisible` (3) pushes the oldest off the screen. With `'collapse'`, the toasts
|
|
@@ -3429,6 +3589,51 @@ job.on('end', () => nc.update(id, { progress: 1, severity: 'success', message: '
|
|
|
3429
3589
|
|
|
3430
3590
|
`tests/notification_progress.test.mjs` holds it in jsdom.
|
|
3431
3591
|
|
|
3592
|
+
### Toast cards are styled and clickable (0.17.2)
|
|
3593
|
+
|
|
3594
|
+
A toast card is `.twm-notification` with `.twm-notification--<severity>`
|
|
3595
|
+
(`info`, `success`, `warn`, `error`, `fatal`), and the "+N more" summary is
|
|
3596
|
+
`.twm-notification.twm-notification--summary`. `flexdesk.css` gives the card its
|
|
3597
|
+
background, a left border in the severity's colour (`--color-success`,
|
|
3598
|
+
`--color-warning`, `--color-danger`; info keeps the blue) and the entry
|
|
3599
|
+
animation `twm-notification-in`, which the sheet now defines. The card sets
|
|
3600
|
+
`pointer-events: auto` over the root's `none`, so its buttons and its
|
|
3601
|
+
click-to-close work.
|
|
3602
|
+
|
|
3603
|
+
Until 0.17.2 the card carried the bare `notification` / `notification--<severity>`
|
|
3604
|
+
classes, which no FlexDesk sheet styled: the card had no background and no
|
|
3605
|
+
border, and inherited `pointer-events: none`, so its buttons could not be
|
|
3606
|
+
clicked. A consumer stylesheet that targeted `.notification` should target
|
|
3607
|
+
`.twm-notification` instead. The live region is `.twm-notification-center__live-region`.
|
|
3608
|
+
`tests/notification_toast_styles.test.mjs` holds the classes, the cascade and
|
|
3609
|
+
the sheets.
|
|
3610
|
+
|
|
3611
|
+
### One toast, one history entry, one unread (0.17.3)
|
|
3612
|
+
|
|
3613
|
+
`history` holds **one entry per toast**, however it was raised: `show()`, the
|
|
3614
|
+
`warn()` / `error()` / `info()` / `success()` helpers, `toast:show`,
|
|
3615
|
+
`notification:show` or `log:entry`. A toast that leaves (timeout, ×, overflow,
|
|
3616
|
+
`clearAll`) marks its own entry `dismissed: true` with the `reason`, and adds
|
|
3617
|
+
no entry. **`nc.subscribe(fn)`** calls `fn(entry, center)` once for each entry
|
|
3618
|
+
added, after it is in `history` (not for a `skipHistory` toast, and not for a
|
|
3619
|
+
dismissal), and answers the unsubscribe; `dispose()` drops every listener.
|
|
3620
|
+
|
|
3621
|
+
`NotificationHistory` follows the centre through `subscribe()`: every entry
|
|
3622
|
+
recorded is one unread on the bell until the popover is opened, also past
|
|
3623
|
+
`historyLimit`. It no longer watches the bus for toasts, so its
|
|
3624
|
+
`notificationCenter` is a `NotificationCenter` (or anything with `history` and
|
|
3625
|
+
`subscribe`).
|
|
3626
|
+
|
|
3627
|
+
```js
|
|
3628
|
+
const off = nc.subscribe((entry) => console.log('recorded', entry.severity, entry.message));
|
|
3629
|
+
nc.warn('Disk almost full'); // the bell says 1
|
|
3630
|
+
```
|
|
3631
|
+
|
|
3632
|
+
Until 0.17.3 the bell counted only on bus events, so a toast raised through
|
|
3633
|
+
`show()` / `warn()` / `error()` / `info()` never raised its badge, and a dismissal
|
|
3634
|
+
was pushed as a second entry: a toast that timed out was in `history` twice
|
|
3635
|
+
and counted twice. `tests/notification_history_follows_center.test.mjs` holds it.
|
|
3636
|
+
|
|
3432
3637
|
### Alerts with history: a log, a pane, a tab host and a bell (0.14.0)
|
|
3433
3638
|
|
|
3434
3639
|
A toast is the moment. The **alert log** keeps what came in until it is
|
package/css/base.css
CHANGED
|
@@ -275,6 +275,28 @@
|
|
|
275
275
|
flex-direction: column;
|
|
276
276
|
gap: var(--space-lg);
|
|
277
277
|
}
|
|
278
|
+
/* A toast card. The root takes no pointer events (it overlays the page), so the
|
|
279
|
+
* card takes them back: without this its buttons cannot be clicked (BUG-0033). */
|
|
280
|
+
.twm-notification {
|
|
281
|
+
pointer-events: auto;
|
|
282
|
+
background: #1f1f20;
|
|
283
|
+
border: 1px solid #2f2f31;
|
|
284
|
+
border-left: 4px solid #4fc1ff;
|
|
285
|
+
border-radius: var(--radius-lg);
|
|
286
|
+
padding: var(--space-lg) 14px;
|
|
287
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
288
|
+
animation: twm-notification-in 160ms ease-out;
|
|
289
|
+
min-width: 280px;
|
|
290
|
+
cursor: pointer;
|
|
291
|
+
}
|
|
292
|
+
.twm-notification--success { border-left-color: var(--color-success, #3fb950); }
|
|
293
|
+
.twm-notification--warn { border-left-color: var(--color-warning, #ff9800); }
|
|
294
|
+
.twm-notification--error,
|
|
295
|
+
.twm-notification--fatal { border-left-color: var(--color-danger, #c74e4e); }
|
|
296
|
+
@keyframes twm-notification-in {
|
|
297
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
298
|
+
to { opacity: 1; transform: translateY(0); }
|
|
299
|
+
}
|
|
278
300
|
.twm-notification__header {
|
|
279
301
|
display: flex;
|
|
280
302
|
align-items: center;
|
|
@@ -425,7 +447,7 @@
|
|
|
425
447
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
426
448
|
display: flex;
|
|
427
449
|
flex-direction: column;
|
|
428
|
-
animation: notification-in 160ms ease-out;
|
|
450
|
+
animation: twm-notification-in 160ms ease-out;
|
|
429
451
|
}
|
|
430
452
|
.twm-notification-history__header {
|
|
431
453
|
display: flex;
|
package/css/flexdesk.css
CHANGED
|
@@ -283,6 +283,28 @@
|
|
|
283
283
|
flex-direction: column;
|
|
284
284
|
gap: var(--space-lg);
|
|
285
285
|
}
|
|
286
|
+
/* A toast card. The root takes no pointer events (it overlays the page), so the
|
|
287
|
+
* card takes them back: without this its buttons cannot be clicked (BUG-0033). */
|
|
288
|
+
.twm-notification {
|
|
289
|
+
pointer-events: auto;
|
|
290
|
+
background: #1f1f20;
|
|
291
|
+
border: 1px solid #2f2f31;
|
|
292
|
+
border-left: 4px solid #4fc1ff;
|
|
293
|
+
border-radius: var(--radius-lg);
|
|
294
|
+
padding: var(--space-lg) 14px;
|
|
295
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
296
|
+
animation: twm-notification-in 160ms ease-out;
|
|
297
|
+
min-width: 280px;
|
|
298
|
+
cursor: pointer;
|
|
299
|
+
}
|
|
300
|
+
.twm-notification--success { border-left-color: var(--color-success, #3fb950); }
|
|
301
|
+
.twm-notification--warn { border-left-color: var(--color-warning, #ff9800); }
|
|
302
|
+
.twm-notification--error,
|
|
303
|
+
.twm-notification--fatal { border-left-color: var(--color-danger, #c74e4e); }
|
|
304
|
+
@keyframes twm-notification-in {
|
|
305
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
306
|
+
to { opacity: 1; transform: translateY(0); }
|
|
307
|
+
}
|
|
286
308
|
|
|
287
309
|
/* NotificationCenter `overflow: 'collapse'`: the toasts past maxVisible, as one. */
|
|
288
310
|
.twm-notification--summary {
|
|
@@ -455,7 +477,7 @@
|
|
|
455
477
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
456
478
|
display: flex;
|
|
457
479
|
flex-direction: column;
|
|
458
|
-
animation: notification-in 160ms ease-out;
|
|
480
|
+
animation: twm-notification-in 160ms ease-out;
|
|
459
481
|
}
|
|
460
482
|
.twm-notification-history__header {
|
|
461
483
|
display: flex;
|
|
@@ -8322,6 +8344,9 @@ body.twm-dragging * { user-select: none; }
|
|
|
8322
8344
|
.twm-cmdpal__item--active .twm-cmdpal__acts { display: flex; }
|
|
8323
8345
|
/* A copy verb a single kind refuses: drawn, greyed, with the reason as its title. */
|
|
8324
8346
|
.twm-cmdpal__act--disabled { opacity: 0.45; }
|
|
8347
|
+
/* 0.17.2. A row whose `enabled()` says no: listed, reachable by the arrows,
|
|
8348
|
+
* greyed, with its `disabledReason` as the title; picking it does nothing. */
|
|
8349
|
+
.twm-cmdpal__item--disabled { opacity: 0.45; cursor: default; }
|
|
8325
8350
|
.twm-cmdpal__item--active .twm-cmdpal__kind,
|
|
8326
8351
|
.twm-cmdpal__item--active .twm-cmdpal__shortcut { display: none; }
|
|
8327
8352
|
.twm-cmdpal__item--more { color: var(--text-muted); font-size: var(--font-size-sm); }
|
|
@@ -10541,6 +10566,17 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
10541
10566
|
padding: var(--space-xl) 0;
|
|
10542
10567
|
color: var(--text-muted);
|
|
10543
10568
|
}
|
|
10569
|
+
/* SettingsCategories (0.17.2): the sidebar's filter, categories and
|
|
10570
|
+
* Reset all, mounted outside the view; the host sets its width and padding. */
|
|
10571
|
+
.twm-settings-categories {
|
|
10572
|
+
display: flex;
|
|
10573
|
+
flex-direction: column;
|
|
10574
|
+
min-height: 0;
|
|
10575
|
+
height: 100%;
|
|
10576
|
+
gap: var(--space-sm);
|
|
10577
|
+
color: var(--text-body);
|
|
10578
|
+
font-size: var(--font-size-sm);
|
|
10579
|
+
}
|
|
10544
10580
|
/* ══ end SETTINGS VIEW ══ */
|
|
10545
10581
|
|
|
10546
10582
|
/* ══ DOCUMENT OUTLINE (0.17.0) ═══════════════════════════════════════
|
package/dist/flexdesk.css
CHANGED
|
@@ -283,6 +283,28 @@
|
|
|
283
283
|
flex-direction: column;
|
|
284
284
|
gap: var(--space-lg);
|
|
285
285
|
}
|
|
286
|
+
/* A toast card. The root takes no pointer events (it overlays the page), so the
|
|
287
|
+
* card takes them back: without this its buttons cannot be clicked (BUG-0033). */
|
|
288
|
+
.twm-notification {
|
|
289
|
+
pointer-events: auto;
|
|
290
|
+
background: #1f1f20;
|
|
291
|
+
border: 1px solid #2f2f31;
|
|
292
|
+
border-left: 4px solid #4fc1ff;
|
|
293
|
+
border-radius: var(--radius-lg);
|
|
294
|
+
padding: var(--space-lg) 14px;
|
|
295
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
296
|
+
animation: twm-notification-in 160ms ease-out;
|
|
297
|
+
min-width: 280px;
|
|
298
|
+
cursor: pointer;
|
|
299
|
+
}
|
|
300
|
+
.twm-notification--success { border-left-color: var(--color-success, #3fb950); }
|
|
301
|
+
.twm-notification--warn { border-left-color: var(--color-warning, #ff9800); }
|
|
302
|
+
.twm-notification--error,
|
|
303
|
+
.twm-notification--fatal { border-left-color: var(--color-danger, #c74e4e); }
|
|
304
|
+
@keyframes twm-notification-in {
|
|
305
|
+
from { opacity: 0; transform: translateY(6px); }
|
|
306
|
+
to { opacity: 1; transform: translateY(0); }
|
|
307
|
+
}
|
|
286
308
|
|
|
287
309
|
/* NotificationCenter `overflow: 'collapse'`: the toasts past maxVisible, as one. */
|
|
288
310
|
.twm-notification--summary {
|
|
@@ -455,7 +477,7 @@
|
|
|
455
477
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
|
|
456
478
|
display: flex;
|
|
457
479
|
flex-direction: column;
|
|
458
|
-
animation: notification-in 160ms ease-out;
|
|
480
|
+
animation: twm-notification-in 160ms ease-out;
|
|
459
481
|
}
|
|
460
482
|
.twm-notification-history__header {
|
|
461
483
|
display: flex;
|
|
@@ -8322,6 +8344,9 @@ body.twm-dragging * { user-select: none; }
|
|
|
8322
8344
|
.twm-cmdpal__item--active .twm-cmdpal__acts { display: flex; }
|
|
8323
8345
|
/* A copy verb a single kind refuses: drawn, greyed, with the reason as its title. */
|
|
8324
8346
|
.twm-cmdpal__act--disabled { opacity: 0.45; }
|
|
8347
|
+
/* 0.17.2. A row whose `enabled()` says no: listed, reachable by the arrows,
|
|
8348
|
+
* greyed, with its `disabledReason` as the title; picking it does nothing. */
|
|
8349
|
+
.twm-cmdpal__item--disabled { opacity: 0.45; cursor: default; }
|
|
8325
8350
|
.twm-cmdpal__item--active .twm-cmdpal__kind,
|
|
8326
8351
|
.twm-cmdpal__item--active .twm-cmdpal__shortcut { display: none; }
|
|
8327
8352
|
.twm-cmdpal__item--more { color: var(--text-muted); font-size: var(--font-size-sm); }
|
|
@@ -10541,6 +10566,17 @@ button.twm-alerts__ref:hover { text-decoration: underline; }
|
|
|
10541
10566
|
padding: var(--space-xl) 0;
|
|
10542
10567
|
color: var(--text-muted);
|
|
10543
10568
|
}
|
|
10569
|
+
/* SettingsCategories (0.17.2): the sidebar's filter, categories and
|
|
10570
|
+
* Reset all, mounted outside the view; the host sets its width and padding. */
|
|
10571
|
+
.twm-settings-categories {
|
|
10572
|
+
display: flex;
|
|
10573
|
+
flex-direction: column;
|
|
10574
|
+
min-height: 0;
|
|
10575
|
+
height: 100%;
|
|
10576
|
+
gap: var(--space-sm);
|
|
10577
|
+
color: var(--text-body);
|
|
10578
|
+
font-size: var(--font-size-sm);
|
|
10579
|
+
}
|
|
10544
10580
|
/* ══ end SETTINGS VIEW ══ */
|
|
10545
10581
|
|
|
10546
10582
|
/* ══ DOCUMENT OUTLINE (0.17.0) ═══════════════════════════════════════
|