@justai/cuts 0.80.0 → 0.82.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justai/cuts",
3
- "version": "0.80.0",
3
+ "version": "0.82.0",
4
4
  "description": "A persona's named parts — the page shell that holds them, and the cuts themselves.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -37,7 +37,7 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@justai/core": "^0.11.0",
40
+ "@justai/core": "^0.12.0",
41
41
  "@justai/ui": "^0",
42
42
  "@justai/atrium": "^0.1.9"
43
43
  }
@@ -103,6 +103,13 @@ interface Props {
103
103
  bio?: string;
104
104
  /** The small print under the bio — what it costs, what it keeps. */
105
105
  meta?: string;
106
+ /** The child's own colours for its avatar well. Genuinely per-child taste: /me is a dark vault,
107
+ * /files is a light sheet of paper. */
108
+ avatarBg?: string;
109
+ avatarBgLight?: string;
110
+ avatarPad?: string;
111
+ /** The cover behind the profile. Defaults to the host persona's accent, which is the point. */
112
+ cover?: string;
106
113
  /** The host persona's face, if the page already resolved it server-side. Otherwise `childFace()`
107
114
  * fills it in at runtime from /api/face — see @justai/core. */
108
115
  host?: { name?: string; avatar?: string; accent?: string };
@@ -121,51 +128,76 @@ const {
121
128
  child, name, bio, meta, host,
122
129
  parentHref = "/#kernel", parentLabel = "Home",
123
130
  sectionsLabel = "Sections", profileLabel, kernelLabel, face = "page",
131
+ avatarBg = "linear-gradient(160deg, #1f2740, #11141f)",
132
+ avatarBgLight = "linear-gradient(160deg, #f4f6fb, #fff)",
133
+ avatarPad = "15px",
134
+ cover = "linear-gradient(135deg, color-mix(in srgb, var(--accent) 88%, #fff), var(--accent) 55%, color-mix(in srgb, var(--accent) 70%, #000))",
124
135
  } = Astro.props;
125
136
  // `page` is the default because it is the face a child shows when nobody asked for one — somebody
126
137
  // typed the address. A guest is always ASKED for, which is why the caller names it.
127
138
  const chrome = face === "page";
128
139
  ---
129
140
 
130
- {/* `.pp` IS the child persona. One wrapper, two situations — and `data-presented` is how the kernel
131
- inside asks which one it is in without re-deriving it from the URL. */}
132
- <div class="pp" id="pp" data-child={child} data-face={face}>
133
- {/* A PRESENTED CHILD SHOWS NO PROFILE AND NO ROW. It is content inside somebody's sheet, and a
134
- biography there is the guest introducing itself while the host is mid-sentence. Standalone it
135
- is a full persona page, because then it IS the page. */}
136
- {chrome && (
137
- <>
138
- <Profile
139
- name={name}
140
- handle={`@${child}`}
141
- bio={bio}
142
- meta={meta}
143
- kernelLabel={name}
144
- avatarBg="#fff"
145
- avatarPad="14px"
146
- cover="linear-gradient(135deg, color-mix(in srgb, var(--accent) 88%, #fff), var(--accent) 55%, color-mix(in srgb, var(--accent) 70%, #000))"
147
- >
148
- <Fragment slot="avatar"><slot name="mark" /></Fragment>
149
- </Profile>
141
+ {/* `.pp` IS the child persona — one wrapper, every face. `data-face` is how the kernel inside asks
142
+ which one it is in without re-deriving it from the URL.
150
143
 
151
- <div class="below" id="below">
152
- <Toolbar
153
- sectionsLabel={sectionsLabel}
154
- profileLabel={profileLabel ?? name}
155
- kernelLabel={kernelLabel ?? name}
156
- postsLabel="Posts"
157
- parent={{ href: parentHref, label: parentLabel, icon: host?.avatar }}
158
- files={false}
144
+ IT RENDERS THE COLUMN ITSELF. An earlier draft styled `.pp .app` and left the consumer to emit
145
+ the element, which is precisely the homework law 1 forbids: a shell whose geometry only works if
146
+ somebody remembers a class name is a template, not a component. */}
147
+ <div class="pp" id="pp" data-child={child} data-face={face}>
148
+ <main class="app">
149
+ {/* THE `sheet` FACE SHOWS NO PROFILE AND NO ROW. It is content inside somebody's chrome, and a
150
+ biography there is the guest introducing itself while the host is mid-sentence. As a `page`
151
+ it IS the page, so it wears the whole persona shape. */}
152
+ {chrome ? (
153
+ <>
154
+ {/* queries: pnName pnHandle pnMeta · the child persona shows the wrong name · host identity
155
+ in a child's profile · why are there spans in these strings
156
+ THE IDS ARE THE CONTRACT, and they are here rather than in each child because both
157
+ children were already doing this identically.
158
+ A child persona ADOPTS ITS HOST'S IDENTITY at runtime: the page is built once and mounted
159
+ on every persona's host, so the name, the handle and the small print cannot be known at
160
+ build time. They are rendered as spans with stable ids and rewritten by `childFace()` in
161
+ @justai/core once /api/face answers. What the server renders is the honest fallback — the
162
+ child's own words, correct if the lookup never returns. */}
163
+ <Profile
164
+ name={`<span id="pnName">${name}</span><span class="pro" id="pnFacet"></span>`}
165
+ handle={`<span id="pnHandle">@${child}</span>`}
166
+ bio={bio ? `<span id="pnBio">${bio}</span>` : undefined}
167
+ meta={`<span id="pnMeta">${meta ?? ""}</span>`}
168
+ kernelLabel={name}
169
+ avatarBg={avatarBg}
170
+ avatarBgLight={avatarBgLight}
171
+ avatarPad={avatarPad}
172
+ cover={cover}
159
173
  >
160
- <Fragment slot="profileIcon"><slot name="mark" /></Fragment>
161
- <slot name="langPicker" slot="langPicker" />
162
- </Toolbar>
163
- <section class="cut kernel" id="kernel"><slot /></section>
164
- </div>
165
- </>
166
- )}
174
+ <Fragment slot="avatar"><slot name="mark" /></Fragment>
175
+ </Profile>
176
+
177
+ <div class="below" id="below">
178
+ <Toolbar
179
+ sectionsLabel={sectionsLabel}
180
+ profileLabel={profileLabel ?? name}
181
+ kernelLabel={kernelLabel ?? name}
182
+ postsLabel="Posts"
183
+ parent={{ href: parentHref, label: parentLabel, icon: host?.avatar }}
184
+ files={false}
185
+ >
186
+ <Fragment slot="profileIcon"><slot name="mark" /></Fragment>
187
+ <slot name="langPicker" slot="langPicker" />
188
+ </Toolbar>
189
+ <section class="cut kernel" id="kernel"><slot /></section>
190
+ </div>
191
+ </>
192
+ ) : (
193
+ <section class="cut kernel" id="kernel" data-guest><slot /></section>
194
+ )}
195
+ </main>
167
196
 
168
- {!chrome && <section class="cut kernel" id="kernel" data-guest><slot /></section>}
197
+ {/* Sheets, toasts, confirmations — inside `.pp` so they take the child's tokens, OUTSIDE `.app`
198
+ so the column does not clip or centre them. Every child has some; naming the slot is what
199
+ stops each one inventing a different place to put them. */}
200
+ <slot name="overlays" />
169
201
  </div>
170
202
 
171
203
  <style>