@nadicodeai/ui 12.1.136 → 12.1.138

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.
Files changed (42) hide show
  1. package/dist/components/agent-orb.d.ts +5 -1
  2. package/dist/components/agent-orb.d.ts.map +1 -1
  3. package/dist/components/agent-orb.js +5 -1
  4. package/dist/components/brand.d.ts +5 -5
  5. package/dist/components/brand.d.ts.map +1 -1
  6. package/dist/components/brand.js +5 -5
  7. package/dist/components/catalog-entry.d.ts +5 -4
  8. package/dist/components/catalog-entry.d.ts.map +1 -1
  9. package/dist/components/catalog-entry.js +4 -3
  10. package/dist/components/company-card/renderer.d.ts +8 -0
  11. package/dist/components/company-card/renderer.d.ts.map +1 -1
  12. package/dist/components/company-card/renderer.js +122 -53
  13. package/dist/components/company-card.d.ts.map +1 -1
  14. package/dist/components/company-card.js +70 -39
  15. package/dist/components/hive-scene.d.ts.map +1 -1
  16. package/dist/components/hive-scene.js +46 -8
  17. package/dist/components/identity-mark.d.ts +4 -4
  18. package/dist/components/identity-mark.d.ts.map +1 -1
  19. package/dist/components/identity-mark.js +2 -3
  20. package/dist/components/scroll-area.js +3 -3
  21. package/dist/components/settings-section.d.ts +26 -15
  22. package/dist/components/settings-section.d.ts.map +1 -1
  23. package/dist/components/settings-section.js +23 -16
  24. package/dist/components/switch.d.ts +2 -1
  25. package/dist/components/switch.d.ts.map +1 -1
  26. package/dist/components/switch.js +3 -2
  27. package/dist/components/theme-mode-switcher.d.ts +1 -1
  28. package/dist/components/theme-mode-switcher.js +1 -1
  29. package/dist/internal/agent-orb-motion.d.ts +4 -0
  30. package/dist/internal/agent-orb-motion.d.ts.map +1 -1
  31. package/dist/internal/agent-orb-motion.js +1 -0
  32. package/dist/internal/agent-orb.d.ts +1 -0
  33. package/dist/internal/agent-orb.d.ts.map +1 -1
  34. package/dist/internal/agent-orb.js +207 -86
  35. package/dist/showcase/specimens/compositions.js +1 -1
  36. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  37. package/dist/showcase/specimens/inputs.js +2 -2
  38. package/dist/showcase/specimens/status.js +2 -2
  39. package/dist/showcase/usage.generated.d.ts.map +1 -1
  40. package/dist/showcase/usage.generated.js +13 -13
  41. package/dist/standalone/index.js +2 -2
  42. package/package.json +2 -2
@@ -239,18 +239,25 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
239
239
  drawComb(comb, width, height);
240
240
  context = sizeCanvas(flow, width, height);
241
241
  };
242
+ const observeLayout = (onLayout) => {
243
+ const resize = new ResizeObserver(onLayout);
244
+ resize.observe(scene);
245
+ if (wordsColumn)
246
+ resize.observe(wordsColumn);
247
+ return resize;
248
+ };
242
249
  place();
243
- const resize = new ResizeObserver(place);
244
- resize.observe(scene);
245
- if (wordsColumn)
246
- resize.observe(wordsColumn);
247
- if (still)
250
+ if (still) {
251
+ const resize = observeLayout(place);
248
252
  return () => resize.disconnect();
253
+ }
249
254
  const colours = orbRefs.current.map((canvas) => canvas ? getComputedStyle(canvas).color : "white");
250
255
  const particles = [];
251
256
  let frame = 0;
252
- let last = performance.now();
257
+ let last = null;
253
258
  let nextSpawn = 0;
259
+ // A browser that cannot tell whether the scene is seen shows it as seen.
260
+ let onScreen = typeof IntersectionObserver === "undefined";
254
261
  const spawn = () => {
255
262
  const source = Math.floor(Math.random() * AGENTS.length);
256
263
  const seat = seats[source];
@@ -287,8 +294,11 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
287
294
  trail: [],
288
295
  });
289
296
  };
297
+ const flowing = () => context !== null && !reduced.matches && seats.some((seat) => seat !== null);
298
+ const running = () => onScreen && !document.hidden && (particles.length > 0 || flowing());
290
299
  const tick = (now) => {
291
- const dt = Math.min(0.05, (now - last) / 1000);
300
+ frame = 0;
301
+ const dt = last === null ? 0 : Math.min(0.05, (now - last) / 1000);
292
302
  last = now;
293
303
  nextSpawn -= dt;
294
304
  const paint = context;
@@ -322,12 +332,40 @@ function HiveScene({ mode, column = "default", logo, picture, work, chrome, labe
322
332
  }
323
333
  paint.globalAlpha = 1;
324
334
  }
335
+ if (running())
336
+ frame = requestAnimationFrame(tick);
337
+ };
338
+ const play = () => {
339
+ if (!running()) {
340
+ cancelAnimationFrame(frame);
341
+ frame = 0;
342
+ return;
343
+ }
344
+ if (frame)
345
+ return;
346
+ last = null;
325
347
  frame = requestAnimationFrame(tick);
326
348
  };
327
- frame = requestAnimationFrame(tick);
349
+ const resize = observeLayout(() => {
350
+ place();
351
+ play();
352
+ });
353
+ const visibility = onScreen
354
+ ? undefined
355
+ : new IntersectionObserver((entries) => {
356
+ onScreen = entries.at(-1)?.isIntersecting ?? false;
357
+ play();
358
+ });
359
+ visibility?.observe(scene);
360
+ document.addEventListener("visibilitychange", play);
361
+ reduced.addEventListener("change", play);
362
+ play();
328
363
  return () => {
329
364
  cancelAnimationFrame(frame);
330
365
  resize.disconnect();
366
+ visibility?.disconnect();
367
+ document.removeEventListener("visibilitychange", play);
368
+ reduced.removeEventListener("change", play);
331
369
  };
332
370
  }, [mode, still, wordsColumn]);
