@justai/cuts 0.26.0 → 0.27.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 +4 -3
- package/src/Base.astro +4 -0
- package/src/ConfirmSheet.astro +10 -2
- package/src/ground.css +76 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justai/cuts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "A persona's named parts \u2014 the page shell that holds them, and the cuts themselves.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"./Posts.astro": "./src/Posts.astro",
|
|
20
20
|
"./Toolbar.astro": "./src/Toolbar.astro",
|
|
21
21
|
"./Profile.astro": "./src/Profile.astro",
|
|
22
|
-
"./ConfirmSheet.astro": "./src/ConfirmSheet.astro"
|
|
22
|
+
"./ConfirmSheet.astro": "./src/ConfirmSheet.astro",
|
|
23
|
+
"./ground.css": "./src/ground.css"
|
|
23
24
|
},
|
|
24
25
|
"peerDependencies": {
|
|
25
26
|
"@justai/ui": ">=0.2.0",
|
|
@@ -29,6 +30,6 @@
|
|
|
29
30
|
"access": "public"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
|
-
"@justai/core": "^0.4.
|
|
33
|
+
"@justai/core": "^0.4.1"
|
|
33
34
|
}
|
|
34
35
|
}
|
package/src/Base.astro
CHANGED
|
@@ -27,6 +27,10 @@
|
|
|
27
27
|
* The dictionaries. Same reason, stronger: the machinery is shared, the CONTENT is the persona's.
|
|
28
28
|
*/
|
|
29
29
|
import { dir as dirOf } from "@justai/ui/locale";
|
|
30
|
+
// THE GROUND — the first law of the framework: a component brings its own ground. Zero-specificity
|
|
31
|
+
// defaults (:where) for every token the cuts consume; any persona declaration overrides outright.
|
|
32
|
+
// See ground.css for the law, the day it was learned, and how it coexists with ui's styling contract.
|
|
33
|
+
import "./ground.css";
|
|
30
34
|
// The load-bearing behaviour is framework-free and lives in @justai/core, so `feed` (Next) injects the
|
|
31
35
|
// SAME strings instead of hand-copying them. This binding just decides where they go in an Astro head.
|
|
32
36
|
import { AUTH_CAPTURE_JS, CONSENT_JS, JS_CLASS_JS, REVEAL_CSS, analyticsJs, consentCopy } from "@justai/core";
|
package/src/ConfirmSheet.astro
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
+
// THE GROUND rides with the sheet: this cut is consumed standalone (me, feed) where Base never
|
|
3
|
+
// runs, and it must look right on a page that defines nothing. Zero-specificity — see ground.css.
|
|
4
|
+
import "./ground.css";
|
|
2
5
|
// ░░ CONFIRM SHEET — the fleet's ONE confirmation dialog: an iOS-style action sheet. ░░
|
|
3
6
|
//
|
|
4
7
|
// Born in the /me vault ("Forget everything?") and promoted to the framework because a confirmation
|
|
@@ -71,10 +74,15 @@ const { id, title, body, actionLabel, cancelLabel, destructive = false, ask = fa
|
|
|
71
74
|
{title && <strong id={`${id}-t`}>{title}</strong>}
|
|
72
75
|
<span id={`${id}-b`}>{body}</span>
|
|
73
76
|
</div>
|
|
74
|
-
|
|
77
|
+
{/* NO autofocus ATTRIBUTE, deliberately: with a fragment in the URL (/me#profile) Chrome
|
|
78
|
+
refuses to process the attribute at parse and prints a console warning on every load —
|
|
79
|
+
on a closed dialog, noise about a focus that was never going to happen. Focus is the
|
|
80
|
+
OPENER's job now, at showModal time: ask → the invitation (CONSENT_JS does it),
|
|
81
|
+
destructive → the cancel (the consumer does it). The genre decides, as before. */}
|
|
82
|
+
<button class:list={["confirm-act", { destructive, preferred: ask }]} id={`${id}-act`} value="confirm">{actionLabel}</button>
|
|
75
83
|
{ask && <button class="confirm-act quiet" id={`${id}-cancel`} value={cancelValue} formnovalidate>{cancelLabel}</button>}
|
|
76
84
|
</div>
|
|
77
|
-
{!ask && <button class="confirm-act confirm-cancel" id={`${id}-cancel`} value={cancelValue} formnovalidate
|
|
85
|
+
{!ask && <button class="confirm-act confirm-cancel" id={`${id}-cancel`} value={cancelValue} formnovalidate>{cancelLabel}</button>}
|
|
78
86
|
</form>
|
|
79
87
|
</dialog>
|
|
80
88
|
|
package/src/ground.css
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* @justai/cuts — the GROUND.
|
|
2
|
+
*
|
|
3
|
+
* THE FIRST LAW OF THE FRAMEWORK (founder, 2026-07-25): a component brings its own ground. A
|
|
4
|
+
* component that renders broken unless its consumer defines --bg, --border, --text and --font is
|
|
5
|
+
* not a component — it is a template with homework, and the homework is invisible until a new
|
|
6
|
+
* surface forgets it. The ConfirmSheet proved it the same day: mounted on feed, it rendered as
|
|
7
|
+
* bare transparent text, because color-mix() over an undefined var() invalidates the whole
|
|
8
|
+
* declaration. Nothing errored. There was nothing to see except the founder's screenshot.
|
|
9
|
+
*
|
|
10
|
+
* HOW THIS COEXISTS WITH THE STYLING CONTRACT. @justai/ui's tokens.css deliberately names the
|
|
11
|
+
* colour tokens and values NONE of them — "so a persona cannot forget to supply them". That
|
|
12
|
+
* contract stands. What changes is the failure mode: every selector here is wrapped in :where(),
|
|
13
|
+
* whose specificity is ZERO, so ANY consumer declaration (`:root { --bg: … }`, in any file, loaded
|
|
14
|
+
* in any order) wins outright. A persona that supplies its contract looks exactly as it chose; a
|
|
15
|
+
* surface that supplies nothing gets the fleet-neutral look below instead of invisible text.
|
|
16
|
+
* Forgetting now degrades to "default look", never to "broken render" — enforcement of the
|
|
17
|
+
* contract belongs to gates, not to a visitor's screen.
|
|
18
|
+
*
|
|
19
|
+
* The values are READ, not designed: the skeleton half mirrors @justai/ui tokens.css (the
|
|
20
|
+
* invariants measured across eleven personas), the colour half is the fleet's most common ground
|
|
21
|
+
* (the same values feed's public-persona.css carries). Change ui's tokens and this file must
|
|
22
|
+
* follow — the harness pins the skeleton halves equal.
|
|
23
|
+
*
|
|
24
|
+
* Imported by Base.astro AND ConfirmSheet.astro (the one cut consumed standalone), so the ground
|
|
25
|
+
* travels with whichever of the two reaches a page first; the bundler dedupes when both do.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
:where(:root) {
|
|
29
|
+
/* skeleton — mirrors @justai/ui tokens.css, pinned equal by the harness */
|
|
30
|
+
--fs-2xs: 0.76rem;
|
|
31
|
+
--fs-xs: 0.84rem;
|
|
32
|
+
--fs-sm: 0.92rem;
|
|
33
|
+
--fs-base: 1rem;
|
|
34
|
+
--fs-md: 1.13rem;
|
|
35
|
+
--fs-lg: 1.32rem;
|
|
36
|
+
--fs-xl: 1.6rem;
|
|
37
|
+
|
|
38
|
+
--radius-sm: 10px;
|
|
39
|
+
--radius-md: 14px;
|
|
40
|
+
--radius-lg: 20px;
|
|
41
|
+
--radius-pill: 999px;
|
|
42
|
+
|
|
43
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
44
|
+
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
45
|
+
|
|
46
|
+
/* ground — the fleet-neutral defaults for the colour contract (dark first: the fleet's default scheme) */
|
|
47
|
+
--font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter", system-ui, sans-serif;
|
|
48
|
+
--bg: #0a0c10;
|
|
49
|
+
--text: #f2f4f8;
|
|
50
|
+
--text-dim: #9aa3b2;
|
|
51
|
+
--border: rgba(255, 255, 255, 0.1);
|
|
52
|
+
--surface: rgba(255, 255, 255, 0.04);
|
|
53
|
+
--surface-2: rgba(255, 255, 255, 0.07);
|
|
54
|
+
--accent: #0a84ff;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@media (prefers-color-scheme: light) {
|
|
58
|
+
:where(:root) {
|
|
59
|
+
--bg: #f6f7f9;
|
|
60
|
+
--text: #0a0c10;
|
|
61
|
+
--text-dim: #5b6472;
|
|
62
|
+
--border: rgba(0, 0, 0, 0.08);
|
|
63
|
+
--surface: rgba(255, 255, 255, 0.7);
|
|
64
|
+
--surface-2: rgba(0, 0, 0, 0.05);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* The body's own ground — margin reset, the fleet's type baseline, the page colours. Zero
|
|
69
|
+
* specificity again: any consumer body rule overrides. Without this, a blank page renders the
|
|
70
|
+
* sheet over a white serif document — the Times lesson, carved as CSS. */
|
|
71
|
+
:where(body) {
|
|
72
|
+
margin: 0;
|
|
73
|
+
background: var(--bg);
|
|
74
|
+
color: var(--text);
|
|
75
|
+
font: 1rem/1.5 var(--font);
|
|
76
|
+
}
|