@deskwork/studio 0.21.0 → 0.22.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/dist/pages/dashboard/adjacent-section.d.ts +38 -0
- package/dist/pages/dashboard/adjacent-section.d.ts.map +1 -0
- package/dist/pages/dashboard/adjacent-section.js +61 -0
- package/dist/pages/dashboard/adjacent-section.js.map +1 -0
- package/dist/pages/dashboard/adjacent-section.ts +71 -0
- package/dist/pages/dashboard/data.d.ts +35 -4
- package/dist/pages/dashboard/data.d.ts.map +1 -1
- package/dist/pages/dashboard/data.js +69 -5
- package/dist/pages/dashboard/data.js.map +1 -1
- package/dist/pages/dashboard/data.ts +84 -5
- package/dist/pages/dashboard/press-queue.d.ts +16 -0
- package/dist/pages/dashboard/press-queue.d.ts.map +1 -0
- package/dist/pages/dashboard/press-queue.js +91 -0
- package/dist/pages/dashboard/press-queue.js.map +1 -0
- package/dist/pages/dashboard/press-queue.ts +112 -0
- package/dist/pages/dashboard/section.d.ts.map +1 -1
- package/dist/pages/dashboard/section.js +7 -0
- package/dist/pages/dashboard/section.js.map +1 -1
- package/dist/pages/dashboard/section.ts +7 -0
- package/dist/pages/dashboard/shortform-section.d.ts +86 -0
- package/dist/pages/dashboard/shortform-section.d.ts.map +1 -0
- package/dist/pages/dashboard/shortform-section.js +189 -0
- package/dist/pages/dashboard/shortform-section.js.map +1 -0
- package/dist/pages/dashboard/shortform-section.ts +228 -0
- package/dist/pages/dashboard.d.ts.map +1 -1
- package/dist/pages/dashboard.js +34 -1
- package/dist/pages/dashboard.js.map +1 -1
- package/dist/pages/dashboard.ts +40 -1
- package/dist/pages/entry-review/index.d.ts.map +1 -1
- package/dist/pages/entry-review/index.js +24 -2
- package/dist/pages/entry-review/index.js.map +1 -1
- package/dist/pages/entry-review/mobile-sheet.d.ts +65 -0
- package/dist/pages/entry-review/mobile-sheet.d.ts.map +1 -0
- package/dist/pages/entry-review/mobile-sheet.js +170 -0
- package/dist/pages/entry-review/mobile-sheet.js.map +1 -0
- package/dist/pages/masthead-menu.d.ts +38 -0
- package/dist/pages/masthead-menu.d.ts.map +1 -0
- package/dist/pages/masthead-menu.js +126 -0
- package/dist/pages/masthead-menu.js.map +1 -0
- package/dist/pages/masthead-menu.ts +128 -0
- package/dist/pages/masthead.d.ts +85 -0
- package/dist/pages/masthead.d.ts.map +1 -0
- package/dist/pages/masthead.js +99 -0
- package/dist/pages/masthead.js.map +1 -0
- package/dist/pages/masthead.ts +155 -0
- package/dist/pages/mobile-bar.d.ts +72 -0
- package/dist/pages/mobile-bar.d.ts.map +1 -0
- package/dist/pages/mobile-bar.js +88 -0
- package/dist/pages/mobile-bar.js.map +1 -0
- package/dist/pages/mobile-bar.ts +129 -0
- package/dist/pages/shortform-review-mobile-sheet.d.ts +76 -0
- package/dist/pages/shortform-review-mobile-sheet.d.ts.map +1 -0
- package/dist/pages/shortform-review-mobile-sheet.js +159 -0
- package/dist/pages/shortform-review-mobile-sheet.js.map +1 -0
- package/dist/pages/shortform-review-mobile-sheet.ts +185 -0
- package/dist/pages/shortform-review.d.ts +18 -0
- package/dist/pages/shortform-review.d.ts.map +1 -1
- package/dist/pages/shortform-review.js +62 -111
- package/dist/pages/shortform-review.js.map +1 -1
- package/dist/pages/shortform-review.ts +68 -140
- package/dist/pages/shortform.d.ts.map +1 -1
- package/dist/pages/shortform.js +0 -1
- package/dist/pages/shortform.js.map +1 -1
- package/dist/pages/shortform.ts +0 -1
- package/dist/server.js +41 -1
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortform-review-specific mobile sheet host + bar cell composition.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `entry-review/mobile-sheet.ts` for the shortform review
|
|
5
|
+
* surface. The mobile-bar primitive (`../mobile-bar.ts`) is universal;
|
|
6
|
+
* each surface composes its `Cell[]` and the corresponding slot host
|
|
7
|
+
* here.
|
|
8
|
+
*
|
|
9
|
+
* Design contract (DESIGN-STANDARDS.md § Universal bar contract,
|
|
10
|
+
* settled 2026-05-13):
|
|
11
|
+
* - One bar primitive, one shape. The per-surface design variable
|
|
12
|
+
* is the cells, not the chrome.
|
|
13
|
+
* - 1-6 contextual cells. The Actions cell is unconditional so the
|
|
14
|
+
* bar is never empty (renderMobileBar throws on empty cells).
|
|
15
|
+
* - The TOC and Versions cells are conditional (hidden when their
|
|
16
|
+
* content has fewer than 2 items).
|
|
17
|
+
*
|
|
18
|
+
* State-machine compliance (DESKWORK-STATE-MACHINE.md):
|
|
19
|
+
* - Commandment II: verbs are universal. Approve/Iterate/Cancel are
|
|
20
|
+
* rendered unconditionally inside the Actions slot. The shortform
|
|
21
|
+
* surface header (shortform-review.ts:1-18) explicitly defers the
|
|
22
|
+
* legacy `DraftWorkflowState` migration; for this step we surface
|
|
23
|
+
* the three universal verbs and trust the client clipboard handlers
|
|
24
|
+
* to compose the right slash command from the workflow context.
|
|
25
|
+
* - Commandment III: no review-state surfacing. No "IN REVIEW" /
|
|
26
|
+
* "ITERATING" / "APPROVED" pills. No `.er-stamp`. No
|
|
27
|
+
* `.er-pending-state` markup.
|
|
28
|
+
* - Commandment IV/V/VII: clipboard-copy is the only action. The
|
|
29
|
+
* three buttons carry `data-action="approve|iterate|cancel"`; the
|
|
30
|
+
* existing client handlers in `editorial-review-client.ts` wire
|
|
31
|
+
* them to clipboard-only handlers (post-G.3 refactor).
|
|
32
|
+
* - G.4 (issue #260): the destructive verb is `cancel`, NOT `reject`.
|
|
33
|
+
* The state machine has no `reject` verb.
|
|
34
|
+
*/
|
|
35
|
+
import { html, unsafe, escapeHtml } from "./html.js";
|
|
36
|
+
/**
|
|
37
|
+
* Build the shortform review bar's contextual cell list.
|
|
38
|
+
*
|
|
39
|
+
* Cell ordering (when present): TOC → Versions → Actions. The Actions
|
|
40
|
+
* cell is always last and always present; the bar is never empty.
|
|
41
|
+
*
|
|
42
|
+
* Conditional-omission rules:
|
|
43
|
+
* - TOC cell: omitted when fewer than 2 heading entries exist.
|
|
44
|
+
* Shortform drafts (social-platform copy) are often headingless;
|
|
45
|
+
* surfacing an empty TOC adds noise without value per the
|
|
46
|
+
* "structure over scrolling" principle.
|
|
47
|
+
* - Versions cell: omitted when only one revision exists. With one
|
|
48
|
+
* revision there is no history to navigate.
|
|
49
|
+
*/
|
|
50
|
+
export function getShortformBarCells(opts) {
|
|
51
|
+
const cells = [];
|
|
52
|
+
if (opts.tocEntries.length >= 2) {
|
|
53
|
+
cells.push({
|
|
54
|
+
glyph: '§',
|
|
55
|
+
label: `TOC · ${opts.tocEntries.length}`,
|
|
56
|
+
mode: 'review',
|
|
57
|
+
action: { kind: 'sheet', name: 'toc' },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (opts.versions.length >= 2) {
|
|
61
|
+
cells.push({
|
|
62
|
+
glyph: '№',
|
|
63
|
+
label: `Versions · ${opts.versions.length}`,
|
|
64
|
+
mode: 'review',
|
|
65
|
+
action: { kind: 'sheet', name: 'versions' },
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
cells.push({
|
|
69
|
+
glyph: '⊕',
|
|
70
|
+
label: 'Actions',
|
|
71
|
+
mode: 'review',
|
|
72
|
+
action: { kind: 'sheet', name: 'actions' },
|
|
73
|
+
});
|
|
74
|
+
return cells;
|
|
75
|
+
}
|
|
76
|
+
function renderTocSlotBody(tocEntries) {
|
|
77
|
+
if (tocEntries.length === 0)
|
|
78
|
+
return '';
|
|
79
|
+
const items = tocEntries
|
|
80
|
+
.map((entry) => {
|
|
81
|
+
const depthClass = `er-mobile-toc-item er-mobile-toc-item--h${entry.depth}`;
|
|
82
|
+
return `<li class="${depthClass}"><a href="#${escapeHtml(entry.id)}">${escapeHtml(entry.text)}</a></li>`;
|
|
83
|
+
})
|
|
84
|
+
.join('');
|
|
85
|
+
return `<ul class="er-mobile-toc-list">${items}</ul>`;
|
|
86
|
+
}
|
|
87
|
+
function renderVersionsSlotBody(versions, currentVersion) {
|
|
88
|
+
if (versions.length === 0)
|
|
89
|
+
return '';
|
|
90
|
+
const items = versions
|
|
91
|
+
.map((v) => {
|
|
92
|
+
const isActive = v.version === currentVersion.version;
|
|
93
|
+
const cls = isActive ? ' class="active"' : '';
|
|
94
|
+
return `<li class="er-mobile-versions-item"><a href="?v=${v.version}"${cls}>v${v.version}</a></li>`;
|
|
95
|
+
})
|
|
96
|
+
.join('');
|
|
97
|
+
return `<ul class="er-mobile-versions-list">${items}</ul>`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The Actions slot renders the three universal verbs unconditionally
|
|
101
|
+
* per Commandment II. Per Commandment VII (and THESIS Cons. 2), each
|
|
102
|
+
* button is a clipboard-copy trigger handled by the existing
|
|
103
|
+
* `editorial-review-client.ts` `[data-action]` listeners — the markup
|
|
104
|
+
* here carries no copy-target or state mutation logic; the client
|
|
105
|
+
* composes the slash command from the embedded workflow state.
|
|
106
|
+
*
|
|
107
|
+
* G.4: `data-action="cancel"`, NOT `reject` (the state machine has
|
|
108
|
+
* no `reject` verb; this matches issue #260's resolution shape).
|
|
109
|
+
*/
|
|
110
|
+
function renderActionsSlotBody() {
|
|
111
|
+
return [
|
|
112
|
+
'<div class="er-mobile-actions">',
|
|
113
|
+
' <button class="er-btn er-btn-primary er-btn-approve" data-action="approve" type="button">Approve</button>',
|
|
114
|
+
' <button class="er-btn" data-action="iterate" type="button">Iterate</button>',
|
|
115
|
+
' <button class="er-btn er-btn-cancel" data-action="cancel" type="button">Cancel</button>',
|
|
116
|
+
'</div>',
|
|
117
|
+
].join('\n');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Render the shortform mobile sheet host with the three named slots
|
|
121
|
+
* (toc / versions / actions). Each slot body is server-rendered so
|
|
122
|
+
* the client doesn't need to clone DOM from elsewhere on the page —
|
|
123
|
+
* the slot is self-contained.
|
|
124
|
+
*
|
|
125
|
+
* The sheet host is always rendered (matches the entry-review pattern
|
|
126
|
+
* where the host is present and the client toggles `hidden` on
|
|
127
|
+
* dispatch). Individual slots are hidden until the corresponding bar
|
|
128
|
+
* cell opens them via the shared `sheet-controller` primitive.
|
|
129
|
+
*/
|
|
130
|
+
export function renderShortformMobileSheet(opts) {
|
|
131
|
+
const tocBody = renderTocSlotBody(opts.tocEntries);
|
|
132
|
+
const versionsBody = renderVersionsSlotBody(opts.versions, opts.currentVersion);
|
|
133
|
+
const actionsBody = renderActionsSlotBody();
|
|
134
|
+
return unsafe(html `
|
|
135
|
+
<section
|
|
136
|
+
class="er-mobile-sheet"
|
|
137
|
+
id="er-mobile-sheet"
|
|
138
|
+
data-mobile-sheet-host
|
|
139
|
+
hidden
|
|
140
|
+
aria-label="Surface sheet"
|
|
141
|
+
role="dialog"
|
|
142
|
+
aria-modal="false"
|
|
143
|
+
>
|
|
144
|
+
<button class="er-mobile-sheet-handle" data-mobile-sheet-handle type="button" aria-label="Drag to dismiss the sheet">
|
|
145
|
+
<span class="er-mobile-sheet-handle-bar" aria-hidden="true"></span>
|
|
146
|
+
</button>
|
|
147
|
+
<header class="er-mobile-sheet-head">
|
|
148
|
+
<span class="er-mobile-sheet-kicker" data-mobile-sheet-kicker></span>
|
|
149
|
+
<span class="er-mobile-sheet-meta" data-mobile-sheet-meta></span>
|
|
150
|
+
<button class="er-mobile-sheet-close" data-mobile-sheet-close type="button" aria-label="Close sheet">×</button>
|
|
151
|
+
</header>
|
|
152
|
+
<div class="er-mobile-sheet-body" data-mobile-sheet-body>
|
|
153
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="toc" hidden>${unsafe(tocBody)}</div>
|
|
154
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="versions" hidden>${unsafe(versionsBody)}</div>
|
|
155
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="actions" hidden>${unsafe(actionsBody)}</div>
|
|
156
|
+
</div>
|
|
157
|
+
</section>`);
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=shortform-review-mobile-sheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortform-review-mobile-sheet.js","sourceRoot":"","sources":["../../src/pages/shortform-review-mobile-sheet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shortform-review-specific mobile sheet host + bar cell composition.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `entry-review/mobile-sheet.ts` for the shortform review
|
|
5
|
+
* surface. The mobile-bar primitive (`../mobile-bar.ts`) is universal;
|
|
6
|
+
* each surface composes its `Cell[]` and the corresponding slot host
|
|
7
|
+
* here.
|
|
8
|
+
*
|
|
9
|
+
* Design contract (DESIGN-STANDARDS.md § Universal bar contract,
|
|
10
|
+
* settled 2026-05-13):
|
|
11
|
+
* - One bar primitive, one shape. The per-surface design variable
|
|
12
|
+
* is the cells, not the chrome.
|
|
13
|
+
* - 1-6 contextual cells. The Actions cell is unconditional so the
|
|
14
|
+
* bar is never empty (renderMobileBar throws on empty cells).
|
|
15
|
+
* - The TOC and Versions cells are conditional (hidden when their
|
|
16
|
+
* content has fewer than 2 items).
|
|
17
|
+
*
|
|
18
|
+
* State-machine compliance (DESKWORK-STATE-MACHINE.md):
|
|
19
|
+
* - Commandment II: verbs are universal. Approve/Iterate/Cancel are
|
|
20
|
+
* rendered unconditionally inside the Actions slot. The shortform
|
|
21
|
+
* surface header (shortform-review.ts:1-18) explicitly defers the
|
|
22
|
+
* legacy `DraftWorkflowState` migration; for this step we surface
|
|
23
|
+
* the three universal verbs and trust the client clipboard handlers
|
|
24
|
+
* to compose the right slash command from the workflow context.
|
|
25
|
+
* - Commandment III: no review-state surfacing. No "IN REVIEW" /
|
|
26
|
+
* "ITERATING" / "APPROVED" pills. No `.er-stamp`. No
|
|
27
|
+
* `.er-pending-state` markup.
|
|
28
|
+
* - Commandment IV/V/VII: clipboard-copy is the only action. The
|
|
29
|
+
* three buttons carry `data-action="approve|iterate|cancel"`; the
|
|
30
|
+
* existing client handlers in `editorial-review-client.ts` wire
|
|
31
|
+
* them to clipboard-only handlers (post-G.3 refactor).
|
|
32
|
+
* - G.4 (issue #260): the destructive verb is `cancel`, NOT `reject`.
|
|
33
|
+
* The state machine has no `reject` verb.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import type { TocEntry } from '@deskwork/core/review/toc';
|
|
37
|
+
import type {
|
|
38
|
+
DraftVersion,
|
|
39
|
+
DraftWorkflowItem,
|
|
40
|
+
} from '@deskwork/core/review/types';
|
|
41
|
+
import { html, unsafe, escapeHtml, type RawHtml } from './html.ts';
|
|
42
|
+
import type { Cell } from './mobile-bar.ts';
|
|
43
|
+
|
|
44
|
+
export interface ShortformBarCellOptions {
|
|
45
|
+
readonly tocEntries: readonly TocEntry[];
|
|
46
|
+
readonly versions: readonly DraftVersion[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Build the shortform review bar's contextual cell list.
|
|
51
|
+
*
|
|
52
|
+
* Cell ordering (when present): TOC → Versions → Actions. The Actions
|
|
53
|
+
* cell is always last and always present; the bar is never empty.
|
|
54
|
+
*
|
|
55
|
+
* Conditional-omission rules:
|
|
56
|
+
* - TOC cell: omitted when fewer than 2 heading entries exist.
|
|
57
|
+
* Shortform drafts (social-platform copy) are often headingless;
|
|
58
|
+
* surfacing an empty TOC adds noise without value per the
|
|
59
|
+
* "structure over scrolling" principle.
|
|
60
|
+
* - Versions cell: omitted when only one revision exists. With one
|
|
61
|
+
* revision there is no history to navigate.
|
|
62
|
+
*/
|
|
63
|
+
export function getShortformBarCells(opts: ShortformBarCellOptions): readonly Cell[] {
|
|
64
|
+
const cells: Cell[] = [];
|
|
65
|
+
if (opts.tocEntries.length >= 2) {
|
|
66
|
+
cells.push({
|
|
67
|
+
glyph: '§',
|
|
68
|
+
label: `TOC · ${opts.tocEntries.length}`,
|
|
69
|
+
mode: 'review',
|
|
70
|
+
action: { kind: 'sheet', name: 'toc' },
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (opts.versions.length >= 2) {
|
|
74
|
+
cells.push({
|
|
75
|
+
glyph: '№',
|
|
76
|
+
label: `Versions · ${opts.versions.length}`,
|
|
77
|
+
mode: 'review',
|
|
78
|
+
action: { kind: 'sheet', name: 'versions' },
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
cells.push({
|
|
82
|
+
glyph: '⊕',
|
|
83
|
+
label: 'Actions',
|
|
84
|
+
mode: 'review',
|
|
85
|
+
action: { kind: 'sheet', name: 'actions' },
|
|
86
|
+
});
|
|
87
|
+
return cells;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ShortformMobileSheetOptions {
|
|
91
|
+
readonly tocEntries: readonly TocEntry[];
|
|
92
|
+
readonly versions: readonly DraftVersion[];
|
|
93
|
+
readonly workflow: DraftWorkflowItem;
|
|
94
|
+
readonly currentVersion: DraftVersion;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function renderTocSlotBody(tocEntries: readonly TocEntry[]): string {
|
|
98
|
+
if (tocEntries.length === 0) return '';
|
|
99
|
+
const items = tocEntries
|
|
100
|
+
.map((entry) => {
|
|
101
|
+
const depthClass = `er-mobile-toc-item er-mobile-toc-item--h${entry.depth}`;
|
|
102
|
+
return `<li class="${depthClass}"><a href="#${escapeHtml(entry.id)}">${escapeHtml(entry.text)}</a></li>`;
|
|
103
|
+
})
|
|
104
|
+
.join('');
|
|
105
|
+
return `<ul class="er-mobile-toc-list">${items}</ul>`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function renderVersionsSlotBody(
|
|
109
|
+
versions: readonly DraftVersion[],
|
|
110
|
+
currentVersion: DraftVersion,
|
|
111
|
+
): string {
|
|
112
|
+
if (versions.length === 0) return '';
|
|
113
|
+
const items = versions
|
|
114
|
+
.map((v) => {
|
|
115
|
+
const isActive = v.version === currentVersion.version;
|
|
116
|
+
const cls = isActive ? ' class="active"' : '';
|
|
117
|
+
return `<li class="er-mobile-versions-item"><a href="?v=${v.version}"${cls}>v${v.version}</a></li>`;
|
|
118
|
+
})
|
|
119
|
+
.join('');
|
|
120
|
+
return `<ul class="er-mobile-versions-list">${items}</ul>`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The Actions slot renders the three universal verbs unconditionally
|
|
125
|
+
* per Commandment II. Per Commandment VII (and THESIS Cons. 2), each
|
|
126
|
+
* button is a clipboard-copy trigger handled by the existing
|
|
127
|
+
* `editorial-review-client.ts` `[data-action]` listeners — the markup
|
|
128
|
+
* here carries no copy-target or state mutation logic; the client
|
|
129
|
+
* composes the slash command from the embedded workflow state.
|
|
130
|
+
*
|
|
131
|
+
* G.4: `data-action="cancel"`, NOT `reject` (the state machine has
|
|
132
|
+
* no `reject` verb; this matches issue #260's resolution shape).
|
|
133
|
+
*/
|
|
134
|
+
function renderActionsSlotBody(): string {
|
|
135
|
+
return [
|
|
136
|
+
'<div class="er-mobile-actions">',
|
|
137
|
+
' <button class="er-btn er-btn-primary er-btn-approve" data-action="approve" type="button">Approve</button>',
|
|
138
|
+
' <button class="er-btn" data-action="iterate" type="button">Iterate</button>',
|
|
139
|
+
' <button class="er-btn er-btn-cancel" data-action="cancel" type="button">Cancel</button>',
|
|
140
|
+
'</div>',
|
|
141
|
+
].join('\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Render the shortform mobile sheet host with the three named slots
|
|
146
|
+
* (toc / versions / actions). Each slot body is server-rendered so
|
|
147
|
+
* the client doesn't need to clone DOM from elsewhere on the page —
|
|
148
|
+
* the slot is self-contained.
|
|
149
|
+
*
|
|
150
|
+
* The sheet host is always rendered (matches the entry-review pattern
|
|
151
|
+
* where the host is present and the client toggles `hidden` on
|
|
152
|
+
* dispatch). Individual slots are hidden until the corresponding bar
|
|
153
|
+
* cell opens them via the shared `sheet-controller` primitive.
|
|
154
|
+
*/
|
|
155
|
+
export function renderShortformMobileSheet(
|
|
156
|
+
opts: ShortformMobileSheetOptions,
|
|
157
|
+
): RawHtml {
|
|
158
|
+
const tocBody = renderTocSlotBody(opts.tocEntries);
|
|
159
|
+
const versionsBody = renderVersionsSlotBody(opts.versions, opts.currentVersion);
|
|
160
|
+
const actionsBody = renderActionsSlotBody();
|
|
161
|
+
return unsafe(html`
|
|
162
|
+
<section
|
|
163
|
+
class="er-mobile-sheet"
|
|
164
|
+
id="er-mobile-sheet"
|
|
165
|
+
data-mobile-sheet-host
|
|
166
|
+
hidden
|
|
167
|
+
aria-label="Surface sheet"
|
|
168
|
+
role="dialog"
|
|
169
|
+
aria-modal="false"
|
|
170
|
+
>
|
|
171
|
+
<button class="er-mobile-sheet-handle" data-mobile-sheet-handle type="button" aria-label="Drag to dismiss the sheet">
|
|
172
|
+
<span class="er-mobile-sheet-handle-bar" aria-hidden="true"></span>
|
|
173
|
+
</button>
|
|
174
|
+
<header class="er-mobile-sheet-head">
|
|
175
|
+
<span class="er-mobile-sheet-kicker" data-mobile-sheet-kicker></span>
|
|
176
|
+
<span class="er-mobile-sheet-meta" data-mobile-sheet-meta></span>
|
|
177
|
+
<button class="er-mobile-sheet-close" data-mobile-sheet-close type="button" aria-label="Close sheet">×</button>
|
|
178
|
+
</header>
|
|
179
|
+
<div class="er-mobile-sheet-body" data-mobile-sheet-body>
|
|
180
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="toc" hidden>${unsafe(tocBody)}</div>
|
|
181
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="versions" hidden>${unsafe(versionsBody)}</div>
|
|
182
|
+
<div class="er-mobile-sheet-slot" data-mobile-sheet-slot="actions" hidden>${unsafe(actionsBody)}</div>
|
|
183
|
+
</div>
|
|
184
|
+
</section>`);
|
|
185
|
+
}
|
|
@@ -15,6 +15,24 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Workflow-keyed wording in this file is documenting that deliberate
|
|
17
17
|
* deferral; do not flag in audits.
|
|
18
|
+
*
|
|
19
|
+
* Step 2.2.10 (v7 universal chrome + state-machine compliance):
|
|
20
|
+
* - Server-side: er-strip / er-stamp / er-pending-state / shortcut
|
|
21
|
+
* overlay / state-branched control rendering all REMOVED. The
|
|
22
|
+
* universal `renderMobileBar` primitive + a shortform-specific
|
|
23
|
+
* sheet host (`./shortform-review-mobile-sheet.ts`) replace them.
|
|
24
|
+
* - Per DESIGN-STANDARDS.md § Universal bar contract: this surface
|
|
25
|
+
* composes its `Cell[]` mechanically (TOC / Versions / Actions)
|
|
26
|
+
* and passes it to `renderMobileBar`. No bespoke chrome shape.
|
|
27
|
+
* - Per DESKWORK-STATE-MACHINE.md Commandment III: no review-state
|
|
28
|
+
* labels on the page (the stamp + pending pills were the
|
|
29
|
+
* violations).
|
|
30
|
+
* - The desktop edit-mode panes (`renderEditPanes`) stay — they're
|
|
31
|
+
* gated by the existing `data-edit-mode` body attribute and the
|
|
32
|
+
* Edit toolbar is still part of the desktop chrome. Mobile edit
|
|
33
|
+
* entry-point is deferred to a future task (the workplan keeps
|
|
34
|
+
* the broader shortform state-machine migration explicitly out
|
|
35
|
+
* of scope for this step).
|
|
18
36
|
*/
|
|
19
37
|
import type { StudioContext } from '../routes/api.ts';
|
|
20
38
|
interface ShortformReviewQuery {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shortform-review.d.ts","sourceRoot":"","sources":["../../src/pages/shortform-review.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shortform-review.d.ts","sourceRoot":"","sources":["../../src/pages/shortform-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAYH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAYtD,UAAU,oBAAoB;IAC5B,wDAAwD;IACxD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA2FD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,GAAG,EAAE,aAAa,EAClB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA0GjB"}
|
|
@@ -15,13 +15,35 @@
|
|
|
15
15
|
*
|
|
16
16
|
* Workflow-keyed wording in this file is documenting that deliberate
|
|
17
17
|
* deferral; do not flag in audits.
|
|
18
|
+
*
|
|
19
|
+
* Step 2.2.10 (v7 universal chrome + state-machine compliance):
|
|
20
|
+
* - Server-side: er-strip / er-stamp / er-pending-state / shortcut
|
|
21
|
+
* overlay / state-branched control rendering all REMOVED. The
|
|
22
|
+
* universal `renderMobileBar` primitive + a shortform-specific
|
|
23
|
+
* sheet host (`./shortform-review-mobile-sheet.ts`) replace them.
|
|
24
|
+
* - Per DESIGN-STANDARDS.md § Universal bar contract: this surface
|
|
25
|
+
* composes its `Cell[]` mechanically (TOC / Versions / Actions)
|
|
26
|
+
* and passes it to `renderMobileBar`. No bespoke chrome shape.
|
|
27
|
+
* - Per DESKWORK-STATE-MACHINE.md Commandment III: no review-state
|
|
28
|
+
* labels on the page (the stamp + pending pills were the
|
|
29
|
+
* violations).
|
|
30
|
+
* - The desktop edit-mode panes (`renderEditPanes`) stay — they're
|
|
31
|
+
* gated by the existing `data-edit-mode` body attribute and the
|
|
32
|
+
* Edit toolbar is still part of the desktop chrome. Mobile edit
|
|
33
|
+
* entry-point is deferred to a future task (the workplan keeps
|
|
34
|
+
* the broader shortform state-machine migration explicitly out
|
|
35
|
+
* of scope for this step).
|
|
18
36
|
*/
|
|
19
37
|
import { handleGetWorkflow } from '@deskwork/core/review/handlers';
|
|
38
|
+
import { extractToc } from '@deskwork/core/review/toc';
|
|
20
39
|
import { parseDraftFrontmatter, renderMarkdownToHtml, } from '@deskwork/core/review/render';
|
|
21
|
-
import { html, unsafe } from "./html.js";
|
|
40
|
+
import { escapeHtml, html, unsafe } from "./html.js";
|
|
22
41
|
import { layout } from "./layout.js";
|
|
23
42
|
import { renderEditorialFolio } from "./chrome.js";
|
|
24
|
-
import {
|
|
43
|
+
import { renderMasthead } from "./masthead.js";
|
|
44
|
+
import { renderMastheadMenu } from "./masthead-menu.js";
|
|
45
|
+
import { renderMobileBar } from "./mobile-bar.js";
|
|
46
|
+
import { getShortformBarCells, renderShortformMobileSheet, } from "./shortform-review-mobile-sheet.js";
|
|
25
47
|
function isSuccessBody(body) {
|
|
26
48
|
if (typeof body !== 'object' || body === null)
|
|
27
49
|
return false;
|
|
@@ -38,9 +60,6 @@ function errorFromBody(body) {
|
|
|
38
60
|
function stringField(v) {
|
|
39
61
|
return typeof v === 'string' ? v : undefined;
|
|
40
62
|
}
|
|
41
|
-
function stateLabel(state) {
|
|
42
|
-
return (state ?? '').replace('-', ' ');
|
|
43
|
-
}
|
|
44
63
|
async function prepareShortformRender(markdown) {
|
|
45
64
|
const parsed = parseDraftFrontmatter(markdown);
|
|
46
65
|
const fm = parsed.frontmatter;
|
|
@@ -56,94 +75,12 @@ async function prepareShortformRender(markdown) {
|
|
|
56
75
|
: dekHtml + bodyHtml;
|
|
57
76
|
return { fm, bodyHtml: renderedHtml };
|
|
58
77
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const href = `?v=${v.version}`;
|
|
66
|
-
return html `<a href="${href}" class="${isActive ? 'active' : ''}">v${v.version}</a>`;
|
|
67
|
-
})
|
|
68
|
-
.join('');
|
|
69
|
-
return unsafe(html `<span class="er-strip-versions">${unsafe(links)}</span>`);
|
|
70
|
-
}
|
|
71
|
-
function pendingSkillCmd(workflow) {
|
|
72
|
-
const { site, slug, state } = workflow;
|
|
73
|
-
if (state === 'iterating') {
|
|
74
|
-
return `/deskwork:iterate --site ${site} ${slug}`;
|
|
75
|
-
}
|
|
76
|
-
if (state === 'approved') {
|
|
77
|
-
return `/deskwork:approve --site ${site} ${slug}`;
|
|
78
|
-
}
|
|
79
|
-
return '';
|
|
80
|
-
}
|
|
81
|
-
function shortcutChipWrap(buttonHtml, letter) {
|
|
82
|
-
return html `<span class="er-shortcut-chip-wrap">${unsafe(buttonHtml)}<small class="er-shortcut-chip"><kbd>${letter}</kbd><kbd>${letter}</kbd></small></span>`;
|
|
83
|
-
}
|
|
84
|
-
function renderControlsRight(workflow) {
|
|
85
|
-
const isActive = workflow.state === 'open' || workflow.state === 'in-review';
|
|
86
|
-
const isApproved = workflow.state === 'approved';
|
|
87
|
-
const isIterating = workflow.state === 'iterating';
|
|
88
|
-
const isTerminal = workflow.state === 'applied' || workflow.state === 'cancelled';
|
|
89
|
-
const buttons = [];
|
|
90
|
-
buttons.push(html `<button class="er-btn er-btn-small" data-action="toggle-edit" type="button">Edit</button><span class="er-edit-mode-label" data-mode="preview">preview</span>`);
|
|
91
|
-
if (isActive) {
|
|
92
|
-
buttons.push(shortcutChipWrap(html `<button class="er-btn er-btn-small er-btn-approve" data-action="approve" type="button">Approve</button>`, 'a'));
|
|
93
|
-
buttons.push(shortcutChipWrap(html `<button class="er-btn er-btn-small" data-action="iterate" type="button">Iterate</button>`, 'i'));
|
|
94
|
-
buttons.push(shortcutChipWrap(html `<button class="er-btn er-btn-small er-btn-reject" data-action="reject" type="button">Reject</button>`, 'r'));
|
|
95
|
-
}
|
|
96
|
-
if (isApproved) {
|
|
97
|
-
const applyCmd = pendingSkillCmd(workflow);
|
|
98
|
-
buttons.push(html `<span class="er-pending-state">awaiting apply…</span>`);
|
|
99
|
-
buttons.push(html `<button class="er-btn er-btn-small" data-action="copy-cmd" data-cmd="${applyCmd}" title="Copy ${applyCmd} to clipboard" type="button">copy <code>/deskwork:approve</code></button>`);
|
|
100
|
-
buttons.push(shortcutChipWrap(html `<button class="er-btn er-btn-small er-btn-reject" data-action="reject" type="button">Reject</button>`, 'r'));
|
|
101
|
-
}
|
|
102
|
-
if (isIterating) {
|
|
103
|
-
const iterateCmd = pendingSkillCmd(workflow);
|
|
104
|
-
buttons.push(html `<span class="er-pending-state">agent iterating…</span>`);
|
|
105
|
-
buttons.push(html `<button class="er-btn er-btn-small" data-action="copy-cmd" data-cmd="${iterateCmd}" title="Copy ${iterateCmd} to clipboard" type="button">copy <code>/deskwork:iterate</code></button>`);
|
|
106
|
-
}
|
|
107
|
-
if (isTerminal) {
|
|
108
|
-
buttons.push(html `<span class="er-pending-state er-pending-state--filed">filed (${workflow.state})</span>`);
|
|
109
|
-
}
|
|
110
|
-
buttons.push(html `<button class="er-btn er-btn-small" data-action="shortcuts" type="button" aria-label="Show keyboard shortcuts" title="Keyboard shortcuts">?</button>`);
|
|
111
|
-
return unsafe(`<span class="er-strip-right">${buttons.join('')}</span>`);
|
|
112
|
-
}
|
|
113
|
-
function renderShortcutsOverlay() {
|
|
114
|
-
return unsafe(html `
|
|
115
|
-
<div class="er-shortcuts" data-shortcuts-overlay hidden role="dialog" aria-modal="true" aria-label="Keyboard shortcuts">
|
|
116
|
-
<div class="er-shortcuts-backdrop" data-shortcuts-backdrop></div>
|
|
117
|
-
<div class="er-shortcuts-panel">
|
|
118
|
-
<h2>Keyboard</h2>
|
|
119
|
-
<dl>
|
|
120
|
-
<dt><kbd>e</kbd> / dbl-click</dt><dd>toggle edit mode</dd>
|
|
121
|
-
<dt><kbd>a</kbd> <kbd>a</kbd></dt><dd>approve <em>— press twice within 500ms</em></dd>
|
|
122
|
-
<dt><kbd>i</kbd> <kbd>i</kbd></dt><dd>iterate <em>— press twice within 500ms</em></dd>
|
|
123
|
-
<dt><kbd>r</kbd> <kbd>r</kbd></dt><dd>reject <em>— press twice within 500ms</em></dd>
|
|
124
|
-
<dt><kbd>?</kbd></dt><dd>this panel</dd>
|
|
125
|
-
<dt><kbd>esc</kbd></dt><dd>close</dd>
|
|
126
|
-
</dl>
|
|
127
|
-
<p class="er-shortcuts-footer">Press <kbd>?</kbd> anytime.</p>
|
|
128
|
-
</div>
|
|
129
|
-
</div>`);
|
|
130
|
-
}
|
|
131
|
-
function renderEditToolbar() {
|
|
132
|
-
return unsafe(html `
|
|
133
|
-
<div class="er-edit-toolbar" data-edit-toolbar hidden>
|
|
134
|
-
<div class="er-edit-modes" role="tablist" aria-label="Editor mode">
|
|
135
|
-
<button class="er-edit-mode-btn" data-edit-view="source" type="button" aria-pressed="true">Source</button>
|
|
136
|
-
<button class="er-edit-mode-btn" data-edit-view="split" type="button" aria-pressed="false">Split</button>
|
|
137
|
-
<button class="er-edit-mode-btn" data-edit-view="preview" type="button" aria-pressed="false">Preview</button>
|
|
138
|
-
</div>
|
|
139
|
-
<div class="er-edit-actions">
|
|
140
|
-
<button class="er-btn er-btn-small" data-action="focus-mode" type="button" title="Distraction-free mode (Shift+F)" aria-pressed="false">Focus ⛶</button>
|
|
141
|
-
<button class="er-btn er-btn-primary" data-action="save-version" type="button">Save as new version</button>
|
|
142
|
-
<button class="er-btn" data-action="cancel-edit" type="button">Cancel</button>
|
|
143
|
-
<span class="er-edit-hint" data-edit-hint></span>
|
|
144
|
-
</div>
|
|
145
|
-
</div>`);
|
|
146
|
-
}
|
|
78
|
+
/**
|
|
79
|
+
* Desktop-only edit panes. The `data-edit-mode` body attribute is the
|
|
80
|
+
* gate (set by the existing client toggle-edit handler). On mobile,
|
|
81
|
+
* edit mode is not currently surfaced from this surface — the broader
|
|
82
|
+
* shortform state-machine migration is the right place to design that.
|
|
83
|
+
*/
|
|
147
84
|
function renderEditPanes() {
|
|
148
85
|
return unsafe(html `
|
|
149
86
|
<div class="er-edit-mode" data-edit-panes-host hidden>
|
|
@@ -211,6 +148,9 @@ export async function renderShortformReviewPage(ctx, workflowId, query) {
|
|
|
211
148
|
const { fm, bodyHtml } = await prepareShortformRender(currentVersion.markdown);
|
|
212
149
|
const draftState = { workflow, currentVersion, versions };
|
|
213
150
|
const titleField = stringField(fm.title) ?? `Draft: ${slug}`;
|
|
151
|
+
// #244 — extract TOC from the rendered body. `rehype-slug` already
|
|
152
|
+
// gave every h2/h3/h4 an `id`; `extractToc` reads the slugs + text.
|
|
153
|
+
const tocEntries = extractToc(bodyHtml);
|
|
214
154
|
const shortformMeta = unsafe(html `
|
|
215
155
|
<div class="er-shortform-meta">
|
|
216
156
|
<span class="er-platform">${workflow.platform ?? 'other'}</span>
|
|
@@ -219,6 +159,30 @@ export async function renderShortformReviewPage(ctx, workflowId, query) {
|
|
|
219
159
|
: ''}
|
|
220
160
|
</div>`);
|
|
221
161
|
const folioSpine = `shortform · ${workflow.platform ?? '?'}${workflow.channel ? ` · ${workflow.channel}` : ''} · ${slug}`;
|
|
162
|
+
// v7 universal masthead (mobile-only at this commit). Kicker carries
|
|
163
|
+
// the platform badge + channel as inline markup; the meta tag holds
|
|
164
|
+
// the galley number. Slug occupies the bottom row.
|
|
165
|
+
const platformLabel = workflow.platform ?? 'other';
|
|
166
|
+
const channelLabel = workflow.channel ? ` ${workflow.channel}` : '';
|
|
167
|
+
const mastheadKicker = unsafe(html `<span class="platform">${platformLabel}</span>${channelLabel}`);
|
|
168
|
+
const masthead = renderMasthead({
|
|
169
|
+
kickerHtml: mastheadKicker,
|
|
170
|
+
slug,
|
|
171
|
+
metaInline: `№ ${currentVersion.version}`,
|
|
172
|
+
isHub: false,
|
|
173
|
+
});
|
|
174
|
+
// v7 universal mobile bar. The cell list is composed mechanically
|
|
175
|
+
// from the surface's TOC + Versions + (always) Actions per
|
|
176
|
+
// DESIGN-STANDARDS.md § Universal bar contract. The Actions cell
|
|
177
|
+
// guarantees the bar is never empty.
|
|
178
|
+
const barCells = getShortformBarCells({ tocEntries, versions });
|
|
179
|
+
const mobileBar = renderMobileBar({ contextual: barCells });
|
|
180
|
+
const mobileSheet = renderShortformMobileSheet({
|
|
181
|
+
tocEntries,
|
|
182
|
+
versions,
|
|
183
|
+
workflow,
|
|
184
|
+
currentVersion,
|
|
185
|
+
});
|
|
222
186
|
const pageGrid = html `
|
|
223
187
|
<div class="er-page-grid">
|
|
224
188
|
<div class="er-draft-frame">
|
|
@@ -229,30 +193,16 @@ export async function renderShortformReviewPage(ctx, workflowId, query) {
|
|
|
229
193
|
</div>`;
|
|
230
194
|
const body = html `
|
|
231
195
|
<div data-review-ui="shortform" class="er-review-shell">
|
|
196
|
+
${masthead}
|
|
197
|
+
${renderMastheadMenu()}
|
|
232
198
|
${renderEditorialFolio('shortform', folioSpine)}
|
|
233
199
|
${shortformMeta}
|
|
234
|
-
<div class="er-strip">
|
|
235
|
-
<div class="er-strip-inner">
|
|
236
|
-
<a class="er-strip-back" href="/dev/editorial-studio" title="Back to the editorial studio">← studio</a>
|
|
237
|
-
<span class="er-strip-galley">${gloss('galley')} <em>№ ${currentVersion.version}</em></span>
|
|
238
|
-
<span class="er-strip-slug">${workflow.site} / ${workflow.slug}</span>
|
|
239
|
-
${renderVersionsStrip(versions, currentVersion)}
|
|
240
|
-
<span class="er-strip-center">
|
|
241
|
-
<span class="er-stamp er-stamp-big er-stamp-${workflow.state}" data-state-label>
|
|
242
|
-
${stateLabel(workflow.state)}
|
|
243
|
-
</span>
|
|
244
|
-
<span class="er-strip-hint">double-click to edit · <kbd>?</kbd> for shortcuts</span>
|
|
245
|
-
</span>
|
|
246
|
-
${renderControlsRight(workflow)}
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
${renderEditToolbar()}
|
|
250
200
|
<article class="er-page">
|
|
251
201
|
${unsafe(pageGrid)}
|
|
252
202
|
</article>
|
|
203
|
+
${mobileBar}
|
|
204
|
+
${mobileSheet}
|
|
253
205
|
<div class="er-toast" data-toast hidden></div>
|
|
254
|
-
${renderShortcutsOverlay()}
|
|
255
|
-
<div class="er-poll-indicator" data-poll>auto-refresh · 8s</div>
|
|
256
206
|
</div>`;
|
|
257
207
|
return layout({
|
|
258
208
|
title: `${titleField} — Review`,
|
|
@@ -261,6 +211,7 @@ export async function renderShortformReviewPage(ctx, workflowId, query) {
|
|
|
261
211
|
'/static/css/editorial-nav.css',
|
|
262
212
|
'/static/css/blog-figure.css',
|
|
263
213
|
'/static/css/review-viewport.css',
|
|
214
|
+
'/static/css/mobile-shell.css',
|
|
264
215
|
],
|
|
265
216
|
bodyHtml: body,
|
|
266
217
|
embeddedJson: [{ id: 'draft-state', data: draftState }],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shortform-review.js","sourceRoot":"","sources":["../../src/pages/shortform-review.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"shortform-review.js","sourceRoot":"","sources":["../../src/pages/shortform-review.ts"],"names":[],"mappings":"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"}
|