@deskwork/studio 0.22.2 → 0.23.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/package.json +2 -2
- package/dist/pages/dashboard/press-queue.d.ts +0 -16
- package/dist/pages/dashboard/press-queue.d.ts.map +0 -1
- package/dist/pages/dashboard/press-queue.js +0 -91
- package/dist/pages/dashboard/press-queue.js.map +0 -1
- package/dist/pages/dashboard/press-queue.ts +0 -112
- package/dist/pages/entry-review/mobile-bar.d.ts +0 -62
- package/dist/pages/entry-review/mobile-bar.d.ts.map +0 -1
- package/dist/pages/entry-review/mobile-bar.js +0 -155
- package/dist/pages/entry-review/mobile-bar.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deskwork/studio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Editorial review studio — local web UI for the deskwork plugin",
|
|
6
6
|
"homepage": "https://github.com/audiocontrol-org/deskwork#readme",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@codemirror/language": "^6.12.3",
|
|
47
47
|
"@codemirror/state": "^6.6.0",
|
|
48
48
|
"@codemirror/view": "^6.41.1",
|
|
49
|
-
"@deskwork/core": "0.
|
|
49
|
+
"@deskwork/core": "0.23.0",
|
|
50
50
|
"@hono/node-server": "^1.13.7",
|
|
51
51
|
"@lezer/highlight": "^1.2.3",
|
|
52
52
|
"@types/diff-match-patch": "^1.0.36",
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Press-queue sidebar — the dashboard's right column.
|
|
3
|
-
*
|
|
4
|
-
* "Press-check" gravity: at the press, the operator wants to know what
|
|
5
|
-
* needs their eyes RIGHT NOW, separately from the at-a-glance pipeline
|
|
6
|
-
* view on the left. This panel surfaces every entry in active review
|
|
7
|
-
* (`reviewState === 'in-review'`), longest-waiting first, with a soft
|
|
8
|
-
* empty state when the press is quiet.
|
|
9
|
-
*
|
|
10
|
-
* Closes the long-empty right column the dashboard's `.er-layout` grid
|
|
11
|
-
* has been declaring since the surface shipped (#158 child concern).
|
|
12
|
-
*/
|
|
13
|
-
import { type RawHtml } from '../html.ts';
|
|
14
|
-
import type { Entry } from '@deskwork/core/schema/entry';
|
|
15
|
-
export declare function renderPressQueue(entries: readonly Entry[], defaultSite: string, now: Date): RawHtml;
|
|
16
|
-
//# sourceMappingURL=press-queue.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"press-queue.d.ts","sourceRoot":"","sources":["../../../src/pages/dashboard/press-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,6BAA6B,CAAC;AAsEhE,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,KAAK,EAAE,EACzB,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,IAAI,GACR,OAAO,CAuBT"}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Press-queue sidebar — the dashboard's right column.
|
|
3
|
-
*
|
|
4
|
-
* "Press-check" gravity: at the press, the operator wants to know what
|
|
5
|
-
* needs their eyes RIGHT NOW, separately from the at-a-glance pipeline
|
|
6
|
-
* view on the left. This panel surfaces every entry in active review
|
|
7
|
-
* (`reviewState === 'in-review'`), longest-waiting first, with a soft
|
|
8
|
-
* empty state when the press is quiet.
|
|
9
|
-
*
|
|
10
|
-
* Closes the long-empty right column the dashboard's `.er-layout` grid
|
|
11
|
-
* has been declaring since the surface shipped (#158 child concern).
|
|
12
|
-
*/
|
|
13
|
-
import { html, unsafe } from "../html.js";
|
|
14
|
-
import { formatRelativeTime } from '@deskwork/core/scrapbook';
|
|
15
|
-
const STAGE_ORNAMENTS = {
|
|
16
|
-
Ideas: '◇',
|
|
17
|
-
Planned: '§',
|
|
18
|
-
Outlining: '⊹',
|
|
19
|
-
Drafting: '✎',
|
|
20
|
-
Final: '※',
|
|
21
|
-
Published: '✓',
|
|
22
|
-
Blocked: '⊘',
|
|
23
|
-
Cancelled: '✗',
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Filter the dashboard's entries to those currently in review and
|
|
27
|
-
* sort longest-waiting first. The "longest waiting" axis is `updatedAt`
|
|
28
|
-
* — every iterate / review-state-change writes to it, so the entry
|
|
29
|
-
* whose updatedAt is oldest is the one the operator has been ignoring
|
|
30
|
-
* longest.
|
|
31
|
-
*/
|
|
32
|
-
function selectAwaitingItems(entries, now) {
|
|
33
|
-
const items = [];
|
|
34
|
-
for (const entry of entries) {
|
|
35
|
-
if (entry.reviewState !== 'in-review')
|
|
36
|
-
continue;
|
|
37
|
-
const updatedAt = new Date(entry.updatedAt).getTime();
|
|
38
|
-
items.push({ entry, waitedMs: now.getTime() - updatedAt });
|
|
39
|
-
}
|
|
40
|
-
items.sort((a, b) => b.waitedMs - a.waitedMs);
|
|
41
|
-
return items;
|
|
42
|
-
}
|
|
43
|
-
function renderItem(item, defaultSite, now) {
|
|
44
|
-
const { entry } = item;
|
|
45
|
-
void defaultSite;
|
|
46
|
-
const reviewLink = `/dev/editorial-review/entry/${entry.uuid}`;
|
|
47
|
-
return unsafe(html `
|
|
48
|
-
<li class="er-press-queue__item" data-stage="${entry.currentStage}">
|
|
49
|
-
<a class="er-press-queue__link" href="${reviewLink}">
|
|
50
|
-
<span class="er-press-queue__ornament" aria-hidden="true">${STAGE_ORNAMENTS[entry.currentStage]}</span>
|
|
51
|
-
<span class="er-press-queue__body">
|
|
52
|
-
<span class="er-press-queue__slug">${entry.slug}</span>
|
|
53
|
-
<span class="er-press-queue__meta">
|
|
54
|
-
<span class="er-press-queue__stage">${entry.currentStage}</span>
|
|
55
|
-
<span class="er-press-queue__sep" aria-hidden="true">·</span>
|
|
56
|
-
<span class="er-press-queue__waited">${formatRelativeTime(entry.updatedAt, now)}</span>
|
|
57
|
-
</span>
|
|
58
|
-
</span>
|
|
59
|
-
</a>
|
|
60
|
-
</li>`);
|
|
61
|
-
}
|
|
62
|
-
function renderEmptyState() {
|
|
63
|
-
return unsafe(html `
|
|
64
|
-
<div class="er-press-queue__empty">
|
|
65
|
-
<span class="er-press-queue__empty-mark" aria-hidden="true">※</span>
|
|
66
|
-
<p class="er-press-queue__empty-line">The press is quiet.</p>
|
|
67
|
-
<p class="er-press-queue__empty-hint">Nothing in review.</p>
|
|
68
|
-
</div>`);
|
|
69
|
-
}
|
|
70
|
-
export function renderPressQueue(entries, defaultSite, now) {
|
|
71
|
-
const items = selectAwaitingItems(entries, now);
|
|
72
|
-
const body = items.length === 0
|
|
73
|
-
? renderEmptyState()
|
|
74
|
-
: unsafe(html `
|
|
75
|
-
<ol class="er-press-queue__list">
|
|
76
|
-
${unsafe(items
|
|
77
|
-
.map((item) => renderItem(item, defaultSite, now).__raw)
|
|
78
|
-
.join('\n'))}
|
|
79
|
-
</ol>`);
|
|
80
|
-
return unsafe(html `
|
|
81
|
-
<aside class="er-press-queue${items.length === 0 ? ' er-press-queue--empty' : ''}"
|
|
82
|
-
aria-label="Awaiting your eyes">
|
|
83
|
-
<header class="er-press-queue__head">
|
|
84
|
-
<p class="er-press-queue__kicker">Press queue</p>
|
|
85
|
-
<h2 class="er-press-queue__title">Awaiting your <em>eyes</em></h2>
|
|
86
|
-
<p class="er-press-queue__count">№ ${items.length}</p>
|
|
87
|
-
</header>
|
|
88
|
-
${body}
|
|
89
|
-
</aside>`);
|
|
90
|
-
}
|
|
91
|
-
//# sourceMappingURL=press-queue.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"press-queue.js","sourceRoot":"","sources":["../../../src/pages/dashboard/press-queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,eAAe,GAA0B;IAC7C,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,QAAQ,EAAE,GAAG;IACb,KAAK,EAAE,GAAG;IACV,SAAS,EAAE,GAAG;IACd,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;CACf,CAAC;AAOF;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,OAAyB,EAAE,GAAS;IAC/D,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,KAAK,WAAW;YAAE,SAAS;QAChD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CACjB,IAAkB,EAClB,WAAmB,EACnB,GAAS;IAET,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IACvB,KAAK,WAAW,CAAC;IACjB,MAAM,UAAU,GAAG,+BAA+B,KAAK,CAAC,IAAI,EAAE,CAAC;IAC/D,OAAO,MAAM,CAAC,IAAI,CAAA;mDAC+B,KAAK,CAAC,YAAY;8CACvB,UAAU;oEACY,eAAe,CAAC,KAAK,CAAC,YAAY,CAAC;;+CAExD,KAAK,CAAC,IAAI;;kDAEP,KAAK,CAAC,YAAY;;mDAEjB,kBAAkB,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,CAAC;;;;UAIjF,CAAC,CAAC;AACZ,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;WAKT,CAAC,CAAC;AACb,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAAyB,EACzB,WAAmB,EACnB,GAAS;IAET,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,IAAI,GACR,KAAK,CAAC,MAAM,KAAK,CAAC;QAChB,CAAC,CAAC,gBAAgB,EAAE;QACpB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAA;;cAEL,MAAM,CACN,KAAK;aACF,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC;aACvD,IAAI,CAAC,IAAI,CAAC,CACd;gBACG,CAAC,CAAC;IAChB,OAAO,MAAM,CAAC,IAAI,CAAA;kCACc,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE;;;;;6CAKvC,KAAK,CAAC,MAAM;;QAEjD,IAAI;aACC,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Press-queue sidebar — the dashboard's right column.
|
|
3
|
-
*
|
|
4
|
-
* "Press-check" gravity: at the press, the operator wants to know what
|
|
5
|
-
* needs their eyes RIGHT NOW, separately from the at-a-glance pipeline
|
|
6
|
-
* view on the left. This panel surfaces every entry in active review
|
|
7
|
-
* (`reviewState === 'in-review'`), longest-waiting first, with a soft
|
|
8
|
-
* empty state when the press is quiet.
|
|
9
|
-
*
|
|
10
|
-
* Closes the long-empty right column the dashboard's `.er-layout` grid
|
|
11
|
-
* has been declaring since the surface shipped (#158 child concern).
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { html, unsafe, type RawHtml } from '../html.ts';
|
|
15
|
-
import type { Entry, Stage } from '@deskwork/core/schema/entry';
|
|
16
|
-
import { formatRelativeTime } from '@deskwork/core/scrapbook';
|
|
17
|
-
|
|
18
|
-
const STAGE_ORNAMENTS: Record<Stage, string> = {
|
|
19
|
-
Ideas: '◇',
|
|
20
|
-
Planned: '§',
|
|
21
|
-
Outlining: '⊹',
|
|
22
|
-
Drafting: '✎',
|
|
23
|
-
Final: '※',
|
|
24
|
-
Published: '✓',
|
|
25
|
-
Blocked: '⊘',
|
|
26
|
-
Cancelled: '✗',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
interface AwaitingItem {
|
|
30
|
-
readonly entry: Entry;
|
|
31
|
-
readonly waitedMs: number;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Filter the dashboard's entries to those currently in review and
|
|
36
|
-
* sort longest-waiting first. The "longest waiting" axis is `updatedAt`
|
|
37
|
-
* — every iterate / review-state-change writes to it, so the entry
|
|
38
|
-
* whose updatedAt is oldest is the one the operator has been ignoring
|
|
39
|
-
* longest.
|
|
40
|
-
*/
|
|
41
|
-
function selectAwaitingItems(entries: readonly Entry[], now: Date): AwaitingItem[] {
|
|
42
|
-
const items: AwaitingItem[] = [];
|
|
43
|
-
for (const entry of entries) {
|
|
44
|
-
if (entry.reviewState !== 'in-review') continue;
|
|
45
|
-
const updatedAt = new Date(entry.updatedAt).getTime();
|
|
46
|
-
items.push({ entry, waitedMs: now.getTime() - updatedAt });
|
|
47
|
-
}
|
|
48
|
-
items.sort((a, b) => b.waitedMs - a.waitedMs);
|
|
49
|
-
return items;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function renderItem(
|
|
53
|
-
item: AwaitingItem,
|
|
54
|
-
defaultSite: string,
|
|
55
|
-
now: Date,
|
|
56
|
-
): RawHtml {
|
|
57
|
-
const { entry } = item;
|
|
58
|
-
void defaultSite;
|
|
59
|
-
const reviewLink = `/dev/editorial-review/entry/${entry.uuid}`;
|
|
60
|
-
return unsafe(html`
|
|
61
|
-
<li class="er-press-queue__item" data-stage="${entry.currentStage}">
|
|
62
|
-
<a class="er-press-queue__link" href="${reviewLink}">
|
|
63
|
-
<span class="er-press-queue__ornament" aria-hidden="true">${STAGE_ORNAMENTS[entry.currentStage]}</span>
|
|
64
|
-
<span class="er-press-queue__body">
|
|
65
|
-
<span class="er-press-queue__slug">${entry.slug}</span>
|
|
66
|
-
<span class="er-press-queue__meta">
|
|
67
|
-
<span class="er-press-queue__stage">${entry.currentStage}</span>
|
|
68
|
-
<span class="er-press-queue__sep" aria-hidden="true">·</span>
|
|
69
|
-
<span class="er-press-queue__waited">${formatRelativeTime(entry.updatedAt, now)}</span>
|
|
70
|
-
</span>
|
|
71
|
-
</span>
|
|
72
|
-
</a>
|
|
73
|
-
</li>`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function renderEmptyState(): RawHtml {
|
|
77
|
-
return unsafe(html`
|
|
78
|
-
<div class="er-press-queue__empty">
|
|
79
|
-
<span class="er-press-queue__empty-mark" aria-hidden="true">※</span>
|
|
80
|
-
<p class="er-press-queue__empty-line">The press is quiet.</p>
|
|
81
|
-
<p class="er-press-queue__empty-hint">Nothing in review.</p>
|
|
82
|
-
</div>`);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function renderPressQueue(
|
|
86
|
-
entries: readonly Entry[],
|
|
87
|
-
defaultSite: string,
|
|
88
|
-
now: Date,
|
|
89
|
-
): RawHtml {
|
|
90
|
-
const items = selectAwaitingItems(entries, now);
|
|
91
|
-
const body =
|
|
92
|
-
items.length === 0
|
|
93
|
-
? renderEmptyState()
|
|
94
|
-
: unsafe(html`
|
|
95
|
-
<ol class="er-press-queue__list">
|
|
96
|
-
${unsafe(
|
|
97
|
-
items
|
|
98
|
-
.map((item) => renderItem(item, defaultSite, now).__raw)
|
|
99
|
-
.join('\n'),
|
|
100
|
-
)}
|
|
101
|
-
</ol>`);
|
|
102
|
-
return unsafe(html`
|
|
103
|
-
<aside class="er-press-queue${items.length === 0 ? ' er-press-queue--empty' : ''}"
|
|
104
|
-
aria-label="Awaiting your eyes">
|
|
105
|
-
<header class="er-press-queue__head">
|
|
106
|
-
<p class="er-press-queue__kicker">Press queue</p>
|
|
107
|
-
<h2 class="er-press-queue__title">Awaiting your <em>eyes</em></h2>
|
|
108
|
-
<p class="er-press-queue__count">№ ${items.length}</p>
|
|
109
|
-
</header>
|
|
110
|
-
${body}
|
|
111
|
-
</aside>`);
|
|
112
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mobile bottom-bar + sheet host for the entry-keyed review surface.
|
|
3
|
-
*
|
|
4
|
-
* Renders a 3-tab bottom bar and a sheet host that slides up from the
|
|
5
|
-
* viewport bottom. Visible only at <48rem (phone widths) — see
|
|
6
|
-
* editorial-review.css. Above that the bar and sheet are display:none
|
|
7
|
-
* and the desktop layout (in-flow marginalia column, outline-drawer
|
|
8
|
-
* overlay, decision strip in the top strip) carries the surface.
|
|
9
|
-
*
|
|
10
|
-
* Design references:
|
|
11
|
-
* - Review tabs: plugins/deskwork-studio/public/mockups/mobile-1-bottom-sheet.html
|
|
12
|
-
* - Editor tabs: plugins/deskwork-studio/public/mockups/editor-2-press-check-tabbar.html
|
|
13
|
-
*
|
|
14
|
-
* The bar carries SIX tab buttons; CSS shows three or four at a time
|
|
15
|
-
* keyed off `body[data-edit-mode="editing"]`:
|
|
16
|
-
* - Review mode: Outline · Notes · Scrapbook · Actions (4-column grid)
|
|
17
|
-
* - Edit mode: Format · Notes · Save (3-column grid)
|
|
18
|
-
* The Notes tab is shared between modes (review notes the operator
|
|
19
|
-
* leaves carry across into edit). The bar's data-mode attribute is
|
|
20
|
-
* also flipped by the client so additional state-dependent styles
|
|
21
|
-
* (Save dirty glow, etc.) can key off it. The Scrapbook tab uses a
|
|
22
|
-
* grid glyph (▦) and a kraft-tone count badge to distinguish it
|
|
23
|
-
* from the red-pencil Notes badge — folio is "context for the
|
|
24
|
-
* entry," not an action peer of decisions.
|
|
25
|
-
*
|
|
26
|
-
* The sheet has five content slots (outline / notes / actions /
|
|
27
|
-
* scrapbook / format).
|
|
28
|
-
* The client controller (`entry-review/mobile-sheet-bar.ts`) populates
|
|
29
|
-
* each at first open. Slot sources:
|
|
30
|
-
* - outline: clone of `.er-outline-drawer-body`
|
|
31
|
-
* - notes: actual `[data-sidebar-list]` element MOVED in on phone
|
|
32
|
-
* (preserves event listeners; see mobile-sheet-bar.ts)
|
|
33
|
-
* - actions: rendered fresh from the decision verbs
|
|
34
|
-
* - format: the press-check key grid rendered server-side below
|
|
35
|
-
*
|
|
36
|
-
* The Save tab is NOT a sheet — it triggers the existing
|
|
37
|
-
* `[data-action="save-version"]` handler directly (the one allowed
|
|
38
|
-
* file mutation per THESIS Consequence 2).
|
|
39
|
-
*/
|
|
40
|
-
import { type RawHtml } from '../html.ts';
|
|
41
|
-
export declare function renderMobileBar(): RawHtml;
|
|
42
|
-
export declare function renderMobileSheet(): RawHtml;
|
|
43
|
-
/**
|
|
44
|
-
* Phone-only Source/Preview pill rendered into the top strip when in
|
|
45
|
-
* edit mode. Uses the same `data-edit-view` attribute as the desktop
|
|
46
|
-
* edit toolbar so `editModeBtns` (queried via that attribute in
|
|
47
|
-
* entry-review-client.ts) auto-binds clicks. CSS reveals it only on
|
|
48
|
-
* phone + edit mode; the desktop edit toolbar is hidden in that
|
|
49
|
-
* combination.
|
|
50
|
-
*/
|
|
51
|
-
export declare function renderStripModeSegment(): RawHtml;
|
|
52
|
-
/**
|
|
53
|
-
* Phone-only "✕ Done" exit affordance in the strip. Visible only when
|
|
54
|
-
* editing on phone (CSS-gated). Click dispatches into the existing
|
|
55
|
-
* toggle-edit handler — preserves the confirmDiscard prompt when the
|
|
56
|
-
* buffer is dirty, immediate exit when clean. Sits alongside the
|
|
57
|
-
* existing back-link (which continues to navigate home regardless of
|
|
58
|
-
* mode) so the operator always has both "leave editor" and "leave
|
|
59
|
-
* page" affordances available.
|
|
60
|
-
*/
|
|
61
|
-
export declare function renderStripEditExit(): RawHtml;
|
|
62
|
-
//# sourceMappingURL=mobile-bar.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mobile-bar.d.ts","sourceRoot":"","sources":["../../../src/pages/entry-review/mobile-bar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAgB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAExD,wBAAgB,eAAe,IAAI,OAAO,CA8BzC;AA2BD,wBAAgB,iBAAiB,IAAI,OAAO,CA2B3C;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAMhD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAM7C"}
|
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mobile bottom-bar + sheet host for the entry-keyed review surface.
|
|
3
|
-
*
|
|
4
|
-
* Renders a 3-tab bottom bar and a sheet host that slides up from the
|
|
5
|
-
* viewport bottom. Visible only at <48rem (phone widths) — see
|
|
6
|
-
* editorial-review.css. Above that the bar and sheet are display:none
|
|
7
|
-
* and the desktop layout (in-flow marginalia column, outline-drawer
|
|
8
|
-
* overlay, decision strip in the top strip) carries the surface.
|
|
9
|
-
*
|
|
10
|
-
* Design references:
|
|
11
|
-
* - Review tabs: plugins/deskwork-studio/public/mockups/mobile-1-bottom-sheet.html
|
|
12
|
-
* - Editor tabs: plugins/deskwork-studio/public/mockups/editor-2-press-check-tabbar.html
|
|
13
|
-
*
|
|
14
|
-
* The bar carries SIX tab buttons; CSS shows three or four at a time
|
|
15
|
-
* keyed off `body[data-edit-mode="editing"]`:
|
|
16
|
-
* - Review mode: Outline · Notes · Scrapbook · Actions (4-column grid)
|
|
17
|
-
* - Edit mode: Format · Notes · Save (3-column grid)
|
|
18
|
-
* The Notes tab is shared between modes (review notes the operator
|
|
19
|
-
* leaves carry across into edit). The bar's data-mode attribute is
|
|
20
|
-
* also flipped by the client so additional state-dependent styles
|
|
21
|
-
* (Save dirty glow, etc.) can key off it. The Scrapbook tab uses a
|
|
22
|
-
* grid glyph (▦) and a kraft-tone count badge to distinguish it
|
|
23
|
-
* from the red-pencil Notes badge — folio is "context for the
|
|
24
|
-
* entry," not an action peer of decisions.
|
|
25
|
-
*
|
|
26
|
-
* The sheet has five content slots (outline / notes / actions /
|
|
27
|
-
* scrapbook / format).
|
|
28
|
-
* The client controller (`entry-review/mobile-sheet-bar.ts`) populates
|
|
29
|
-
* each at first open. Slot sources:
|
|
30
|
-
* - outline: clone of `.er-outline-drawer-body`
|
|
31
|
-
* - notes: actual `[data-sidebar-list]` element MOVED in on phone
|
|
32
|
-
* (preserves event listeners; see mobile-sheet-bar.ts)
|
|
33
|
-
* - actions: rendered fresh from the decision verbs
|
|
34
|
-
* - format: the press-check key grid rendered server-side below
|
|
35
|
-
*
|
|
36
|
-
* The Save tab is NOT a sheet — it triggers the existing
|
|
37
|
-
* `[data-action="save-version"]` handler directly (the one allowed
|
|
38
|
-
* file mutation per THESIS Consequence 2).
|
|
39
|
-
*/
|
|
40
|
-
import { html, unsafe } from "../html.js";
|
|
41
|
-
export function renderMobileBar() {
|
|
42
|
-
return unsafe(html `
|
|
43
|
-
<nav class="er-mobile-bar" data-mobile-bar aria-label="Surface tabs">
|
|
44
|
-
<button class="er-mobile-tab er-mobile-tab--review" data-mobile-sheet="outline" type="button" aria-controls="er-mobile-sheet" aria-expanded="false">
|
|
45
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">§</span>
|
|
46
|
-
<span class="er-mobile-tab-label">Outline</span>
|
|
47
|
-
</button>
|
|
48
|
-
<button class="er-mobile-tab er-mobile-tab--edit" data-mobile-sheet="format" type="button" aria-controls="er-mobile-sheet" aria-expanded="false">
|
|
49
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">¶</span>
|
|
50
|
-
<span class="er-mobile-tab-label">Format</span>
|
|
51
|
-
</button>
|
|
52
|
-
<button class="er-mobile-tab" data-mobile-sheet="notes" type="button" aria-controls="er-mobile-sheet" aria-expanded="false">
|
|
53
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">✎</span>
|
|
54
|
-
<span class="er-mobile-tab-label">Notes</span>
|
|
55
|
-
<span class="er-mobile-tab-count" data-notes-count hidden>0</span>
|
|
56
|
-
</button>
|
|
57
|
-
<button class="er-mobile-tab er-mobile-tab--review er-mobile-tab--scrapbook" data-mobile-sheet="scrapbook" type="button" aria-controls="er-mobile-sheet" aria-expanded="false">
|
|
58
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">▦</span>
|
|
59
|
-
<span class="er-mobile-tab-label">Scrapbook</span>
|
|
60
|
-
<span class="er-mobile-tab-count er-mobile-tab-count--kraft" data-scrapbook-count hidden>0</span>
|
|
61
|
-
</button>
|
|
62
|
-
<button class="er-mobile-tab er-mobile-tab--review" data-mobile-sheet="actions" type="button" aria-controls="er-mobile-sheet" aria-expanded="false">
|
|
63
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">⊕</span>
|
|
64
|
-
<span class="er-mobile-tab-label">Actions</span>
|
|
65
|
-
</button>
|
|
66
|
-
<button class="er-mobile-tab er-mobile-tab--edit er-mobile-tab--save" data-mobile-action="save" type="button">
|
|
67
|
-
<span class="er-mobile-tab-glyph" aria-hidden="true">⊕</span>
|
|
68
|
-
<span class="er-mobile-tab-label">Save</span>
|
|
69
|
-
</button>
|
|
70
|
-
</nav>`);
|
|
71
|
-
}
|
|
72
|
-
function renderFormatGrid() {
|
|
73
|
-
return html `
|
|
74
|
-
<div class="er-fkey-section">Headings</div>
|
|
75
|
-
<div class="er-fkey-grid">
|
|
76
|
-
<button type="button" class="er-fkey er-fkey--h1" data-fkey="h1"><span class="er-fkey-face">H1</span><span class="er-fkey-label">Title</span></button>
|
|
77
|
-
<button type="button" class="er-fkey er-fkey--h2" data-fkey="h2"><span class="er-fkey-face">H2</span><span class="er-fkey-label">Section</span></button>
|
|
78
|
-
<button type="button" class="er-fkey er-fkey--h3" data-fkey="h3"><span class="er-fkey-face">H3</span><span class="er-fkey-label">Sub</span></button>
|
|
79
|
-
<button type="button" class="er-fkey er-fkey--hr" data-fkey="hr"><span class="er-fkey-face">— · — · —</span><span class="er-fkey-label">Rule</span></button>
|
|
80
|
-
</div>
|
|
81
|
-
<div class="er-fkey-section">Inline</div>
|
|
82
|
-
<div class="er-fkey-grid">
|
|
83
|
-
<button type="button" class="er-fkey er-fkey--bold" data-fkey="bold"><span class="er-fkey-face"><strong>B</strong></span><span class="er-fkey-label">Bold</span></button>
|
|
84
|
-
<button type="button" class="er-fkey er-fkey--em" data-fkey="em"><span class="er-fkey-face"><em>I</em></span><span class="er-fkey-label">Italic</span></button>
|
|
85
|
-
<button type="button" class="er-fkey er-fkey--code" data-fkey="code"><span class="er-fkey-face">\` \`</span><span class="er-fkey-label">Code</span></button>
|
|
86
|
-
<button type="button" class="er-fkey er-fkey--link" data-fkey="link"><span class="er-fkey-face">link</span><span class="er-fkey-label">Link</span></button>
|
|
87
|
-
</div>
|
|
88
|
-
<div class="er-fkey-section">Block</div>
|
|
89
|
-
<div class="er-fkey-grid">
|
|
90
|
-
<button type="button" class="er-fkey er-fkey--list" data-fkey="list"><span class="er-fkey-face">— ·<br>— ·</span><span class="er-fkey-label">List</span></button>
|
|
91
|
-
<button type="button" class="er-fkey er-fkey--ol" data-fkey="ol"><span class="er-fkey-face">1·<br>2·</span><span class="er-fkey-label">Numbered</span></button>
|
|
92
|
-
<button type="button" class="er-fkey er-fkey--quote" data-fkey="quote"><span class="er-fkey-face">"</span><span class="er-fkey-label">Quote</span></button>
|
|
93
|
-
<button type="button" class="er-fkey er-fkey--fence" data-fkey="fence"><span class="er-fkey-face">\`\`\`</span><span class="er-fkey-label">Code block</span></button>
|
|
94
|
-
</div>`;
|
|
95
|
-
}
|
|
96
|
-
export function renderMobileSheet() {
|
|
97
|
-
return unsafe(html `
|
|
98
|
-
<section
|
|
99
|
-
class="er-mobile-sheet"
|
|
100
|
-
id="er-mobile-sheet"
|
|
101
|
-
data-mobile-sheet-host
|
|
102
|
-
hidden
|
|
103
|
-
aria-label="Surface sheet"
|
|
104
|
-
role="dialog"
|
|
105
|
-
aria-modal="false"
|
|
106
|
-
>
|
|
107
|
-
<button class="er-mobile-sheet-handle" data-mobile-sheet-handle type="button" aria-label="Drag to dismiss the sheet">
|
|
108
|
-
<span class="er-mobile-sheet-handle-bar" aria-hidden="true"></span>
|
|
109
|
-
</button>
|
|
110
|
-
<header class="er-mobile-sheet-head">
|
|
111
|
-
<span class="er-mobile-sheet-kicker" data-mobile-sheet-kicker></span>
|
|
112
|
-
<span class="er-mobile-sheet-meta" data-mobile-sheet-meta></span>
|
|
113
|
-
<button class="er-mobile-sheet-close" data-mobile-sheet-close type="button" aria-label="Close sheet">×</button>
|
|
114
|
-
</header>
|
|
115
|
-
<div class="er-mobile-sheet-body" data-mobile-sheet-body>
|
|
116
|
-
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="outline" hidden></div>
|
|
117
|
-
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="notes" hidden></div>
|
|
118
|
-
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="actions" hidden></div>
|
|
119
|
-
<div class="er-mobile-sheet-slot er-mobile-sheet-slot--scrapbook" data-mobile-sheet-slot="scrapbook" hidden></div>
|
|
120
|
-
<div class="er-mobile-sheet-slot er-mobile-sheet-slot--format" data-mobile-sheet-slot="format" hidden>${unsafe(renderFormatGrid())}</div>
|
|
121
|
-
</div>
|
|
122
|
-
</section>`);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Phone-only Source/Preview pill rendered into the top strip when in
|
|
126
|
-
* edit mode. Uses the same `data-edit-view` attribute as the desktop
|
|
127
|
-
* edit toolbar so `editModeBtns` (queried via that attribute in
|
|
128
|
-
* entry-review-client.ts) auto-binds clicks. CSS reveals it only on
|
|
129
|
-
* phone + edit mode; the desktop edit toolbar is hidden in that
|
|
130
|
-
* combination.
|
|
131
|
-
*/
|
|
132
|
-
export function renderStripModeSegment() {
|
|
133
|
-
return unsafe(html `
|
|
134
|
-
<span class="er-strip-mode-mobile" data-strip-mode-mobile aria-hidden="true">
|
|
135
|
-
<button type="button" class="er-strip-mode-btn" data-edit-view="source" aria-pressed="true">Source</button>
|
|
136
|
-
<button type="button" class="er-strip-mode-btn" data-edit-view="preview" aria-pressed="false">Preview</button>
|
|
137
|
-
</span>`);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Phone-only "✕ Done" exit affordance in the strip. Visible only when
|
|
141
|
-
* editing on phone (CSS-gated). Click dispatches into the existing
|
|
142
|
-
* toggle-edit handler — preserves the confirmDiscard prompt when the
|
|
143
|
-
* buffer is dirty, immediate exit when clean. Sits alongside the
|
|
144
|
-
* existing back-link (which continues to navigate home regardless of
|
|
145
|
-
* mode) so the operator always has both "leave editor" and "leave
|
|
146
|
-
* page" affordances available.
|
|
147
|
-
*/
|
|
148
|
-
export function renderStripEditExit() {
|
|
149
|
-
return unsafe(html `
|
|
150
|
-
<button type="button" class="er-strip-edit-done" data-strip-edit-done aria-label="Exit editor">
|
|
151
|
-
<span class="er-strip-edit-done-glyph" aria-hidden="true">✕</span>
|
|
152
|
-
<span class="er-strip-edit-done-label">Done</span>
|
|
153
|
-
</button>`);
|
|
154
|
-
}
|
|
155
|
-
//# sourceMappingURL=mobile-bar.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mobile-bar.js","sourceRoot":"","sources":["../../../src/pages/entry-review/mobile-bar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAExD,MAAM,UAAU,eAAe;IAC7B,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BT,CAAC,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;WAqBF,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,MAAM,CAAC,IAAI,CAAA;;;;;;;;;;;;;;;;;;;;;;;gHAuB4F,MAAM,CAAC,gBAAgB,EAAE,CAAC;;eAE3H,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB;IACpC,OAAO,MAAM,CAAC,IAAI,CAAA;;;;YAIR,CAAC,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,MAAM,CAAC,IAAI,CAAA;;;;cAIN,CAAC,CAAC;AAChB,CAAC"}
|