@ammduncan/easel 0.2.22 → 0.2.24
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 +14 -0
- package/dist/client/viewer.js +67 -25
- package/dist/http-server.js +10 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to easel. This project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 0.2.24 — 2026-05-23
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **`.window` primitive — skeuomorphic macOS window chrome for mockups.** `<div class="window" data-title="App name">…</div>` draws a 40px title bar with the three traffic-light dots (red/yellow/green) and a centred title from `data-title`; content sits below. Add the `desktop` class (`class="window desktop"`) for the 1440×900 (16:10) standard design canvas via `min-height: 900px` — so a full desktop-screen mockup looks like a real window with viewport breathing room, while a dialog/component in the same chrome (no `desktop`) stays content-sized. Pairs with `.full-bleed` to fill the content column.
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **Reading column is now left-aligned with a shared left edge, instead of per-element centred.** 0.2.22 centred each prose element independently, which produced a ragged left edge when elements had different `max-width`s (e.g. a deck capped narrower than the heading). Reverted to left-aligned prose; `.full-bleed` now fills the content column from the *same* left edge (dropped the viewport-breakout/centring) — so prose and mockups share one left margin down the card, and neither touches the card edge (the body padding stays as a gutter).
|
|
12
|
+
- **Client JS/CSS now sent with `Cache-Control: no-cache`** so a normal reload revalidates and picks up updates, instead of serving a stale cached `viewer.js` that required a hard reload (⌘⇧R). Takes effect after the MCP server restarts.
|
|
13
|
+
|
|
14
|
+
## 0.2.23 — 2026-05-23
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **`.full-bleed` now caps at 1440px and centres.** On a wide monitor the card itself can be ~2000px, and a full-bleed mockup was stretching to fill all of it — but a real desktop screen tops out around 1440px, so the mockup looked unnaturally wide. `.full-bleed` is now `width: min(100vw, 1440px)` (still centred via `left:50%` + `translateX(-50%)`): it fills the card up to 1440 then centres with gutters. On cards narrower than 1440 it still fills edge-to-edge. Browser-verified at a 1949px viewport (1542px card → mockup capped at 1440, centred).
|
|
18
|
+
|
|
5
19
|
## 0.2.22 — 2026-05-23
|
|
6
20
|
|
|
7
21
|
### Changed
|
package/dist/client/viewer.js
CHANGED
|
@@ -692,42 +692,84 @@ body {
|
|
|
692
692
|
@media (min-width: 2000px) {
|
|
693
693
|
body { max-width: 1600px; }
|
|
694
694
|
}
|
|
695
|
-
/* Constrain prose to a comfortable reading length
|
|
696
|
-
(cards, grids,
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
.
|
|
695
|
+
/* Constrain prose to a comfortable reading length and LEFT-ALIGN it to the
|
|
696
|
+
content column's left edge. Visual blocks (cards, grids, mockups, .full-bleed)
|
|
697
|
+
fill the wider content column from the SAME left edge — so prose and mockups
|
|
698
|
+
share one left margin down the card. Match prose both as direct body children
|
|
699
|
+
AND one level deep through a .wrap container (the skill recommends wrapping
|
|
700
|
+
content in div.wrap; without the .wrap branch the cap silently misses). */
|
|
701
701
|
body > p, body > .deck, body > .lede, body > ul, body > ol, body > blockquote,
|
|
702
702
|
body > h1, body > h2, body > h3, body > h4,
|
|
703
703
|
body > .wrap > p, body > .wrap > .deck, body > .wrap > .lede,
|
|
704
704
|
body > .wrap > ul, body > .wrap > ol, body > .wrap > blockquote,
|
|
705
705
|
body > .wrap > h1, body > .wrap > h2, body > .wrap > h3, body > .wrap > h4 {
|
|
706
706
|
max-width: 880px;
|
|
707
|
-
/* Centre the reading column in the card so it stays balanced whether or not
|
|
708
|
-
a .full-bleed sibling has widened the body. Without auto margins the
|
|
709
|
-
capped prose sits flush-left with a large empty right gutter next to any
|
|
710
|
-
full-bleed block. !important is required because authors routinely set an
|
|
711
|
-
inline margin shorthand like 0 0 16px on prose — that sets the left/right
|
|
712
|
-
margins to 0 and would otherwise win over the stylesheet, leaving that one
|
|
713
|
-
element flush-left while its siblings centre (inconsistent column edge).
|
|
714
|
-
We only force the horizontal margins; inline top/bottom spacing is kept. */
|
|
715
|
-
margin-left: auto !important;
|
|
716
|
-
margin-right: auto !important;
|
|
717
707
|
}
|
|
718
708
|
body > *:first-child { margin-top: 0 !important; }
|
|
719
709
|
body > *:last-child { margin-bottom: 0 !important; }
|
|
720
|
-
/*
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
710
|
+
/* Wide-content escape for embedded mockups mid-presentation. Wrap a section in
|
|
711
|
+
<div class="full-bleed"> and it fills the content column's full width —
|
|
712
|
+
wider than the 880px prose cap — while sharing the prose's LEFT edge. It does
|
|
713
|
+
NOT break out to the card's physical edge: the body's horizontal padding
|
|
714
|
+
stays as a gutter, so neither the mockup nor the surrounding text ever touches
|
|
715
|
+
the card border. (The name is historical — it's "full content width", not
|
|
716
|
+
"bleed to the card edge".) Capped at 100% of the content column, which the
|
|
717
|
+
body's max-width already limits to desktop-realistic proportions. */
|
|
725
718
|
.full-bleed {
|
|
726
|
-
width:
|
|
719
|
+
width: 100%;
|
|
720
|
+
max-width: 100% !important;
|
|
721
|
+
margin-left: 0;
|
|
722
|
+
margin-right: 0;
|
|
723
|
+
}
|
|
724
|
+
/* Skeuomorphic macOS-style window chrome for UI mockups. Usage:
|
|
725
|
+
<div class="window" data-title="App name"> …mockup content… </div>
|
|
726
|
+
Draws a 40px title bar with the three traffic-light dots (red/yellow/green)
|
|
727
|
+
and an optional centred title from data-title. Content sits below the bar.
|
|
728
|
+
Add the desktop class for a full desktop-screen canvas — min-height 900px,
|
|
729
|
+
i.e. the 1440x900 (16:10) standard design canvas — so a screen mockup looks
|
|
730
|
+
like a real window with viewport breathing room rather than a short strip.
|
|
731
|
+
Omit desktop for dialogs / small components so they stay content-sized. */
|
|
732
|
+
.window {
|
|
727
733
|
position: relative;
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
734
|
+
padding-top: 40px;
|
|
735
|
+
border-radius: 12px;
|
|
736
|
+
border: 1px solid light-dark(#e2e2e2, #2a2a2a);
|
|
737
|
+
box-shadow: 0 14px 48px rgba(0, 0, 0, 0.16);
|
|
738
|
+
overflow: hidden;
|
|
739
|
+
background: light-dark(#ffffff, #161616);
|
|
740
|
+
}
|
|
741
|
+
.window::before {
|
|
742
|
+
content: "";
|
|
743
|
+
position: absolute;
|
|
744
|
+
top: 0;
|
|
745
|
+
left: 0;
|
|
746
|
+
right: 0;
|
|
747
|
+
height: 40px;
|
|
748
|
+
background-color: light-dark(#f1f1f1, #1f1f1f);
|
|
749
|
+
border-bottom: 1px solid light-dark(#e2e2e2, #2a2a2a);
|
|
750
|
+
background-image:
|
|
751
|
+
radial-gradient(circle at 19px 20px, #ff5f57 6px, transparent 6.5px),
|
|
752
|
+
radial-gradient(circle at 39px 20px, #febc2e 6px, transparent 6.5px),
|
|
753
|
+
radial-gradient(circle at 59px 20px, #28c840 6px, transparent 6.5px);
|
|
754
|
+
background-repeat: no-repeat;
|
|
755
|
+
}
|
|
756
|
+
.window::after {
|
|
757
|
+
content: attr(data-title);
|
|
758
|
+
position: absolute;
|
|
759
|
+
top: 0;
|
|
760
|
+
left: 0;
|
|
761
|
+
right: 0;
|
|
762
|
+
height: 40px;
|
|
763
|
+
display: flex;
|
|
764
|
+
align-items: center;
|
|
765
|
+
justify-content: center;
|
|
766
|
+
font-size: 13px;
|
|
767
|
+
font-weight: 500;
|
|
768
|
+
color: light-dark(#6b6b6b, #9b9b9b);
|
|
769
|
+
pointer-events: none;
|
|
770
|
+
}
|
|
771
|
+
.window.desktop {
|
|
772
|
+
min-height: 900px;
|
|
731
773
|
}
|
|
732
774
|
.wrap { display: block; }
|
|
733
775
|
.kicker {
|
package/dist/http-server.js
CHANGED
|
@@ -51,6 +51,16 @@ export function startHttpServer() {
|
|
|
51
51
|
app.use("/static", express.static(CLIENT_DIR, {
|
|
52
52
|
fallthrough: false,
|
|
53
53
|
maxAge: "0",
|
|
54
|
+
etag: true,
|
|
55
|
+
lastModified: true,
|
|
56
|
+
// Force the browser to revalidate the client JS/CSS on every load (via
|
|
57
|
+
// ETag) instead of serving a stale cached copy. Without this a plain
|
|
58
|
+
// reload after an easel update keeps the old viewer.js — the user has to
|
|
59
|
+
// hard-reload (⌘⇧R) to pick up new styles, which has bitten us. `no-cache`
|
|
60
|
+
// means "cached copy is fine ONLY after revalidating it's unchanged".
|
|
61
|
+
setHeaders: (res) => {
|
|
62
|
+
res.setHeader("Cache-Control", "no-cache");
|
|
63
|
+
},
|
|
54
64
|
}));
|
|
55
65
|
app.get("/health", (_req, res) => {
|
|
56
66
|
res.json({ ok: true, pid: process.pid, port });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ammduncan/easel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.24",
|
|
4
4
|
"description": "A live browser tab for every Claude Code (and MCP) session. The push MCP tool appends HTML cards to a scrolling feed you keep open in split-screen.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|