anentrypoint-design 0.0.445 → 0.0.448

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": "anentrypoint-design",
3
- "version": "0.0.445",
3
+ "version": "0.0.448",
4
4
  "description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
5
5
  "type": "module",
6
6
  "main": "./dist/247420.js",
@@ -6,23 +6,33 @@ import * as webjsx from '../../../vendor/webjsx/index.js';
6
6
  import { Icon } from '../shell.js';
7
7
  const h = webjsx.createElement;
8
8
 
9
- // items: [n, label] or [n, label, {delta, tone: 'up'|'down', spark: number[]}]
9
+ // items: [n, label] or [n, label, {delta, tone: 'up'|'down', spark: number[], invert}]
10
10
  // meta is optional and additive — every existing 2-tuple call site is untouched.
11
+ // `tone` always drives the arrow glyph (it mirrors the delta's own arithmetic
12
+ // sign, so the arrow never contradicts the figure beside it). `invert` is a
13
+ // separate, optional per-metric flag for "lower is better" metrics (error
14
+ // rate, latency, p95, etc.): when set, the good/bad COLOR polarity flips
15
+ // relative to tone while the arrow direction is left alone — a rising error
16
+ // rate still shows an up-arrow (the number went up) but in the bad/danger
17
+ // color, not the good/success color the raw arithmetic sign would imply.
11
18
  export function Kpi({ items = [], emptyText = 'no metrics yet' }) {
12
19
  if (!items.length) return h('div', { class: 'empty' }, emptyText);
13
- return h('div', { class: 'kpi' }, ...items.map(([n, l, meta], i) =>
14
- h('div', { key: i, class: 'kpi-card' },
20
+ return h('div', { class: 'kpi' }, ...items.map(([n, l, meta], i) => {
21
+ const isUp = meta && meta.tone !== 'down';
22
+ const good = meta && meta.invert ? !isUp : isUp;
23
+ return h('div', { key: i, class: 'kpi-card' },
15
24
  h('div', { class: 'num' }, String(n)),
16
25
  h('div', { class: 'lbl' }, l),
17
26
  meta && (meta.delta != null || meta.spark)
18
27
  ? h('div', { class: 'kpi-foot' },
19
28
  meta.delta != null
20
- ? h('span', { class: 'kpi-delta kpi-delta-' + (meta.tone === 'down' ? 'down' : 'up') },
21
- Icon(meta.tone === 'down' ? 'arrow-down' : 'arrow-up', { size: 12 }),
29
+ ? h('span', { class: 'kpi-delta kpi-delta-' + (good ? 'up' : 'down') },
30
+ Icon(isUp ? 'arrow-up' : 'arrow-down', { size: 12 }),
22
31
  String(meta.delta))
23
32
  : null,
24
- meta.spark ? Sparkline({ values: meta.spark, tone: meta.tone }) : null)
25
- : null)));
33
+ meta.spark ? Sparkline({ values: meta.spark, tone: good ? 'up' : 'down' }) : null)
34
+ : null);
35
+ }));
26
36
  }
27
37
 
28
38
  // Minimal inline SVG trend line — token-stroke only, no raw color literals.
@@ -166,6 +166,20 @@ h4, .t-h4 { font-family: var(--ff-display); font-size: var(--fs-h4); line-height
166
166
  margin: 0;
167
167
  }
168
168
 
