@nadicodeai/ui 12.1.135 → 12.1.137

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.
@@ -44,6 +44,7 @@ export type AgentOrbMountOptions = AgentOrbMountBase & ({
44
44
  motion: "ambient";
45
45
  state?: never;
46
46
  });
47
+ export declare const LONGEST_FRAME_SECONDS = 0.1;
47
48
  export declare function mountAgentOrb(canvas: HTMLCanvasElement, options: AgentOrbMountOptions): {
48
49
  destroy(): void;
49
50
  setPaused(_value: boolean): void;
@@ -1 +1 @@
1
- {"version":3,"file":"agent-orb.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAEb,KAAK,QAAQ,EAId,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,aAAa,EAOnB,MAAM,oBAAoB,CAAC;AAE5B,QAAA,MAAM,aAAa;;;;;;;;CAQ0B,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,aAAa,CAAC;AACtD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;AAE7D,kDAAkD;AAClD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,cAAc,CAAC;AACxD,+FAA+F;AAC/F,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAyDlD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAuDpF;AA6HD,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB;;;OAGG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAClD,CAAC;IAAE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAExF,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB;;sBAIzC,OAAO;qBAAuB,aAAa;EA0MvF"}
1
+ {"version":3,"file":"agent-orb.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAEb,KAAK,QAAQ,EAId,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,aAAa,EAQnB,MAAM,oBAAoB,CAAC;AAE5B,QAAA,MAAM,aAAa;;;;;;;;CAQ0B,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,aAAa,CAAC;AACtD;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,MAAM,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC;AAE7D,kDAAkD;AAClD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,cAAc,CAAC;AACxD,+FAA+F;AAC/F,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AA+DlD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAuDpF;AA2ID,KAAK,iBAAiB,GAAG;IACvB,IAAI,EAAE,cAAc,CAAC;IACrB;;;OAGG;IACH,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAClD,CAAC;IAAE,MAAM,CAAC,EAAE,QAAQ,CAAC;IAAC,KAAK,CAAC,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAmIxF,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,wBAAgB,aAAa,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB;;sBAIzC,OAAO;qBAAuB,aAAa;EA2LvF"}
@@ -1,5 +1,5 @@
1
1
  import { finalizeFrame, MODE_FRAMES, makeProj, radiusScale, resolvePreset, } from "thinking-orbs/engine";
2
- import { motionPose, nativeSpeed, paintOrbCue, reducedBreath, readOrbTiming, stateSpeed, } from "./agent-orb-motion.js";
2
+ import { motionPose, nativeSpeed, ORB_FRAME_RATE, paintOrbCue, reducedBreath, readOrbTiming, stateSpeed, } from "./agent-orb-motion.js";
3
3
  const agentOrbForms = {
4
4
  orbit: "working",
5
5
  globe: "searching",
@@ -28,14 +28,11 @@ const presenceWeights = {
28
28
  const nadiaStripes = ["--nc-identity-azzurro", "--nc-identity-verde", null, "--nc-identity-rosso"];
29
29
  const celebrationTokens = ["--nc-acqua-700", "--nc-viola-700", "--nc-warning", "--nc-rosso-700"];
30
30
  const statusTokens = { waiting: "--nc-warning-deep", blocked: "--nc-error" };
31
- const appearanceTokens = [
32
- ...celebrationTokens,
33
- ...nadiaStripes.filter((token) => token !== null),
34
- ...Object.values(statusTokens),
35
- "--nc-duration-wait",
36
- "--nc-duration-confirm",
37
- "--nc-duration-transition",
38
- ];
31
+ /**
32
+ * WebKit's canvas rejects `color-mix()` in a gradient stop, so a mix is handed
33
+ * to the canvas as the colour it computes to.
34
+ */
35
+ const computedColors = new Map();
39
36
  /**
40
37
  * Sofia's four stripes: cobalto, giallo, the orb's own pigment and arancio, the
41
38
  * identity hues Nadia does not wear, so side by side the two carry all six.
@@ -50,6 +47,14 @@ const figureStripes = {
50
47
  nadia: nadiaStripes,
51
48
  sofia: sofiaStripes,
52
49
  };
50
+ const appearanceTokens = [
51
+ ...celebrationTokens,
52
+ ...[...nadiaStripes, ...sofiaStripes].filter((token) => token !== null),
53
+ ...Object.values(statusTokens),
54
+ "--nc-duration-wait",
55
+ "--nc-duration-confirm",
56
+ "--nc-duration-transition",
57
+ ];
53
58
  /** A stable direction on the unit sphere, the vendor's Fibonacci lattice. */
54
59
  function fibonacci(i, n) {
55
60
  const y = 1 - (2 * (i + 0.5)) / n;
@@ -120,10 +125,18 @@ function facing(frame, size) {
120
125
  dot.x = size - dot.x;
121
126
  return frame;
122
127
  }
128
+ function detailProfile(drawn) {
129
+ if (drawn <= 32)
130
+ return 20;
131
+ return drawn <= 48 ? 32 : 64;
132
+ }
133
+ function shownState(state, age, motion, timing) {
134
+ return motion === "ambient" || (state === "done" && age >= timing.doneDuration) ? "idle" : state;
135
+ }
123
136
  function paintAgentOrb(context, input) {
124
137
  const { form, size, seconds, color, state, age, reduced, breath, celebrationColors, stripeColors, } = input;
125
138
  const presence = presenceWeights[input.presence];
126
- const preset = resolvePreset(agentOrbForms[form === "nadia" || form === "sofia" ? "ribbon" : form], size <= 32 ? 20 : 64);
139
+ const preset = resolvePreset(agentOrbForms[form === "nadia" || form === "sofia" ? "ribbon" : form], detailProfile(size));
127
140
  const frame = form === "nadia"
128
141
  ? stripedRibbonFrame(size, seconds, preset.opts)
129
142
  : form === "sofia"
@@ -131,7 +144,7 @@ function paintAgentOrb(context, input) {
131
144
  : MODE_FRAMES[preset.mode](size, seconds, preset.opts);
132
145
  context.clearRect(0, 0, size, size);
133
146
  const done = state === "done" && age >= input.timing.doneDuration;
134
- const visualState = input.motion === "ambient" || done ? "idle" : state;
147
+ const visualState = shownState(state, age, input.motion, input.timing);
135
148
  const poseAge = input.motion === "ambient" ? 0 : done ? age - input.timing.doneDuration : age;
136
149
  const pose = motionPose(visualState, poseAge, input.timing, reduced);
137
150
  const cueAge = done ? age - input.timing.doneDuration : age;
@@ -173,16 +186,137 @@ function paintAgentOrb(context, input) {
173
186
  paintOrbCue(context, visualState, size, cueAge, reduced, celebrationColors, "front", breath, input.timing, statusColor);
174
187
  }
175
188
  }
189
+ function createOrbWatchers(stopped) {
190
+ const orbs = new Map();
191
+ const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
192
+ function changedWithin(roots) {
193
+ const inside = (canvas) => {
194
+ for (let node = canvas; node; node = node.parentElement)
195
+ if (roots.has(node))
196
+ return true;
197
+ return false;
198
+ };
199
+ const writes = [...orbs].flatMap(([canvas, orb]) => (inside(canvas) ? [orb.readChange()] : []));
200
+ for (const write of writes)
201
+ write?.();
202
+ }
203
+ function playAll() {
204
+ for (const orb of orbs.values())
205
+ orb.play();
206
+ }
207
+ // A browser that cannot tell whether an orb is seen shows it as seen.
208
+ const visibility = typeof IntersectionObserver === "undefined"
209
+ ? undefined
210
+ : new IntersectionObserver((entries) => {
211
+ for (const entry of entries)
212
+ orbs.get(entry.target)?.setVisible(entry.isIntersecting);
213
+ });
214
+ const appearance = new MutationObserver((records) => {
215
+ changedWithin(new Set(records.map((record) => record.target)));
216
+ });
217
+ appearance.observe(document.documentElement, {
218
+ attributes: true,
219
+ attributeFilter: ["class", "style", "data-theme"],
220
+ subtree: true,
221
+ });
222
+ const box = new ResizeObserver((entries) => {
223
+ const writes = entries.map((entry) => orbs.get(entry.target)?.readResize());
224
+ for (const write of writes)
225
+ write?.();
226
+ });
227
+ // A colour transition on the canvas or on an element it inherits from hands
228
+ // the observer the colour the transition starts from, so the orb reads its
229
+ // colour again when that transition ends. The event bubbles up from where it
230
+ // ran, never down to the canvas, so it is heard on the document.
231
+ function settle(event) {
232
+ if (event.propertyName === "color" && event.target instanceof Node)
233
+ changedWithin(new Set([event.target]));
234
+ }
235
+ function resized() {
236
+ changedWithin(new Set([document.documentElement]));
237
+ }
238
+ document.addEventListener("transitionend", settle, true);
239
+ motion.addEventListener("change", playAll);
240
+ document.addEventListener("visibilitychange", playAll);
241
+ window.addEventListener("resize", resized);
242
+ return {
243
+ motion,
244
+ watch(canvas, orb) {
245
+ orbs.set(canvas, orb);
246
+ visibility?.observe(canvas);
247
+ box.observe(canvas);
248
+ },
249
+ unwatch(canvas, orb) {
250
+ if (orbs.get(canvas) !== orb)
251
+ return;
252
+ orbs.delete(canvas);
253
+ if (orbs.size > 0) {
254
+ visibility?.unobserve(canvas);
255
+ box.unobserve(canvas);
256
+ return;
257
+ }
258
+ visibility?.disconnect();
259
+ appearance.disconnect();
260
+ box.disconnect();
261
+ document.removeEventListener("transitionend", settle, true);
262
+ motion.removeEventListener("change", playAll);
263
+ document.removeEventListener("visibilitychange", playAll);
264
+ window.removeEventListener("resize", resized);
265
+ stopped();
266
+ },
267
+ };
268
+ }
269
+ let pageOrbWatchers;
270
+ function createOrbClock() {
271
+ const running = new Set();
272
+ let request = 0;
273
+ function frame(now) {
274
+ request = 0;
275
+ for (const orb of [...running])
276
+ if (!orb(now))
277
+ running.delete(orb);
278
+ if (running.size > 0 && request === 0)
279
+ request = requestAnimationFrame(frame);
280
+ }
281
+ return {
282
+ run(orb) {
283
+ running.add(orb);
284
+ if (request === 0)
285
+ request = requestAnimationFrame(frame);
286
+ },
287
+ stop(orb) {
288
+ running.delete(orb);
289
+ if (running.size > 0 || request === 0)
290
+ return;
291
+ cancelAnimationFrame(request);
292
+ request = 0;
293
+ },
294
+ };
295
+ }
296
+ const orbClock = createOrbClock();
297
+ /**
298
+ * A display's frames arrive a little early or late, so a paint due within this
299
+ * many milliseconds is painted on the frame at hand: at 60 Hz a 30 fps orb then
300
+ * paints every second frame rather than every second or third.
301
+ */
302
+ const PAINT_SLACK_MS = 4;
303
+ function orbWatchers() {
304
+ pageOrbWatchers ??= createOrbWatchers(() => {
305
+ pageOrbWatchers = undefined;
306
+ });
307
+ return pageOrbWatchers;
308
+ }
309
+ export const LONGEST_FRAME_SECONDS = 0.1;
176
310
  export function mountAgentOrb(canvas, options) {
177
311
  const { form, presence = "plain" } = options;
178
312
  const context = canvas.getContext("2d");
179
313
  if (!context)
180
314
  return { destroy() { }, setPaused(_value) { }, setState(_value) { } };
181
- const motion = window.matchMedia("(prefers-reduced-motion: reduce)");
315
+ const page = orbWatchers();
316
+ const { motion } = page;
182
317
  let paused = options.paused ?? false;
183
318
  let visible = true;
184
319
  let disposed = false;
185
- let request = 0;
186
320
  let seconds = 0.6;
187
321
  let age = 0;
188
322
  let breath = 0;
@@ -241,11 +375,10 @@ export function mountAgentOrb(canvas, options) {
241
375
  return !(state === "blocked" && age >= timing.blockedDuration);
242
376
  }
243
377
  function tick(now) {
244
- request = 0;
245
378
  if (!running())
246
- return;
379
+ return false;
247
380
  if (previous !== null) {
248
- const elapsed = Math.min((now - previous) / 1000, 0.1);
381
+ const elapsed = Math.min((now - previous) / 1000, LONGEST_FRAME_SECONDS);
249
382
  if (motion.matches)
250
383
  breath += elapsed;
251
384
  else {
@@ -257,98 +390,92 @@ export function mountAgentOrb(canvas, options) {
257
390
  }
258
391
  }
259
392
  previous = now;
260
- if (now - lastPaint >= 1000 / 30 || !running()) {
393
+ const rate = shownState(state, age, orbMotion, timing) === "idle"
394
+ ? ORB_FRAME_RATE.resting
395
+ : ORB_FRAME_RATE.busy;
396
+ if (now - lastPaint >= 1000 / rate - PAINT_SLACK_MS || !running()) {
261
397
  paint();
262
398
  lastPaint = now;
263
399
  }
264
- if (running())
265
- request = requestAnimationFrame(tick);
400
+ return running();
266
401
  }
267
402
  function play() {
268
- cancelAnimationFrame(request);
269
- request = 0;
270
403
  previous = null;
271
404
  paint();
272
405
  if (running())
273
- request = requestAnimationFrame(tick);
406
+ orbClock.run(tick);
407
+ else
408
+ orbClock.stop(tick);
274
409
  }
275
- /** WebKit's canvas rejects `color-mix()` in a gradient stop, so a mix is
276
- * handed to the canvas as the colour it computes to. */
277
410
  function computedColor(declaration) {
411
+ const known = computedColors.get(declaration);
412
+ if (known)
413
+ return known;
278
414
  const probe = document.createElement("span");
279
415
  probe.hidden = true;
280
416
  probe.style.color = declaration;
281
417
  (canvas.parentElement ?? document.body).append(probe);
282
418
  const resolved = getComputedStyle(probe).color;
283
419
  probe.remove();
284
- return resolved || color;
285
- }
286
- function readAppearanceKey(appearance, side) {
287
- return [
288
- side,
289
- window.devicePixelRatio || 1,
290
- appearance.color,
291
- ...appearanceTokens.map((token) => appearance.getPropertyValue(token)),
292
- ].join("|");
420
+ if (!resolved)
421
+ return color;
422
+ computedColors.set(declaration, resolved);
423
+ return resolved;
293
424
  }
294
- function refreshIfChanged() {
295
- if (readAppearanceKey(getComputedStyle(canvas), measure()) !== appearanceKey)
296
- refresh();
425
+ function readAppearance() {
426
+ const style = getComputedStyle(canvas);
427
+ const tokens = new Map(appearanceTokens.map((token) => [token, style.getPropertyValue(token).trim()]));
428
+ const key = [window.devicePixelRatio || 1, style.color, ...tokens.values()].join("|");
429
+ return { key, color: style.color, tokens, timing: readOrbTiming(style) };
297
430
  }
298
- function refresh() {
431
+ function resize(side) {
299
432
  if (disposed || !canvas.isConnected)
300
433
  return;
301
- painted = measure();
434
+ painted = side;
302
435
  const backing = Math.max(1, Math.round(painted * Math.min(window.devicePixelRatio || 1, 2)));
303
436
  canvas.width = backing;
304
437
  canvas.height = backing;
305
438
  ratio = backing / painted;
306
- const appearance = getComputedStyle(canvas);
307
- appearanceKey = readAppearanceKey(appearance, painted);
439
+ play();
440
+ }
441
+ function refresh(appearance, side) {
442
+ appearanceKey = appearance.key;
308
443
  color = appearance.color;
309
- timing = readOrbTiming(appearance);
444
+ timing = appearance.timing;
310
445
  statusColors = {
311
- waiting: computedColor(appearance.getPropertyValue(statusTokens.waiting).trim() || color),
312
- blocked: computedColor(appearance.getPropertyValue(statusTokens.blocked).trim() || color),
446
+ waiting: computedColor(appearance.tokens.get(statusTokens.waiting) || color),
447
+ blocked: computedColor(appearance.tokens.get(statusTokens.blocked) || color),
313
448
  };
314
- celebrationColors = celebrationTokens.map((token) => computedColor(`color-mix(in oklch, ${appearance.getPropertyValue(token).trim() || color} 75%, white)`));
315
- stripeColors = (figureStripes[form] ?? []).map((token) => (token && appearance.getPropertyValue(token).trim()) || color);
316
- play();
449
+ celebrationColors = celebrationTokens.map((token) => computedColor(`color-mix(in oklch, ${appearance.tokens.get(token) || color} 75%, white)`));
450
+ stripeColors = (figureStripes[form] ?? []).map((token) => (token && appearance.tokens.get(token)) || color);
451
+ resize(side);
317
452
  }
318
- const visibility = new IntersectionObserver(([entry]) => {
319
- visible = entry?.isIntersecting ?? false;
320
- play();
321
- });
322
- visibility.observe(canvas);
323
- const appearance = new MutationObserver(refreshIfChanged);
324
- for (let ancestor = canvas; ancestor; ancestor = ancestor.parentElement) {
325
- appearance.observe(ancestor, {
326
- attributes: true,
327
- attributeFilter: ["class", "style", "data-theme"],
328
- });
453
+ function readResize() {
454
+ if (disposed || !canvas.isConnected)
455
+ return undefined;
456
+ const side = measure();
457
+ return Math.abs(side - painted) >= 0.5 ? () => resize(side) : undefined;
329
458
  }
330
- // Layout, not the declared size, decides the pixels, so the box is observed
331
- // rather than remounted on: an orb sized by its container stays sharp.
332
- const box = new ResizeObserver(() => {
333
- if (Math.abs(measure() - painted) >= 0.5)
334
- refresh();
335
- });
336
- box.observe(canvas);
337
- // A colour transition on the canvas or on an element it inherits from hands
338
- // the observer the colour the transition starts from, so the orb reads its
339
- // colour again when that transition ends. The event bubbles up from where it
340
- // ran, never down to the canvas, so it is heard on the document.
341
- function settle(event) {
342
- if (event.propertyName === "color" &&
343
- event.target instanceof Node &&
344
- event.target.contains(canvas))
345
- refreshIfChanged();
459
+ function readChange() {
460
+ if (disposed || !canvas.isConnected)
461
+ return undefined;
462
+ const appearance = readAppearance();
463
+ if (appearance.key === appearanceKey)
464
+ return readResize();
465
+ const side = measure();
466
+ return () => refresh(appearance, side);
346
467
  }
347
- document.addEventListener("transitionend", settle, true);
348
- motion.addEventListener("change", play);
349
- document.addEventListener("visibilitychange", play);
350
- window.addEventListener("resize", refreshIfChanged);
351
- refresh();
468
+ const watched = {
469
+ readChange,
470
+ readResize,
471
+ setVisible(value) {
472
+ visible = value;
473
+ play();
474
+ },
475
+ play,
476
+ };
477
+ page.watch(canvas, watched);
478
+ readChange()?.();
352
479
  return {
353
480
  setState(value) {
354
481
  state = value;
@@ -362,14 +489,8 @@ export function mountAgentOrb(canvas, options) {
362
489
  },
363
490
  destroy() {
364
491
  disposed = true;
365
- cancelAnimationFrame(request);
366
- visibility.disconnect();
367
- appearance.disconnect();
368
- box.disconnect();
369
- document.removeEventListener("transitionend", settle, true);
370
- motion.removeEventListener("change", play);
371
- document.removeEventListener("visibilitychange", play);
372
- window.removeEventListener("resize", refreshIfChanged);
492
+ orbClock.stop(tick);
493
+ page.unwatch(canvas, watched);
373
494
  },
374
495
  };
375
496
  }
@@ -9,6 +9,10 @@ export type TableDetailFact = {
9
9
  /** The value stands beside the record's name instead, which ends in an ellipsis before it: a status. */
10
10
  besideName?: boolean;
11
11
  };
12
+ /** A facts line reads a `Tag` as its text and a block value inline. */
13
+ export declare const detailFactsLine = "[&_[data-slot=tag]]:contents [&>span>:is(div,p,.block,.grid,.flex)]:inline";
14
+ /** A facts line that wraps breaks every value between its words, except a badge, which stands whole. */
15
+ export declare const detailFactsWrap = "[&_:not(.sr-only,[data-slot=badge],[data-slot=badge]_*,[data-slot=status-badge],[data-slot=status-badge]_*)]:whitespace-normal";
12
16
  export declare function DetailFacts({ facts, leadingSeparator, }: {
13
17
  facts: readonly TableDetailFact[];
14
18
  leadingSeparator?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"table-compact-line.d.ts","sourceRoot":"","sources":["../../src/internal/table-compact-line.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4HAA4H;IAC5H,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wGAAwG;IACxG,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,gBAAwB,GACzB,EAAE;IACD,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,uBAQA;AAED,KAAK,qBAAqB,GAAG;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAI/F,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,qBAEvD;AAED,4IAA4I;AAC5I,wBAAgB,iBAAiB,6BAgBhC;AAED,2KAA2K;AAC3K,wBAAgB,qBAAqB,6BAkBpC;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,qBAEA;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
1
+ {"version":3,"file":"table-compact-line.d.ts","sourceRoot":"","sources":["../../src/internal/table-compact-line.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAuB,KAAK,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,4HAA4H;IAC5H,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wGAAwG;IACxG,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,eAAe,+EACkD,CAAC;AAE/E,wGAAwG;AACxG,eAAO,MAAM,eAAe,mIACsG,CAAC;AAEnI,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,gBAAwB,GACzB,EAAE;IACD,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,uBAQA;AAED,KAAK,qBAAqB,GAAG;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAA;CAAE,CAAC;AAI/F,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,qBAEvD;AAED,4IAA4I;AAC5I,wBAAgB,iBAAiB,6BAahC;AAED,2KAA2K;AAC3K,wBAAgB,qBAAqB,6BAkBpC;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,qBAEA;AAED,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD"}
@@ -3,6 +3,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { tableCompactLayouts } from "../components/table-layouts.js";
5
5
  import { cn } from "../lib/utils.js";
6
+ /** A facts line reads a `Tag` as its text and a block value inline. */
7
+ export const detailFactsLine = "[&_[data-slot=tag]]:contents [&>span>:is(div,p,.block,.grid,.flex)]:inline";
8
+ /** A facts line that wraps breaks every value between its words, except a badge, which stands whole. */
9
+ export const detailFactsWrap = "[&_:not(.sr-only,[data-slot=badge],[data-slot=badge]_*,[data-slot=status-badge],[data-slot=status-badge]_*)]:whitespace-normal";
6
10
  export function DetailFacts({ facts, leadingSeparator = false, }) {
7
11
  return facts.map((fact, index) => (_jsxs("span", { children: [index > 0 || leadingSeparator ? _jsx("span", { "aria-hidden": "true", children: " \u00B7 " }) : null, _jsxs("span", { className: "sr-only", children: [fact.label, ": "] }), fact.value] }, fact.id)));
8
12
  }
@@ -18,7 +22,7 @@ export function TableCompactFacts() {
18
22
  const facts = line.facts.filter((fact) => !fact.besideName);
19
23
  if (facts.length === 0)
20
24
  return null;
21
- return (_jsx("span", { className: cn("[&_[data-slot=tag]]:contents [&>span>:is(div,p,.block,.grid,.flex)]:inline", tableCompactLayouts[line.layout].details), "data-slot": "table-detail-line", children: _jsx(DetailFacts, { facts: facts, leadingSeparator: true }) }));
25
+ return (_jsx("span", { className: cn(detailFactsLine, detailFactsWrap, tableCompactLayouts[line.layout].details), "data-slot": "table-detail-line", children: _jsx(DetailFacts, { facts: facts, leadingSeparator: true }) }));
22
26
  }
23
27
  /** The compact facts that stand beside the name of the row this stands in, which no ellipsis cuts; nothing outside such a row or on a card wide enough for the columns. */
24
28
  export function TableCompactNameFacts() {
@@ -624,9 +624,9 @@ export const USAGE = [
624
624
  module: "agent-orb",
625
625
  family: "Status",
626
626
  summary: "An Agent, anywhere: her orb, the only thing that moves on its own.",
627
- when: 'An Agent, anywhere: 20 in the sidebar, 32 in a row, 64 on her Profile card, 96 in an Agent card, 160 on entry. There is no other Agent picture. The sizes are 20, 24, 32, 40, 64, 96 and 160 px, and no other. On a photograph the orb takes the stronger `presence="over-picture"` weight; everywhere else it is `plain`.',
627
+ when: "An Agent, anywhere: 20 in the sidebar, 32 in a row, 64 on her Profile card, 96 in an Agent card, 160 on entry. There is no other Agent picture. The sizes are 20, 24, 32, 40, 64, 96 and 160 px, and no other. Detail follows the size the orb is drawn at: up to 32 px it draws the engine's lightest dot profile, at 40 px the middle one and from 64 px the full one, since a small orb cannot show the full profile's dots apart. On a photograph the orb takes the stronger `presence=\"over-picture\"` weight; everywhere else it is `plain`.",
628
628
  instead: 'A person is an `Avatar`. The system\'s own wait is the waiting line, never an orb. An orb in artwork, such as a sign-in picture, takes `motion="ambient"` and claims no activity. An orb that stands for an Agent shows her real state.',
629
- behaviour: "The only thing that moves on its own. Idle particles turn at 86.4% of the form's native pace, with a separate 6.4 s breath. Working sweeps a ribbon every 3.2 s; thinking passes three pulses over 2.4 s. Waiting leans softly as centered pause bars arrive; blocked recoils as a centered stop sign lands. Both entrances settle over 2 s, then waiting breathes and blocked holds still. Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath. A state change interrupts the previous gesture; `motionKey` replays it and `paused` freezes it. A surface that only knows a machine checked in draws idle. No state draws a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue. Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45 opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep their centered signs without an entrance gesture. An orb is one of seven forms, `ribbon`, `lattice`, `orbit`, `globe`, `network`, `braid` and `morph`, in one colour a person chose: cobalto, verde or arancio, or none, which draws it in the text colour. Giallo is not offered because it fails 3:1 on white; rosso is not offered because it is the error red. nadicode's own two Agents are the only ones with a figure nobody chooses, the same at every size and in every state. Nadia is her striped ribbon, the form `nadia`: azzurro, verde, the text colour and rosso along its whole length. Sofia, the Agent that looks up a new company, is her sister, the form `sofia`: the same ribbon turned to face Nadia's, striped cobalto, giallo, the text colour and arancio, the identity hues Nadia does not wear. Neither figure is ever stored as an Agent's look. An Agent's form is stored as `orb:<form>` and its colour as the identity hex or nothing; a template declares its starting look the same way. The stored-appearance resolver reads it: the root Agent always draws as Nadia, an unknown form draws `orbit`, an unknown colour the text colour, and a stored rosso draws arancio. The retired `forma:*` shapes each draw one of the seven forms, so an Agent that chose one before the orbs keeps a distinct look. An Agent's look is a person's choice and is never derived from a name, id or role. A template that names no look is the one exception: `templateAgentOrb` gives it a form and colour fixed by its slug, so the templates in a gallery differ and the Portal and Nadia draw the same one; Nadia and Sofia keep their figures.",
629
+ behaviour: "The only thing that moves on its own. Idle particles turn at 86.4% of the form's native pace, with a separate 6.4 s breath. Working sweeps a ribbon every 3.2 s; thinking passes three pulses over 2.4 s. Waiting leans softly as centered pause bars arrive; blocked recoils as a centered stop sign lands. Both entrances settle over 2 s, then waiting breathes and blocked holds still. Done celebrates once over 4.8 s, then rests at 72% of native particle speed with the Idle breath. A state change interrupts the previous gesture; `motionKey` replays it and `paused` freezes it. A surface that only knows a machine checked in draws idle. No state draws a circle around the orb. Ambient motion moves the form at its own pace with no state pose or cue. An orb at rest (idle, ambient, or done after its celebration) paints 15 frames a second; every other state, gesture and the celebration paint 30. The pace is the same at either rate. Reduced motion: movement stops, a thinking or working orb breathes between full ink and 0.45 opacity so busy still reads as busy, an ambient orb holds still, and waiting and blocked keep their centered signs without an entrance gesture. An orb is one of seven forms, `ribbon`, `lattice`, `orbit`, `globe`, `network`, `braid` and `morph`, in one colour a person chose: cobalto, verde or arancio, or none, which draws it in the text colour. Giallo is not offered because it fails 3:1 on white; rosso is not offered because it is the error red. nadicode's own two Agents are the only ones with a figure nobody chooses, the same at every size and in every state. Nadia is her striped ribbon, the form `nadia`: azzurro, verde, the text colour and rosso along its whole length. Sofia, the Agent that looks up a new company, is her sister, the form `sofia`: the same ribbon turned to face Nadia's, striped cobalto, giallo, the text colour and arancio, the identity hues Nadia does not wear. Neither figure is ever stored as an Agent's look. An Agent's form is stored as `orb:<form>` and its colour as the identity hex or nothing; a template declares its starting look the same way. The stored-appearance resolver reads it: the root Agent always draws as Nadia, an unknown form draws `orbit`, an unknown colour the text colour, and a stored rosso draws arancio. The retired `forma:*` shapes each draw one of the seven forms, so an Agent that chose one before the orbs keeps a distinct look. An Agent's look is a person's choice and is never derived from a name, id or role. A template that names no look is the one exception: `templateAgentOrb` gives it a form and colour fixed by its slug, so the templates in a gallery differ and the Portal and Nadia draw the same one; Nadia and Sofia keep their figures.",
630
630
  words: "Text sits beside the orb, never on it. Where the exact state matters a word names it: *Working*, *Waiting for you*.",
631
631
  access: '`role="img"` labelled with the Agent\'s name, and her state where it matters; `decorative` when her name is already beside it.',
632
632
  },