333
371
  return (_jsxs("div", { ...props, className: cn("nc-hive dark", className), "data-mode": mode, "data-slot": "hive-scene", ref: sceneRef, ...(mode === "loading" ? { "aria-label": label, role: "status" } : {}), children: [chrome, _jsx("img", { alt: logo.label, className: "nc-hive-logo", "data-slot": "hive-logo", src: logo.src }), picture, _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-comb", ref: combRef }), _jsx("canvas", { "aria-hidden": "true", className: "nc-hive-flow", ref: flowRef }), still
@@ -42,11 +42,11 @@ export type IdentityMarkProps = {
42
42
  image?: string;
43
43
  } | {
44
44
  kind: "record";
45
- /** The kind's own icon, the one its section has in the navigation: Mail for a mailbox. */
45
+ /** The record's own icon when it names one, as a skill does in its hub card; otherwise its kind's, the one its section has in the navigation: Mail for a mailbox. */
46
46
  icon: IconComponent;
47
47
  /** A catalogue kind's ground; neutral is the ringed card ground. */
48
- tone?: "neutral" | "skill" | "plugin" | "teal";
49
- /** The record's own object picture, a transparent image drawn on its kind's ground in place of the icon. */
48
+ tone?: "neutral" | "plugin" | "teal";
49
+ /** The record's own object picture, a transparent image drawn on its kind's ground in place of the icon at 64; smaller marks draw the icon. */
50
50
  picture?: string;
51
51
  });
52
52
  /**
@@ -58,7 +58,7 @@ export type IdentityMarkProps = {
58
58
  * @family Status
59
59
  * @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
60
60
  * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
61
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
61
+ * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a skill takes the icon its hub card names, and the Skills icon when it names none, on that same neutral ringed tile, so the icon alone tells one skill from another and no colour stands for the kind; a plugin takes the `info-soft` ground with the Plugins icon, without a ring; a record's own object picture, such as a Library skill's or plugin's, is drawn only at 64, at the head of its own page, on its kind's ground in the icon's place, because at a row's size its detail does not read. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
62
62
  * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
63
63
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
64
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,0FAA0F;IAC1F,IAAI,EAAE,aAAa,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC/C,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AA6DF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CA6DhE"}
1
+ {"version":3,"file":"identity-mark.d.ts","sourceRoot":"","sources":["../../src/components/identity-mark.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnF,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAW,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAMnE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE3D,qHAAqH;AACrH,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4GAA4G;IAC5G,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,CACA;IACE,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACrF,kGAAkG;IAClG,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,SAAS,CAAC;CAC1C,GACD,CAAC;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAAC,GAC7C;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,wFAAwF;IACxF,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAChD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,qKAAqK;IACrK,IAAI,EAAE,aAAa,CAAC;IACpB,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,+IAA+I;IAC/I,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CACJ,CAAC;AA4DF;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,CA6DhE"}
@@ -15,7 +15,6 @@ const MEASURES = {
15
15
  };
16
16
  const TONES = {
17
17
  neutral: "bg-card text-muted-foreground ring-1 ring-border ring-inset",
18
- skill: "bg-category-purple text-category-purple-foreground",
19
18
  plugin: "bg-info-soft text-info-soft-foreground",
20
19
  teal: "bg-category-teal text-category-teal-foreground",
21
20
  };
@@ -39,7 +38,7 @@ function RecordTile({ label, size, tone, children, }) {
39
38
  * @family Status
40
39
  * @when The first thing in a record's row (32), at the head of its object page (64), in a feed or a sidebar identity line (24), on a Library entry (40), for the company at the top of Nadia's list (28): wherever it tells a person which thing they are looking at.
41
40
  * @instead An icon beside a card's title, a KPI's label or a section heading only repeats the words and is left out. A picture for a first use or a whole-page moment is the empty state's or the page's own. A model is its `ModelIdentity`; a maker's mark beside a model's name in a list of models is `ModelMark` at 24.
42
- * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with its own object picture, such as a Library skill or plugin, draws that picture on its kind's ground; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a Library skill takes the purple category ground with the Skills icon and a plugin the `info-soft` ground with the Plugins icon, both without a ring, so the ground says which kind it is, and an entry that has its own object picture draws it on that ground in the icon's place. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
41
+ * @behaviour Static, except an Agent's orb, which moves with her state. An Agent is always her real orb from the orb engine, at the largest orb size not above the mark's, with no tile and no ring, never an avatar or a painted circle, and `frame` lets the product wrap that orb, such as in the transition that carries her to her page; an app keeps its own logo in its bordered tile on the page ground, or its first letter when it has no logo; a record that belongs to a model maker, such as a key held at that maker, is the maker's `ModelMark` at the mark's size, with its initials when LobeHub has no mark for it; a company is its own logo, contained whole in its original colours and proportions on a dark ringed tile, as Vercel shows a project's favicon, and until a logo is found, or when the stored logo does not load, its initials in white on that same tile, so a found logo only replaces the letters; a company's mark is the same whatever its standing and whichever directory opened it, and a Partner is said in words where its standing matters, never by a colour; a person is their picture, then their initials, in a round mark; a record with no picture of its own takes its kind's own icon, the same icon its section has in the navigation (Mail for a mailbox, a server for an MCP server, a key for a password), in a ringed tile on the card ground; a skill takes the icon its hub card names, and the Skills icon when it names none, on that same neutral ringed tile, so the icon alone tells one skill from another and no colour stands for the kind; a plugin takes the `info-soft` ground with the Plugins icon, without a ring; a record's own object picture, such as a Library skill's or plugin's, is drawn only at 64, at the head of its own page, on its kind's ground in the icon's place, because at a row's size its detail does not read. A record tile takes `{rounded.sm}` (6 px) corners, `{rounded.md}` (8 px) at 40 and 64; a company's tile and an app's tile take `{rounded.md}` at every size.
43
42
  * @words None of its own: the record's name stands beside it. Initials stand for a company or a person: the first letters of the name's first two words. An app with no logo takes the first letter of its name as a monogram, a model maker with no mark the initials of its slug, and no other kind takes letters.
44
43
  * @access Decorative beside the record's name. Alone, as in a narrow rail, `label` names it.
45
44
  */
@@ -60,6 +59,6 @@ export function IdentityMark(props) {
60
59
  case "company":
61
60
  return (_jsx(CompanyMark, { initialsSize: measures.initials, logo: props.logo, name: props.name, naming: naming(props.label), size: size }));
62
61
  case "record":
63
- return (_jsx(RecordTile, { label: props.label, size: size, tone: props.tone ?? "neutral", children: props.picture ? (_jsx("img", { alt: "", className: "size-[84%] object-contain", "data-slot": "identity-mark-picture", src: props.picture })) : (_jsx(props.icon, { "aria-hidden": "true", size: measures.icon })) }));
62
+ return (_jsx(RecordTile, { label: props.label, size: size, tone: props.tone ?? "neutral", children: props.picture && size === 64 ? (_jsx("img", { alt: "", className: "size-[84%] object-contain", "data-slot": "identity-mark-picture", src: props.picture })) : (_jsx(props.icon, { "aria-hidden": "true", size: measures.icon })) }));
64
63
  }
65
64
  }
@@ -6,9 +6,9 @@ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } fro
6
6
  import { Button } from "./button.js";
7
7
  import { cn } from "../lib/utils.js";
8
8
  const viewportAxis = {
9
- y: "overflow-x-hidden! [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent)]",
10
- x: "overflow-y-hidden! [mask-image:linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
11
- both: "[mask-composite:intersect] [mask-image:linear-gradient(to_bottom,transparent,black_min(2.5rem,var(--scroll-area-overflow-y-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-y-end,0px))),transparent),linear-gradient(to_right,transparent,black_min(2.5rem,var(--scroll-area-overflow-x-start,0px)),black_calc(100%_-_min(2.5rem,var(--scroll-area-overflow-x-end,0px))),transparent)]",
9
+ y: "overflow-x-hidden! data-overflow-y-start:[mask-image:linear-gradient(to_bottom,transparent,black_2.5rem)] data-overflow-y-end:[mask-image:linear-gradient(to_top,transparent,black_2.5rem)] data-overflow-y-start:data-overflow-y-end:[mask-image:linear-gradient(to_bottom,transparent,black_2.5rem,black_calc(100%_-_2.5rem),transparent)]",
10
+ x: "overflow-y-hidden! data-overflow-x-start:[mask-image:linear-gradient(to_right,transparent,black_2.5rem)] data-overflow-x-end:[mask-image:linear-gradient(to_left,transparent,black_2.5rem)] data-overflow-x-start:data-overflow-x-end:[mask-image:linear-gradient(to_right,transparent,black_2.5rem,black_calc(100%_-_2.5rem),transparent)]",
11
+ both: "[--fade-x:linear-gradient(black,black)] [--fade-y:linear-gradient(black,black)] data-overflow-x-start:[--fade-x:linear-gradient(to_right,transparent,black_2.5rem)] data-overflow-x-end:[--fade-x:linear-gradient(to_left,transparent,black_2.5rem)] data-overflow-x-start:data-overflow-x-end:[--fade-x:linear-gradient(to_right,transparent,black_2.5rem,black_calc(100%_-_2.5rem),transparent)] data-overflow-y-start:[--fade-y:linear-gradient(to_bottom,transparent,black_2.5rem)] data-overflow-y-end:[--fade-y:linear-gradient(to_top,transparent,black_2.5rem)] data-overflow-y-start:data-overflow-y-end:[--fade-y:linear-gradient(to_bottom,transparent,black_2.5rem,black_calc(100%_-_2.5rem),transparent)] [mask-composite:intersect] [mask-image:var(--fade-y),var(--fade-x)]",
12
12
  };
13
13
  function scrollToNeighbour(viewport, content, axis, direction) {
14
14
  const edges = (box) => axis === "y" ? { start: box.top, end: box.bottom } : { start: box.left, end: box.right };
@@ -81,7 +81,7 @@ export type SavingSettingsSectionProps = SettingsSectionBase & SavingSection;
81
81
  * @family Compositions
82
82
  * @when One setting a person changes on a SettingsPage or as a section of an ObjectPage: Personal details, Company identity, Notifications. A typed value takes `save`; a switch or a short reversible choice applies at once through its own control's change, with no Save. Also a plan-gated feature, a delete card, one read-only value (an ID in a read-only mono InputGroup with its copy button, no Save), and a paid quantity (its stepper field, the price as the description, a two-fact summary under it).
83
83
  * @instead Read-only facts of an object are a SettingsFactsSection; a table or a list of records is a TableCard; Theme and Language live in the account menu; a record's edit in a list is a RowEditForm.
84
- * @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card: a single SettingsField, the description its only help. A typed value (a name, a URL, a server, a port, a key) gets its own card. A semantic subgroup of related controls inside a field, such as radios or checkboxes, is a `FieldSet` with a `FieldLegend`. One more shape exists, declared by a part and never by classes at the call site. A card of several settings holds SettingsRows, label left and control right, only when every row is a switch or every row is a select. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. A switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone, and when the title's longest word would not fit beside them they move under the title, so they never cover it. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with its own Save in the footer, always visible. The section owns the changed state: Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled, with no saved state in the footer. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it, the line saying the condition in words; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` (red) for a permanent loss (Delete), `warning` (amber) for a disruptive command that can be undone (Pause, Archive). A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` (Geist's disabled wall) is the reason, written as the footer's line, not in a tooltip; it keeps the fields in view, inert with muted text, under a not-allowed cursor, the title and line unchanged; `unlock` is the way to get access, left out when nothing the person does unlocks it. A locked section has no `save` and no header `actions`.
84
+ * @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card, a single SettingsField with the description its only help, unless the card's description covers several settings: then they are its SettingsRows, switches and selects together. A typed value (a name, a URL, a server, a port, a key) gets its own card. A semantic subgroup of related controls inside a field, such as radios or checkboxes, is a `FieldSet` with a `FieldLegend`. Several settings in one card are declared by SettingsRows, never by classes at the call site. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. A switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone, and when the title's longest word would not fit beside them they move under the title, so they never cover it. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with its own Save in the footer, always visible. The section owns the changed state: Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled, with no saved state in the footer. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it, the line saying the condition in words; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` (red) for a permanent loss (Delete), `warning` (amber) for a disruptive command that can be undone (Pause, Archive). A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` (Geist's disabled wall) is the reason, written as the footer's line, not in a tooltip; it keeps the fields in view, inert with muted text, under a not-allowed cursor, the title and line unchanged; `unlock` is the way to get access, left out when nothing the person does unlocks it. A locked section has no `save` and no header `actions`.
85
85
  * @words "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input) Ours: the description is that helper text for the whole card, and no field has its own. "Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation." (https://vercel.com/geist/toggle) Ours: a header-switch card's description says what turning it on does. The title names the values ("Personal details"); the description says what changing them does, in one line; the footer line is a Learn more link, a limit ("Use 32 characters at most."), what stays unaffected, or what is blocked and why ("Ask an owner to change this."); Save and Saving come from the product's catalogue, and so does the toast a `saved` callback raises; a delete card's description opens "Permanently delete".
86
86
  * @access "Provide an accessible name through `children`, `aria-label`, or `aria-labelledby`." (https://vercel.com/geist/toggle) Ours: the title is the section's h2 and names the form that saves it, and the header switch. The footer's line is one status, announced politely; a failure under a field marks the control invalid and describes it. Locked fields are inert, so the section's title, description and reason are what a screen reader meets.
87
87
  */
@@ -120,7 +120,7 @@ type SettingsFieldProps = SettingsFieldBase & ({
120
120
  *
121
121
  * @family Inputs
122
122
  * @when The one value of a SettingsSection: a name, an address, a choice, a switch.
123
- * @instead A field of a drawer's or a dialog's form is a Field from the form's own owner; a read-only fact is a SettingsFactsSection; several switches or selects in one card are SettingsRows; a switch that is the whole card and applies at once is the section's `headerSwitch`.
123
+ * @instead A field of a drawer's or a dialog's form is a Field from the form's own owner; a read-only fact is a SettingsFactsSection; several switches and selects in one card are SettingsRows; a switch that is the whole card and applies at once is the section's `headerSwitch`.
124
124
  * @behaviour "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input) Ours: label required, no help line: the card's description helps, and the (i) `info` is for a part of a value that needs a sentence. The control is 20rem wide under its label (`controlWidth`: `full` for a textarea, `natural` for a segmented control). `control="choice"` puts a checkbox or radio before its sentence; `control="switch"` puts the word for the switch's state after it and requires `stateLabel`. "Validate on blur, not on every keystroke; surface the message by passing a string to `error`." (https://vercel.com/geist/input) Ours: a validation `error` updates as the value is corrected, and it or a failed save about this field shows under the control and marks it invalid; colour sits on the control's edge and the message, never the label.
125
125
  * @words "Labels are short Title Case nouns: `Project Name`, `Domain`, `Environment Variable Name`." (https://vercel.com/geist/input) Ours: sentence case, a noun for the value ("Display name"). "Validation names the field and the constraint, ends in a period, and skips `please` (`Project name is required.`, `Code must be 6 digits.`)." (https://vercel.com/geist/input) Ours: an error says what to do next; `info.text` is one sentence and `info.label` names its button ("About display name"); a switch shows its state word ("Enabled", "Disabled") beside it.
126
126
  * @access "Don’t wrap a labelled `<Input>` in a `Tooltip`; put the explainer on a sibling icon button so the label stays announced." (https://vercel.com/geist/input) Ours: that sibling button is the (i) `info`. The control receives its id, `aria-invalid` and `aria-describedby` through `controlProps`, so the label, the info and the error are read with it. The info button has its own name and opens on focus.
@@ -138,6 +138,8 @@ type SettingsRowBase = {
138
138
  type SettingsSwitchRow = SettingsRowBase & {
139
139
  checked: boolean;
140
140
  onCheckedChange: (checked: boolean) => void;
141
+ options?: never;
142
+ control?: never;
141
143
  };
142
144
  type SettingsSelectRow = SettingsRowBase & {
143
145
  value: string;
@@ -146,30 +148,39 @@ type SettingsSelectRow = SettingsRowBase & {
146
148
  value: string;
147
149
  label: string;
148
150
  }[];
151
+ checked?: never;
152
+ control?: never;
153
+ };
154
+ type SettingsControlRow = SettingsRowBase & {
155
+ /** A control whose usage page puts it in a settings row, such as ThemeModeSwitcher. */
156
+ control: (props: {
157
+ controlProps: SettingsFieldControlProps;
158
+ }) => React.ReactNode;
159
+ options?: never;
160
+ checked?: never;
161
+ };
162
+ type StateLabels = {
163
+ on: string;
164
+ off: string;
149
165
  };
150
166
  type SettingsRowsProps = {
151
- kind: "switch";
152
167
  /** The word beside each switch for its state: "Enabled" and "Disabled". */
153
- stateLabels: {
154
- on: string;
155
- off: string;
156
- };
157
- rows: readonly SettingsSwitchRow[];
168
+ stateLabels: StateLabels;
169
+ rows: readonly (SettingsSwitchRow | SettingsSelectRow | SettingsControlRow)[];
158
170
  } | {
159
- kind: "select";
160
171
  stateLabels?: never;
161
- rows: readonly SettingsSelectRow[];
172
+ rows: readonly (SettingsSelectRow | SettingsControlRow)[];
162
173
  };
163
174
  /**
164
- * Several switches, or several selects, in one card: each row its label on the left and its control on the right.
175
+ * Several switches and selects in one card: each row its label on the left and its control on the right.
165
176
  *
166
177
  * @family Inputs
167
- * @when A card of settings of one kind, all switches or all selects, that the card's one description covers: a project's Git switches, a team's notification channels, a set of defaults.
168
- * @instead One setting is a SettingsField. Fields of different kinds, text boxes among them, are one card each.
169
- * @behaviour Declares `kind` once; every row is that kind, so a card cannot mix a switch with a select. Required on every row: the label and its `info` (an (i) with its sentence in a tooltip and on the control); no help line sits under a row. A switch row shows its state word beside the switch (`stateLabels`) and is controlled, so the word always follows the switch. Rows stand 16 px apart; below 28rem a row stacks its control under its label. "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) Ours: a switch is a draft the card's Save applies.
178
+ * @when A card of switches and selects that the card's one description covers: a project's Git switches, a team's notification channels, a set of defaults, how long a computer stays awake beside whether the window goes to the tray.
179
+ * @instead One setting is a SettingsField. A text box is a field of its own card.
180
+ * @behaviour A row with `options` is a select, a row with `checked` a switch, and a row with `control` draws a control whose usage page puts it in a row, such as ThemeModeSwitcher; a card may hold any of them together, as Vercel's Root Directory card holds its switches; `stateLabels` is required once any row is a switch. Required on every row: the label and its `info` (an (i) with its sentence in a tooltip and on the control); no help line sits under a row. A switch row shows its state word beside the switch (`stateLabels`) and is controlled, so the word always follows the switch. Rows stand 16 px apart; below 28rem a row stacks its control under its label. "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) Ours: a switch is a draft the card's Save applies.
170
181
  * @words "Title Case noun phrase, 1–4 words, naming what is true when ON: `Password Protection`, not `Enable Password Protection`." (https://vercel.com/geist/toggle) Ours: sentence case, a noun for what it controls ("Pull request comments"), the same for a switch as for a select. "Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation." (https://vercel.com/geist/toggle) Ours: that sentence is `info.text`. "Options are Title Case when short and match canonical branding (`Next.js`, not `NextJS`); keep the same register across the list." (https://vercel.com/geist/select) Ours: a select's options are sentence case.
171
182
  * @access Each row's control is named by the row's label and described by its info and its error. The info button has its own name and opens on focus.
172
183
  */
173
- declare function SettingsRows(props: SettingsRowsProps): React.JSX.Element;
184
+ declare function SettingsRows({ rows, stateLabels }: SettingsRowsProps): React.JSX.Element;
174
185
  export { SettingsField, SettingsRows, SettingsSection };
175
186
  //# sourceMappingURL=settings-section.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings-section.d.ts","sourceRoot":"","sources":["../../src/components/settings-section.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"settings-section.d.ts","sourceRoot":"","sources":["../../src/components/settings-section.tsx"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ const ACTIONS_ON_TITLE_ROW_WHEN_NARROW = "@max-md/settings-section:flex @max-md/
26
26
  * @family Compositions
27
27
  * @when One setting a person changes on a SettingsPage or as a section of an ObjectPage: Personal details, Company identity, Notifications. A typed value takes `save`; a switch or a short reversible choice applies at once through its own control's change, with no Save. Also a plan-gated feature, a delete card, one read-only value (an ID in a read-only mono InputGroup with its copy button, no Save), and a paid quantity (its stepper field, the price as the description, a two-fact summary under it).
28
28
  * @instead Read-only facts of an object are a SettingsFactsSection; a table or a list of records is a TableCard; Theme and Language live in the account menu; a record's edit in a list is a RowEditForm.
29
- * @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card: a single SettingsField, the description its only help. A typed value (a name, a URL, a server, a port, a key) gets its own card. A semantic subgroup of related controls inside a field, such as radios or checkboxes, is a `FieldSet` with a `FieldLegend`. One more shape exists, declared by a part and never by classes at the call site. A card of several settings holds SettingsRows, label left and control right, only when every row is a switch or every row is a select. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. A switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone, and when the title's longest word would not fit beside them they move under the title, so they never cover it. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with its own Save in the footer, always visible. The section owns the changed state: Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled, with no saved state in the footer. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it, the line saying the condition in words; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` (red) for a permanent loss (Delete), `warning` (amber) for a disruptive command that can be undone (Pause, Archive). A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` (Geist's disabled wall) is the reason, written as the footer's line, not in a tooltip; it keeps the fields in view, inert with muted text, under a not-allowed cursor, the title and line unchanged; `unlock` is the way to get access, left out when nothing the person does unlocks it. A locked section has no `save` and no header `actions`.
29
+ * @behaviour "Groups related form controls inside a bordered card with optional footer actions." (https://vercel.com/geist/fieldset) Ours: one setting per card, a single SettingsField with the description its only help, unless the card's description covers several settings: then they are its SettingsRows, switches and selects together. A typed value (a name, a URL, a server, a port, a key) gets its own card. A semantic subgroup of related controls inside a field, such as radios or checkboxes, is a `FieldSet` with a `FieldLegend`. Several settings in one card are declared by SettingsRows, never by classes at the call site. "Use Toggle for a single boolean setting where ON takes effect immediately, like `Password Protection` or `Auto-Cancel Builds`." (https://vercel.com/geist/toggle) "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) "Disable Toggle only when the action is impossible (missing plan, locked policy); pair with helper text or a `Tooltip` that names the resolver." (https://vercel.com/geist/toggle) Ours: a switch never applies on change; it is a row of the card, a draft until the footer's Save, as Vercel's settings cards are. A switch blocked from above is shown off and disabled, the footer saying why and never a tooltip. Required: the title and the description. The header's actions stand at the title's right; on a card narrower than 28 rem they keep the title's row and the description runs under both, as Vercel's cards read on a phone, and when the title's longest word would not fit beside them they move under the title, so they never cover it. The footer's left line (`footerHint`, `save.hint`) is optional and specific to the card, never a generic line repeated on every card: a limit, what a value is for, a plan it needs, a link; absent, it is nothing, and a card with neither a line nor a button has no footer. Ours: `save`: a typed value, one card with its own Save in the footer, always visible. The section owns the changed state: Save stays disabled until a field differs from what is saved and says `pendingLabel` while saving with Cancel beside it; a completed save calls `saved`, and the product raises one toast from its catalogue ("Completion toasts follow `{Noun} {past-participle}`: `Blob deleted`, `Domain added`, `Environment variable saved`. Never include `successfully`; the action name implies it." https://vercel.com/geist/toast), and Save returns to disabled, with no saved state in the footer. Ours: the section never raises a toast itself. A failed save keeps every value and shows under its field, or above the footer when no field owns it. `tone` marks a state with a command (a failed payment, a trial ending): a 1px border and a footer tinted in the hue with its line in it, the line saying the condition in words; title, line, fields and buttons stay neutral, an outline secondary then a default primary. A button takes the hue of its command, not of the card: `destructive` (red) for a permanent loss (Delete), `warning` (amber) for a disruptive command that can be undone (Pause, Archive). A delete card is `tone="error"` with the object's summary as its body; an archive card is neutral with a `warning` button in the footer. "Use a Note for inline contextual feedback next to the field, card, or section it describes: a region change warning above a region picker, a rate-limit notice next to a usage gauge." (https://vercel.com/geist/note) "One Note per concept." (https://vercel.com/geist/note) Ours: a message about the fields inside is a MessageNotice in the body, the card staying neutral. "Disabled checkboxes still need a Tooltip naming the reason; a greyed box with no explanation reads as a bug." (https://vercel.com/geist/checkbox) Ours: `lockedReason` (Geist's disabled wall) is the reason, written as the footer's line, not in a tooltip; it keeps the fields in view, inert with muted text, under a not-allowed cursor, the title and line unchanged; `unlock` is the way to get access, left out when nothing the person does unlocks it. A locked section has no `save` and no header `actions`.
30
30
  * @words "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input) Ours: the description is that helper text for the whole card, and no field has its own. "Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation." (https://vercel.com/geist/toggle) Ours: a header-switch card's description says what turning it on does. The title names the values ("Personal details"); the description says what changing them does, in one line; the footer line is a Learn more link, a limit ("Use 32 characters at most."), what stays unaffected, or what is blocked and why ("Ask an owner to change this."); Save and Saving come from the product's catalogue, and so does the toast a `saved` callback raises; a delete card's description opens "Permanently delete".
31
31
  * @access "Provide an accessible name through `children`, `aria-label`, or `aria-labelledby`." (https://vercel.com/geist/toggle) Ours: the title is the section's h2 and names the form that saves it, and the header switch. The footer's line is one status, announced politely; a failure under a field marks the control invalid and describes it. Locked fields are inert, so the section's title, description and reason are what a screen reader meets.
32
32
  */
@@ -48,8 +48,8 @@ function controlPropsOf({ id, info, error, invalid, disabled, required, }) {
48
48
  .join(" ") || undefined,
49
49
  };
50
50
  }
51
- function SettingsFieldLabel({ id, label, info, }) {
52
- const fieldLabel = (_jsx(FieldLabel, { htmlFor: id, id: `${id}-label`, children: label }));
51
+ function SettingsFieldLabel({ id, label, info, beside = false, }) {
52
+ const fieldLabel = (_jsx(FieldLabel, { htmlFor: id, id: `${id}-label`, className: beside ? "text-xs font-medium text-foreground" : undefined, children: label }));
53
53
  if (!info)
54
54
  return fieldLabel;
55
55
  return (_jsxs("div", { className: "flex items-center gap-1", children: [fieldLabel, _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx(Button, { "aria-label": info.label, size: "icon-xs", variant: "ghost" }), children: _jsx(Info, { "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: info.text })] }), _jsx("span", { hidden: true, id: `${id}-info`, children: info.text })] }));
@@ -74,7 +74,7 @@ function controlCellClassName(control, controlWidth) {
74
74
  *
75
75
  * @family Inputs
76
76
  * @when The one value of a SettingsSection: a name, an address, a choice, a switch.
77
- * @instead A field of a drawer's or a dialog's form is a Field from the form's own owner; a read-only fact is a SettingsFactsSection; several switches or selects in one card are SettingsRows; a switch that is the whole card and applies at once is the section's `headerSwitch`.
77
+ * @instead A field of a drawer's or a dialog's form is a Field from the form's own owner; a read-only fact is a SettingsFactsSection; several switches and selects in one card are SettingsRows; a switch that is the whole card and applies at once is the section's `headerSwitch`.
78
78
  * @behaviour "Helper text is sentence case, one sentence with a trailing period, on a sibling element wired through `aria-describedby`." (https://vercel.com/geist/input) Ours: label required, no help line: the card's description helps, and the (i) `info` is for a part of a value that needs a sentence. The control is 20rem wide under its label (`controlWidth`: `full` for a textarea, `natural` for a segmented control). `control="choice"` puts a checkbox or radio before its sentence; `control="switch"` puts the word for the switch's state after it and requires `stateLabel`. "Validate on blur, not on every keystroke; surface the message by passing a string to `error`." (https://vercel.com/geist/input) Ours: a validation `error` updates as the value is corrected, and it or a failed save about this field shows under the control and marks it invalid; colour sits on the control's edge and the message, never the label.
79
79
  * @words "Labels are short Title Case nouns: `Project Name`, `Domain`, `Environment Variable Name`." (https://vercel.com/geist/input) Ours: sentence case, a noun for the value ("Display name"). "Validation names the field and the constraint, ends in a period, and skips `please` (`Project name is required.`, `Code must be 6 digits.`)." (https://vercel.com/geist/input) Ours: an error says what to do next; `info.text` is one sentence and `info.label` names its button ("About display name"); a switch shows its state word ("Enabled", "Disabled") beside it.
80
80
  * @access "Don’t wrap a labelled `<Input>` in a `Tooltip`; put the explainer on a sibling icon button so the label stays announced." (https://vercel.com/geist/input) Ours: that sibling button is the (i) `info`. The control receives its id, `aria-invalid` and `aria-describedby` through `controlProps`, so the label, the info and the error are read with it. The info button has its own name and opens on focus.
@@ -86,28 +86,35 @@ function SettingsField({ id, label, info, error, invalid = Boolean(error), disab
86
86
  const controlCell = (_jsxs("div", { "data-slot": "settings-field-control", className: cn("flex min-w-0", controlCellClassName(control, controlWidth)), children: [children({ controlProps }), control === "switch" ? _jsx("span", { className: "text-sm", children: stateLabel }) : null] }));
87
87
  return (_jsx("div", { "data-slot": "settings-field", "data-invalid": invalid ? true : undefined, className: "contents", children: _jsxs(Field, { "data-invalid": invalid ? true : undefined, "data-disabled": disabled ? true : undefined, orientation: beside ? "horizontal" : "vertical", className: cn("items-start", className), ...props, children: [beside ? controlCell : null, _jsxs(FieldContent, { children: [_jsx(SettingsFieldLabel, { id: id, label: label, info: info }), beside ? errors : null] }), beside ? null : controlCell, beside ? null : errors] }) }));
88
88
  }
89
- function SettingsRow({ id, label, info, error, disabled, children, }) {
89
+ function SettingsRow({ id, label, info, error, disabled, kind, children, }) {
90
90
  const invalid = Boolean(error);
91
91
  const controlProps = controlPropsOf({ id, info, error, invalid, disabled });
92
- return (_jsx("div", { "data-slot": "settings-row", "data-invalid": invalid ? true : undefined, className: "contents", children: _jsxs(Field, { "data-invalid": invalid ? true : undefined, "data-disabled": disabled ? true : undefined, orientation: "horizontal", className: "flex-wrap has-[>[data-slot=field-content]]:items-center", children: [_jsxs(FieldContent, { className: "flex-auto", children: [_jsx(SettingsFieldLabel, { id: id, label: label, info: info }), _jsx(SettingsFieldErrors, { id: id, error: error })] }), _jsx("div", { "data-slot": "settings-row-control", className: "flex items-center gap-2 group-data-[kind=select]/settings-rows:w-48 group-data-[kind=select]/settings-rows:max-w-full", children: children({ controlProps }) })] }) }));
92
+ return (_jsx("div", { "data-slot": "settings-row", "data-invalid": invalid ? true : undefined, className: "contents", children: _jsxs(Field, { "data-invalid": invalid ? true : undefined, "data-disabled": disabled ? true : undefined, orientation: "horizontal", className: "flex-wrap has-[>[data-slot=field-content]]:items-center", children: [_jsxs(FieldContent, { className: "flex-auto", children: [_jsx(SettingsFieldLabel, { id: id, label: label, info: info, beside: true }), _jsx(SettingsFieldErrors, { id: id, error: error })] }), _jsx("div", { "data-slot": "settings-row-control", "data-kind": kind, className: "flex items-center gap-2 data-[kind=control]:w-64 data-[kind=control]:max-w-full data-[kind=select]:w-48 data-[kind=select]:max-w-full", children: children({ controlProps }) })] }) }));
93
93
  }
94
94
  /**
95
- * Several switches, or several selects, in one card: each row its label on the left and its control on the right.
95
+ * Several switches and selects in one card: each row its label on the left and its control on the right.
96
96
  *
97
97
  * @family Inputs
98
- * @when A card of settings of one kind, all switches or all selects, that the card's one description covers: a project's Git switches, a team's notification channels, a set of defaults.
99
- * @instead One setting is a SettingsField. Fields of different kinds, text boxes among them, are one card each.
100
- * @behaviour Declares `kind` once; every row is that kind, so a card cannot mix a switch with a select. Required on every row: the label and its `info` (an (i) with its sentence in a tooltip and on the control); no help line sits under a row. A switch row shows its state word beside the switch (`stateLabels`) and is controlled, so the word always follows the switch. Rows stand 16 px apart; below 28rem a row stacks its control under its label. "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) Ours: a switch is a draft the card's Save applies.
98
+ * @when A card of switches and selects that the card's one description covers: a project's Git switches, a team's notification channels, a set of defaults, how long a computer stays awake beside whether the window goes to the tray.
99
+ * @instead One setting is a SettingsField. A text box is a field of its own card.
100
+ * @behaviour A row with `options` is a select, a row with `checked` a switch, and a row with `control` draws a control whose usage page puts it in a row, such as ThemeModeSwitcher; a card may hold any of them together, as Vercel's Root Directory card holds its switches; `stateLabels` is required once any row is a switch. Required on every row: the label and its `info` (an (i) with its sentence in a tooltip and on the control); no help line sits under a row. A switch row shows its state word beside the switch (`stateLabels`) and is controlled, so the word always follows the switch. Rows stand 16 px apart; below 28rem a row stacks its control under its label. "Pair with a form footer only when the setting needs an explicit `Save` step." (https://vercel.com/geist/toggle) Ours: a switch is a draft the card's Save applies.
101
101
  * @words "Title Case noun phrase, 1–4 words, naming what is true when ON: `Password Protection`, not `Enable Password Protection`." (https://vercel.com/geist/toggle) Ours: sentence case, a noun for what it controls ("Pull request comments"), the same for a switch as for a select. "Render an optional one-sentence description as a sibling under the label that explains ON only. Don’t describe OFF; it’s the negation." (https://vercel.com/geist/toggle) Ours: that sentence is `info.text`. "Options are Title Case when short and match canonical branding (`Next.js`, not `NextJS`); keep the same register across the list." (https://vercel.com/geist/select) Ours: a select's options are sentence case.
102
102
  * @access Each row's control is named by the row's label and described by its info and its error. The info button has its own name and opens on focus.
103
103
  */
104
- function SettingsRows(props) {
105
- return (_jsx("div", { "data-slot": "settings-rows", "data-kind": props.kind, className: "group/settings-rows flex flex-col gap-4", children: props.kind === "switch" ? switchRows(props.rows, props.stateLabels) : selectRows(props.rows) }));
104
+ function SettingsRows({ rows, stateLabels }) {
105
+ return (_jsx("div", { "data-slot": "settings-rows", className: "flex flex-col gap-4", children: rows.map((row) => {
106
+ if (row.control !== undefined)
107
+ return controlRow(row);
108
+ return row.options === undefined ? switchRow(row, stateLabels) : selectRow(row);
109
+ }) }));
106
110
  }
107
- function switchRows(rows, stateLabels) {
108
- return rows.map((row) => (_jsx(SettingsRow, { ...row, children: ({ controlProps }) => (_jsxs(_Fragment, { children: [_jsx(Switch, { ...controlProps, checked: row.checked, name: row.name, onCheckedChange: row.onCheckedChange, size: "md" }), _jsx("span", { className: "text-sm", children: row.checked ? stateLabels.on : stateLabels.off })] })) }, row.id)));
111
+ function switchRow(row, stateLabels) {
112
+ return (_jsx(SettingsRow, { kind: "switch", ...row, children: ({ controlProps }) => (_jsxs(_Fragment, { children: [_jsx(Switch, { ...controlProps, checked: row.checked, name: row.name, onCheckedChange: row.onCheckedChange, size: "md" }), _jsx("span", { className: "text-sm", children: row.checked ? stateLabels?.on : stateLabels?.off })] })) }, row.id));
109
113
  }
110
- function selectRows(rows) {
111
- return rows.map((row) => (_jsx(SettingsRow, { ...row, children: ({ controlProps }) => (_jsx(NativeSelect, { ...controlProps, name: row.name, onChange: (event) => row.onValueChange(event.target.value), value: row.value, children: row.options.map((option) => (_jsx(NativeSelectOption, { value: option.value, children: option.label }, option.value))) })) }, row.id)));
114
+ function controlRow(row) {
115
+ return (_jsx(SettingsRow, { kind: "control", ...row, children: row.control }, row.id));
116
+ }
117
+ function selectRow(row) {
118
+ return (_jsx(SettingsRow, { kind: "select", ...row, children: ({ controlProps }) => (_jsx(NativeSelect, { ...controlProps, name: row.name, onChange: (event) => row.onValueChange(event.target.value), value: row.value, children: row.options.map((option) => (_jsx(NativeSelectOption, { value: option.value, children: option.label }, option.value))) })) }, row.id));
112
119
  }
113
120
  export { SettingsField, SettingsRows, SettingsSection };
@@ -23,7 +23,8 @@ import { type ControlName } from "../internal/control-name.js";
23
23
  * named: `aria-label` or `aria-labelledby`, or an `id` that a `FieldLabel`'s `htmlFor` points at,
24
24
  * and a switch with none of them does not compile. A bare `Switch` is the 28 by 14 px track with an
25
25
  * 11 px thumb; `md` is 36 by 20 px and `lg` 40 by 24 px. Colour: off is the input grey, on is
26
- * ink, and a disabled switch turns grey, on or off, with a greyer thumb and no shadow. Space flips
26
+ * cobalto, the thumb white in both themes, and a disabled switch turns grey, on or off, with a
27
+ * greyer thumb and no shadow. Space flips
27
28
  * it. On a settings page it is a draft its card's footer Save applies, and the product's toast
28
29
  * confirms the save, in one of two places: in the card's body under its label, its state word after
29
30
  * it (`SettingsField`'s `control="switch"`); or at the end of a row of a card of several settings,
@@ -1 +1 @@
1
- {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../src/components/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,IAAW,EACX,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAC3B,WAAW,GAAG;IACZ,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B,+BAiBF;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../src/components/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGlE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,iBAAS,MAAM,CAAC,EACd,SAAS,EACT,IAAW,EACX,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAC3B,WAAW,GAAG;IACZ,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;CAC3B,+BAiBF;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -24,7 +24,8 @@ import { cn } from "../lib/utils.js";
24
24
  * named: `aria-label` or `aria-labelledby`, or an `id` that a `FieldLabel`'s `htmlFor` points at,
25
25
  * and a switch with none of them does not compile. A bare `Switch` is the 28 by 14 px track with an
26
26
  * 11 px thumb; `md` is 36 by 20 px and `lg` 40 by 24 px. Colour: off is the input grey, on is
27
- * ink, and a disabled switch turns grey, on or off, with a greyer thumb and no shadow. Space flips
27
+ * cobalto, the thumb white in both themes, and a disabled switch turns grey, on or off, with a
28
+ * greyer thumb and no shadow. Space flips
28
29
  * it. On a settings page it is a draft its card's footer Save applies, and the product's toast
29
30
  * confirms the save, in one of two places: in the card's body under its label, its state word after
30
31
  * it (`SettingsField`'s `control="switch"`); or at the end of a row of a card of several settings,
@@ -47,6 +48,6 @@ import { cn } from "../lib/utils.js";
47
48
  * both states; a missing name does not compile.
48
49
  */
49
50
  function Switch({ className, size = "sm", ...props }) {
50
- return (_jsx(SwitchPrimitive.Root, { "data-slot": "switch", "data-size": size, className: cn("nc-transition-paint peer group/switch relative inline-flex shrink-0 items-start rounded-full border border-transparent p-0 after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 aria-invalid:border-destructive data-[size=sm]:h-3.5 data-[size=sm]:w-7 data-[size=md]:h-5 data-[size=md]:w-9 data-[size=lg]:h-6 data-[size=lg]:w-10 data-checked:bg-primary data-unchecked:bg-input data-disabled:cursor-not-allowed data-disabled:data-checked:bg-input/50 [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: _jsx(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "pointer-events-none mt-px block rounded-full bg-background ring-0 nc-transition-transform not-data-disabled:nc-elevation-resting group-data-[size=sm]/switch:ml-px group-data-[size=sm]/switch:size-2.75 group-data-[size=md]/switch:size-4.25 group-data-[size=lg]/switch:ml-px group-data-[size=lg]/switch:size-5.25 group-data-[size=sm]/switch:data-checked:translate-x-3.5 group-data-[size=md]/switch:data-checked:translate-x-4.25 group-data-[size=lg]/switch:data-checked:translate-x-4 data-disabled:bg-muted data-unchecked:translate-x-0" }) }));
51
+ return (_jsx(SwitchPrimitive.Root, { "data-slot": "switch", "data-size": size, className: cn("nc-transition-paint peer group/switch relative inline-flex shrink-0 items-start rounded-full border border-transparent p-0 after:absolute after:top-1/2 after:left-1/2 after:size-touch-target after:-translate-x-1/2 after:-translate-y-1/2 aria-invalid:border-destructive data-[size=sm]:h-3.5 data-[size=sm]:w-7 data-[size=md]:h-5 data-[size=md]:w-9 data-[size=lg]:h-6 data-[size=lg]:w-10 data-checked:bg-primary data-unchecked:bg-input data-disabled:cursor-not-allowed data-disabled:data-checked:bg-input/50 [@media(hover:hover)_and_(pointer:fine)]:after:hidden", className), ...props, children: _jsx(SwitchPrimitive.Thumb, { "data-slot": "switch-thumb", className: "pointer-events-none mt-px block rounded-full bg-primary-foreground ring-0 nc-transition-transform not-data-disabled:nc-elevation-resting group-data-[size=sm]/switch:ml-px group-data-[size=sm]/switch:size-2.75 group-data-[size=md]/switch:size-4.25 group-data-[size=lg]/switch:ml-px group-data-[size=lg]/switch:size-5.25 group-data-[size=sm]/switch:data-checked:translate-x-3.5 group-data-[size=md]/switch:data-checked:translate-x-4.25 group-data-[size=lg]/switch:data-checked:translate-x-4 data-disabled:bg-muted data-unchecked:translate-x-0" }) }));
51
52
  }
52
53
  export { Switch };
@@ -23,7 +23,7 @@ export type ThemeModeSwitcherProps = Omit<React.ComponentProps<typeof RadioGroup
23
23
  * The three appearances side by side, each with its glyph and its name.
24
24
  *
25
25
  * @family Choices
26
- * @when An Appearance setting on a settings page, where the choice has room to show its names.
26
+ * @when An Appearance setting on a settings page, where the choice has room to show its names: its own field, or a row of a SettingsRows card, `compact`, beside settings of the same card.
27
27
  * @instead Inside a menu, the same choice is ThemeModeMenu; a choice that is not the appearance is a RadioGroup or a ToggleGroup.
28
28
  * @behaviour Exclusive: one mode is selected; on a settings card the choice is a draft the card's Save applies. The order is System, Light, Dark everywhere.
29
29
  * @words The setting's name, then each mode's name from the product's catalogue: "System", "Light", "Dark".
@@ -17,7 +17,7 @@ const themeModeIcons = {
17
17
  * The three appearances side by side, each with its glyph and its name.
18
18
  *
19
19
  * @family Choices
20
- * @when An Appearance setting on a settings page, where the choice has room to show its names.
20
+ * @when An Appearance setting on a settings page, where the choice has room to show its names: its own field, or a row of a SettingsRows card, `compact`, beside settings of the same card.
21
21
  * @instead Inside a menu, the same choice is ThemeModeMenu; a choice that is not the appearance is a RadioGroup or a ToggleGroup.
22
22
  * @behaviour Exclusive: one mode is selected; on a settings card the choice is a draft the card's Save applies. The order is System, Light, Dark everywhere.
23
23
  * @words The setting's name, then each mode's name from the product's catalogue: "System", "Light", "Dark".
@@ -10,6 +10,10 @@ export declare function stateSpeed(state: AgentOrbState, form: AgentOrbFigure, a
10
10
  gestureAge: (age: number) => number;
11
11
  settle: (age: number, delay?: number) => number;
12
12
  }): number;
13
+ export declare const ORB_FRAME_RATE: {
14
+ readonly resting: 15;
15
+ readonly busy: 30;
16
+ };
13
17
  /**
14
18
  * Reduced motion turns movement off and keeps opacity and colour, so a
15
19
  * thinking or working orb breathes between full ink and 0.45 over 1.6 s,
@@ -1 +1 @@
1
- {"version":3,"file":"agent-orb-motion.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb-motion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAc7F,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,UAE/C;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,cAAc,EACpB,GAAG,SAAI,EACP,MAAM;;;;;;sBA2Cc,MAAM;kBACV,MAAM;CA5CA,UAWvB;AAKD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAIlE;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,mBAAmB;;;;;;sBAgBnC,MAAM;kBACV,MAAM;EAGvB;AAUD,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,MAAM;;;;;;sBAjBc,MAAM;kBACV,MAAM;CAgBA,EACtB,OAAO,UAAQ;;;;;;EA+ChB;AA6ED,wBAAgB,WAAW,CACzB,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO;AACvB,mFAAmF;AACnF,GAAG,SAAI,EACP,MAAM;;;;;;sBAxJc,MAAM;kBACV,MAAM;CAuJA,EACtB,WAAW,SAA8B,QA4E1C"}
1
+ {"version":3,"file":"agent-orb-motion.d.ts","sourceRoot":"","sources":["../../src/internal/agent-orb-motion.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAc7F,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,UAE/C;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,cAAc,EACpB,GAAG,SAAI,EACP,MAAM;;;;;;sBA6Cc,MAAM;kBACV,MAAM;CA9CA,UAWvB;AAED,eAAO,MAAM,cAAc;;;CAAqC,CAAC;AAKjE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAIlE;AAED,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,mBAAmB;;;;;;sBAgBnC,MAAM;kBACV,MAAM;EAGvB;AAUD,wBAAgB,UAAU,CACxB,KAAK,EAAE,aAAa,EACpB,GAAG,EAAE,MAAM,EACX,MAAM;;;;;;sBAjBc,MAAM;kBACV,MAAM;CAgBA,EACtB,OAAO,UAAQ;;;;;;EA+ChB;AA6ED,wBAAgB,WAAW,CACzB,OAAO,EAAE,wBAAwB,EACjC,KAAK,EAAE,aAAa,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,MAAM,GAAG,OAAO;AACvB,mFAAmF;AACnF,GAAG,SAAI,EACP,MAAM;;;;;;sBAxJc,MAAM;kBACV,MAAM;CAuJA,EACtB,WAAW,SAA8B,QA4E1C"}
@@ -24,6 +24,7 @@ export function stateSpeed(state, form, age = 0, timing = defaultTiming) {
24
24
  };
25
25
  return speed[state] * nativeSpeed(form);
26
26
  }
27
+ export const ORB_FRAME_RATE = { resting: 15, busy: 30 };
27
28
  /** The breath's period, in seconds. */
28
29
  const BREATH_SECONDS = 1.6;
29
30
  /**
@@ -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"}