169
+ /* h1/h2/h3/h4 and .lede/.t-lede are both margin:0 primitives by design (a
170
+ heading used standalone must not force space its context doesn't want).
171
+ But a heading immediately followed by a lede is a named pairing, not two
172
+ independent primitives that happen to be adjacent -- it needs its own gap
173
+ regardless of whether the surrounding shell opts into .ds-app-surface
174
+ (which only adds this spacing on landing/marketing surfaces, leaving every
175
+ Operate-mode kit that skips that class with a zero-gap heading+subtitle). */
176
+ h1 + .lede, h1 + .t-lede,
177
+ h2 + .lede, h2 + .t-lede,
178
+ h3 + .lede, h3 + .t-lede,
179
+ .t-h1 + .lede, .t-h1 + .t-lede {
180
+ margin-top: var(--space-2);
181
+ }
182
+
169
183
  .eyebrow {
170
184
  font-family: var(--ff-mono);
171
185
  font-size: var(--fs-tiny);
@@ -207,6 +207,15 @@ table.kv td:first-child {
207
207
  font-size: var(--fs-xs);
208
208
  text-transform: uppercase; letter-spacing: var(--tr-caps);
209
209
  width: 14ch;
210
+ /* The 14ch column width is a target, not a guarantee — a label whose
211
+ uppercase-transformed width fills the column exactly (e.g. "environment")
212
+ leaves zero slack before the value cell, so label and value render with
213
+ no visible gap between them ("ENVIRONMENTproduction") while shorter
214
+ labels (region, build, by) are saved only by leftover column slack.
215
+ An explicit right-side padding guarantees a gap regardless of label
216
+ length, instead of relying on slack that a long label can consume
217
+ entirely. */
218
+ padding-right: var(--space-3);
210
219
  }
211
220
  table.kv td:last-child {
212
221
  font-weight: 600;
@@ -276,6 +285,18 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
276
285
  .ds-changelog-ver {
277
286
  font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-sm);
278
287
  }
288
+ /* Belt-and-suspenders for the message column: `.row .title` (panel-row.css)
289
+ is already `white-space: normal` (no nowrap/ellipsis), so long entries wrap
290
+ by word as expected whenever the message track has any real width. This
291
+ only matters in the narrow zone between "row still on 3 columns" and the
292
+ panel's own `@container` breakpoint kicking in (see .panel-wide's new
293
+ container-type in panel-row.css) — overflow-wrap:anywhere is the fallback
294
+ so a single long unbroken token still wraps instead of overflowing the
295
+ track, rather than depending solely on the breakpoint transition. */
296
+ .ds-changelog-row .title {
297
+ overflow-wrap: anywhere;
298
+ min-width: 0;
299
+ }
279
300
 
280
301
  /* ============================================================
281
302
  Works
@@ -27,6 +27,18 @@
27
27
  }
28
28
  .panel.panel-inline { background: var(--bg-2); padding: var(--space-3) var(--space-3); }
29
29
  .panel.panel-wide { background: transparent; box-shadow: none; border: none; }
30
+ /* Changelog (and any other panel-wide content) needs its OWN container-query
31
+ context: the existing `@container (max-width: 760px) .ds-changelog-row`
32
+ rule in hero-content.css measures the nearest CQ ancestor, which without
33
+ this is `.app`/`.ds-stage` (base.css) — the whole shell width, not this
34
+ panel's actual rendered width. A changelog panel sitting inside
35
+ .ds-panel-trio (three equal siblings) can be far narrower than 760px
36
+ while the shell itself stays well over that, so the row-collapse rule
37
+ never engages and the message column's `minmax(0, 1fr)` track collapses
38
+ to 0 — the text then renders past the panel's right edge, clipped
39
+ mid-word instead of wrapping. Scoping the container here (not on
40
+ .panel generally) keeps the blast radius to panel-wide content only. */
41
+ .panel.panel-wide { container-type: inline-size; }
30
42
  /* Dense panel — a compact container for app surfaces (inspector sections,
31
43
  sidebars) that want the .panel look without the roomy 16px pad + 24px stack
32
44
  gap. Tighter corner + padding + head, so it sits between .panel and the
@@ -168,6 +180,46 @@ a.row:hover .meta, .row[role="button"]:hover .meta { color: var(--accent-ink); t
168
180
  /* A row with no leading code/index drops the empty first column so the title
169
181
  takes the full width instead of wrapping in the narrow code gutter. */
170
182
  .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
183
+ /* Template-rendered index/example rows (site/theme.mjs "why design" +
184
+ "live examples" panels, via panelNode()/examplesNode() in
185
+ src/page-html/client-script.js) never emit a leading ".code" span for
186
+ these entries (no `code` field on the "features" items), so their actual
187
+ children are title + an inline ".meta.dim" description + a trailing
188
+ ".ds-row-arrow" — three items, but with no ".code" as the first child the
189
+ base 3-track .row grid (minmax(80px,12ch) / minmax(0,1fr) / auto) still
190
+ places the FIRST item (the title) into the narrow 12ch leading track
191
+ meant for a code index, not the 1fr track. ".ds-row-arrow" also had no
192
+ rule at all, and ".meta" is nowrap by default, so on longer descriptions
193
+ ("…never borders", "…--fs-* tokens") the un-wrapped text overflows its
194
+ cramped column straight into the arrow's box. Rows carrying both a dim
195
+ meta description and an arrow get their own two-row template instead:
196
+ title + arrow share row 1, the description drops to its own full-width
197
+ row 2 and wraps normally — matching how every other multi-line row
198
+ pattern in this file (.ds-row-detail) already gets a dedicated line. */
199
+ .row:has(.meta.dim):has(.ds-row-arrow) {
200
+ grid-template-columns: minmax(0, 1fr) auto;
201
+ grid-template-rows: auto auto;
202
+ row-gap: var(--space-1);
203
+ }
204
+ .row:has(.meta.dim):has(.ds-row-arrow) .title { grid-column: 1; grid-row: 1; }
205
+ .row:has(.meta.dim):has(.ds-row-arrow) .ds-row-arrow { grid-column: 2; grid-row: 1; }
206
+ .row:has(.meta.dim):has(.ds-row-arrow) .meta.dim { grid-column: 1 / -1; grid-row: 2; }
207
+ .row .meta.dim {
208
+ white-space: normal;
209
+ min-width: 0;
210
+ text-align: left;
211
+ }
212
+ .ds-row-arrow {
213
+ font-family: var(--ff-mono);
214
+ font-size: var(--fs-xs);
215
+ color: var(--fg-3);
216
+ white-space: nowrap;
217
+ align-self: center;
218
+ justify-self: end;
219
+ }
220
+ a.row:hover .ds-row-arrow, .row[role="button"]:hover .ds-row-arrow {
221
+ color: var(--accent-ink);
222
+ }
171
223
 
172
224
  /* `.row-code` / `.row-title` / `.row-meta` are the BEM-ish spelling of the same
173
225
  three cells as `.code` / `.title` / `.meta`. Both spellings are live in the
@@ -381,7 +381,7 @@ hr.rule, hr.rule-double, hr.rule-dotted {
381
381
  width: 100%; height: 0; border: 0;
382
382
  }
383
383
  hr.rule { border-top: 1px solid var(--rule); }
384
- hr.rule-double { border-top: 3px double var(--rule-strong); }
384
+ hr.rule-double { border-top: 4px double var(--rule-strong); }
385
385
  hr.rule-dotted { border-top: 1px dotted var(--rule-strong); }
386
386
 
387
387
  /* Hairline-only text input — no box, no fill. A single bottom rule that