@hanzo/ui 8.27.45 → 8.27.47

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 (72) hide show
  1. package/dist/backends/gui/popover.cjs +7 -2
  2. package/dist/backends/gui/popover.d.ts +8 -1
  3. package/dist/backends/gui/popover.d.ts.map +1 -1
  4. package/dist/backends/gui/popover.js +7 -2
  5. package/dist/backends/gui/popover.js.map +1 -1
  6. package/dist/chat/Chat.cjs +7 -2
  7. package/dist/chat/Chat.d.ts +14 -1
  8. package/dist/chat/Chat.d.ts.map +1 -1
  9. package/dist/chat/Chat.js +7 -2
  10. package/dist/chat/Chat.js.map +1 -1
  11. package/dist/gallery.html +119 -5
  12. package/dist/glass.css +14 -0
  13. package/dist/marketing/Cta.cjs +9 -3
  14. package/dist/marketing/Cta.d.ts +7 -5
  15. package/dist/marketing/Cta.d.ts.map +1 -1
  16. package/dist/marketing/Cta.js +10 -4
  17. package/dist/marketing/Cta.js.map +1 -1
  18. package/dist/marketing/controls.cjs +112 -0
  19. package/dist/marketing/controls.d.ts +42 -0
  20. package/dist/marketing/controls.d.ts.map +1 -0
  21. package/dist/marketing/controls.js +108 -0
  22. package/dist/marketing/controls.js.map +1 -0
  23. package/dist/marketing/document.cjs +7 -0
  24. package/dist/marketing/document.d.ts +22 -0
  25. package/dist/marketing/document.d.ts.map +1 -0
  26. package/dist/marketing/document.js +5 -0
  27. package/dist/marketing/document.js.map +1 -0
  28. package/dist/marketing/host.cjs +39 -0
  29. package/dist/marketing/host.d.ts +21 -0
  30. package/dist/marketing/host.d.ts.map +1 -0
  31. package/dist/marketing/host.js +35 -0
  32. package/dist/marketing/host.js.map +1 -0
  33. package/dist/marketing/index.cjs +24 -1
  34. package/dist/marketing/index.d.ts +8 -2
  35. package/dist/marketing/index.d.ts.map +1 -1
  36. package/dist/marketing/index.js +7 -1
  37. package/dist/marketing/index.js.map +1 -1
  38. package/dist/marketing/loose.cjs +2 -0
  39. package/dist/marketing/loose.d.ts +41 -0
  40. package/dist/marketing/loose.d.ts.map +1 -0
  41. package/dist/marketing/loose.js +2 -0
  42. package/dist/marketing/loose.js.map +1 -0
  43. package/dist/marketing/pager.cjs +22 -0
  44. package/dist/marketing/pager.d.ts +22 -0
  45. package/dist/marketing/pager.d.ts.map +1 -0
  46. package/dist/marketing/pager.js +20 -0
  47. package/dist/marketing/pager.js.map +1 -0
  48. package/dist/marketing/pair.cjs +21 -0
  49. package/dist/marketing/pair.d.ts +22 -0
  50. package/dist/marketing/pair.d.ts.map +1 -0
  51. package/dist/marketing/pair.js +19 -0
  52. package/dist/marketing/pair.js.map +1 -0
  53. package/dist/marketing/run.cjs +28 -0
  54. package/dist/marketing/run.d.ts +33 -0
  55. package/dist/marketing/run.d.ts.map +1 -0
  56. package/dist/marketing/run.js +26 -0
  57. package/dist/marketing/run.js.map +1 -0
  58. package/dist/marketing/surface.cjs +76 -0
  59. package/dist/marketing/surface.d.ts +59 -0
  60. package/dist/marketing/surface.d.ts.map +1 -0
  61. package/dist/marketing/surface.js +70 -0
  62. package/dist/marketing/surface.js.map +1 -0
  63. package/dist/marketing/type.cjs +29 -2
  64. package/dist/marketing/type.d.ts +43 -4
  65. package/dist/marketing/type.d.ts.map +1 -1
  66. package/dist/marketing/type.js +24 -1
  67. package/dist/marketing/type.js.map +1 -1
  68. package/dist/styles/document.css +93 -0
  69. package/dist/styles/motion.css +52 -2
  70. package/dist/styles.css +118 -4
  71. package/dist/theme.css +66 -2
  72. package/package.json +3 -2
@@ -23,6 +23,9 @@ const slot_1 = require("./slot.cjs");
23
23
  const DEFAULT_OFFSET = 4;
24
24
  const DEFAULT_SIDE = 'bottom';
25
25
  const Publish = /* @__PURE__ */ (0, react_1.createContext)(null);
26
+ /** Whether the panel this one opened from is solid. A list opened inside a solid
27
+ * panel stands on the same ground, so the pair reads as one surface. */
28
+ const Solid = /* @__PURE__ */ (0, react_1.createContext)(false);
26
29
  function Popover({ offset = DEFAULT_OFFSET, placement, ...props }) {
27
30
  const [placed, setPlaced] = (0, react_1.useState)({});
28
31
  const publish = (0, react_1.useCallback)((p) => setPlaced((prev) => ({ ...prev, ...p })), []);
@@ -34,10 +37,12 @@ const PopoverAnchor = gui_1.Popover.Anchor;
34
37
  exports.PopoverAnchor = PopoverAnchor;
35
38
  const PopoverClose = gui_1.Popover.Close;
36
39
  exports.PopoverClose = PopoverClose;
37
- const PopoverContent = ({ sideOffset = DEFAULT_OFFSET, align, ...props }) => {
40
+ const PopoverContent = ({ sideOffset = DEFAULT_OFFSET, align, solid, ...props }) => {
38
41
  const themeName = (0, portal_theme_1.useThemeName)();
39
42
  const publish = (0, react_1.useContext)(Publish);
43
+ const inherited = (0, react_1.useContext)(Solid);
44
+ const opaque = solid ?? inherited;
40
45
  (0, react_1.useEffect)(() => publish?.({ offset: sideOffset, align }), [publish, sideOffset, align]);
41
- return ((0, jsx_runtime_1.jsx)(portal_theme_1.PortalTheme, { name: themeName, children: (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { ...(0, slot_1.slot)('popover-content'), bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$4", p: "$4", width: 288, ...props }) }));
46
+ return ((0, jsx_runtime_1.jsx)(Solid.Provider, { value: opaque, children: (0, jsx_runtime_1.jsx)(portal_theme_1.PortalTheme, { name: themeName, children: (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { ...(0, slot_1.slot)('popover-content'), ...(opaque ? { 'data-material': 'solid' } : null), bg: opaque ? 'var(--popover)' : '$panel', borderWidth: 1, borderColor: "$borderColor", rounded: "$4", p: "$4", width: 288, ...props }) }) }));
42
47
  };
43
48
  exports.PopoverContent = PopoverContent;
@@ -23,7 +23,14 @@ declare const PopoverClose: typeof GuiPopover.Close;
23
23
  export type PopoverContentProps = ComponentProps<typeof GuiPopover.Content> & {
24
24
  sideOffset?: number;
25
25
  align?: Align;
26
+ /**
27
+ * Stand on the opaque `--popover` ground instead of glass. For a panel over
28
+ * something that moves, such as a menu over a streaming transcript, where the
29
+ * text behind would read through the frost. It keeps the rung's shadow and
30
+ * lit edge, and any popover opened from inside it is solid too.
31
+ */
32
+ solid?: boolean;
26
33
  };
27
- declare const PopoverContent: ({ sideOffset, align, ...props }: PopoverContentProps) => import("react").JSX.Element;
34
+ declare const PopoverContent: ({ sideOffset, align, solid, ...props }: PopoverContentProps) => import("react").JSX.Element;
28
35
  export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose };
29
36
  //# sourceMappingURL=popover.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/popover.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,OAAO,CAAA;AAEd,OAAO,EAAS,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAM3C,YAAY,EAAE,KAAK,EAAE,CAAA;AAOrB,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAElG,iBAAS,OAAO,CAAC,EAAE,MAAuB,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,+BAY9E;AAED,QAAA,MAAM,cAAc,EAAE,OAAO,UAAU,CAAC,OAA4B,CAAA;AACpE,QAAA,MAAM,aAAa,EAAE,OAAO,UAAU,CAAC,MAA0B,CAAA;AACjE,QAAA,MAAM,YAAY,EAAE,OAAO,UAAU,CAAC,KAAwB,CAAA;AAE9D,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,CAAA;AAED,QAAA,MAAM,cAAc,oCAAsD,mBAAmB,gCAkB5F,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/popover.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,OAAO,CAAA;AAEd,OAAO,EAAS,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAM3C,YAAY,EAAE,KAAK,EAAE,CAAA;AAWrB,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,UAAU,CAAC,EAAE,QAAQ,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAElG,iBAAS,OAAO,CAAC,EAAE,MAAuB,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY,+BAY9E;AAED,QAAA,MAAM,cAAc,EAAE,OAAO,UAAU,CAAC,OAA4B,CAAA;AACpE,QAAA,MAAM,aAAa,EAAE,OAAO,UAAU,CAAC,MAA0B,CAAA;AACjE,QAAA,MAAM,YAAY,EAAE,OAAO,UAAU,CAAC,KAAwB,CAAA;AAE9D,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,OAAO,CAAC,GAAG;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,KAAK,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,CAAA;AAED,QAAA,MAAM,cAAc,2CAA6D,mBAAmB,gCAuBnG,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA"}
@@ -19,6 +19,9 @@ import { slot } from './slot.js';
19
19
  const DEFAULT_OFFSET = 4;
20
20
  const DEFAULT_SIDE = 'bottom';
21
21
  const Publish = /* @__PURE__ */ createContext(null);
22
+ /** Whether the panel this one opened from is solid. A list opened inside a solid
23
+ * panel stands on the same ground, so the pair reads as one surface. */
24
+ const Solid = /* @__PURE__ */ createContext(false);
22
25
  function Popover({ offset = DEFAULT_OFFSET, placement, ...props }) {
23
26
  const [placed, setPlaced] = useState({});
24
27
  const publish = useCallback((p) => setPlaced((prev) => ({ ...prev, ...p })), []);
@@ -27,11 +30,13 @@ function Popover({ offset = DEFAULT_OFFSET, placement, ...props }) {
27
30
  const PopoverTrigger = GuiPopover.Trigger;
28
31
  const PopoverAnchor = GuiPopover.Anchor;
29
32
  const PopoverClose = GuiPopover.Close;
30
- const PopoverContent = ({ sideOffset = DEFAULT_OFFSET, align, ...props }) => {
33
+ const PopoverContent = ({ sideOffset = DEFAULT_OFFSET, align, solid, ...props }) => {
31
34
  const themeName = useThemeName();
32
35
  const publish = useContext(Publish);
36
+ const inherited = useContext(Solid);
37
+ const opaque = solid ?? inherited;
33
38
  useEffect(() => publish?.({ offset: sideOffset, align }), [publish, sideOffset, align]);
34
- return (_jsx(PortalTheme, { name: themeName, children: _jsx(GuiPopover.Content, { ...slot('popover-content'), bg: "$panel", borderWidth: 1, borderColor: "$borderColor", rounded: "$4", p: "$4", width: 288, ...props }) }));
39
+ return (_jsx(Solid.Provider, { value: opaque, children: _jsx(PortalTheme, { name: themeName, children: _jsx(GuiPopover.Content, { ...slot('popover-content'), ...(opaque ? { 'data-material': 'solid' } : null), bg: opaque ? 'var(--popover)' : '$panel', borderWidth: 1, borderColor: "$borderColor", rounded: "$4", p: "$4", width: 288, ...props }) }) }));
35
40
  };
36
41
  export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor, PopoverClose };
37
42
  //# sourceMappingURL=popover.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","sourceRoot":"","sources":["../../../src/backends/gui/popover.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EACL,aAAa,EACb,WAAW,EACX,UAAU,EACV,SAAS,EACT,QAAQ,GAET,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EAAE,KAAK,EAAc,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE7B,MAAM,cAAc,GAAG,CAAC,CAAA;AACxB,MAAM,YAAY,GAAG,QAAQ,CAAA;AAO7B,MAAM,OAAO,GAAG,eAAe,CAAC,aAAa,CAA+B,IAAI,CAAC,CAAA;AAIjF,SAAS,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE,SAAS,EAAE,GAAG,KAAK,EAAgB;IAC7E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAS,EAAE,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACxF,OAAO,CACL,KAAC,OAAO,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YAC9B,KAAC,UAAU,IACT,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,EAC/B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,YAAY,EAAE,MAAM,CAAC,KAAK,CAAqB,KACzE,KAAK,GACT,GACe,CACpB,CAAA;AACH,CAAC;AAED,MAAM,cAAc,GAA8B,UAAU,CAAC,OAAO,CAAA;AACpE,MAAM,aAAa,GAA6B,UAAU,CAAC,MAAM,CAAA;AACjE,MAAM,YAAY,GAA4B,UAAU,CAAC,KAAK,CAAA;AAO9D,MAAM,cAAc,GAAG,CAAC,EAAE,UAAU,GAAG,cAAc,EAAE,KAAK,EAAE,GAAG,KAAK,EAAuB,EAAE,EAAE;IAC/F,MAAM,SAAS,GAAG,YAAY,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC,CAAA;IACnC,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAA;IACvF,OAAO,CACL,KAAC,WAAW,IAAC,IAAI,EAAE,SAAS,YAC1B,KAAC,UAAU,CAAC,OAAO,OACb,IAAI,CAAC,iBAAiB,CAAC,EAC3B,EAAE,EAAC,QAAQ,EACX,WAAW,EAAE,CAAC,EACd,WAAW,EAAC,cAAc,EAC1B,OAAO,EAAC,IAAI,EACZ,CAAC,EAAC,IAAI,EACN,KAAK,EAAE,GAAG,KACN,KAAK,GACT,GACU,CACf,CAAA;AACH,CAAC,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA"}
1
+ {"version":3,"file":"popover.js","sourceRoot":"","sources":["../../../src/backends/gui/popover.tsx"],"names":[],"mappings":"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"}
@@ -63,7 +63,7 @@ const words_1 = require("./words.cjs");
63
63
  * in exactly that direction: `Parts` reads `type` before it reads anything else.
64
64
  */
65
65
  const draw = (said) => typeof said === 'string' || said == null ? ((0, ink_1.ink)((0, words_1.words)(said))) : ((0, jsx_runtime_1.jsx)(Parts_1.Parts, { parts: said }));
66
- function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, onFiles, ...thread }) {
66
+ function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, center = false, composer, onFiles, ...thread }) {
67
67
  const [draft, setDraft] = (0, react_1.useState)('');
68
68
  // The ONE window-level drop, off the shared primitive. Enabled only when a
69
69
  // host passed `onFiles` — a surface that cannot route a file leaves the
@@ -80,6 +80,11 @@ function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, e
80
80
  onSend(text);
81
81
  }, [draft, onSend]);
82
82
  const last = messages.length - 1;
83
+ const opening = messages.length === 0 && Boolean(empty);
84
+ // The spacers hold their places in the child list whether or not they draw,
85
+ // so the composer keeps its position and its field keeps focus when the
86
+ // first turn arrives.
87
+ const centred = center && opening;
83
88
  // No `minHeight: 0` on the frame: rnw's View base and gui's stack base both
84
89
  // set it already, measured on the rendered element — and gui publishes no
85
90
  // such prop, so writing it type-errors rather than silently doing nothing,
@@ -90,7 +95,7 @@ function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, e
90
95
  // from the composer lands on a `display: contents` wrapper or on the page,
91
96
  // and then reports a component that is fine as broken, or one that is broken
92
97
  // as fine.
93
- return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, width: "100%", ...(0, slot_1.slot)('chat'), children: [messages.length === 0 && empty ? (empty) : ((0, jsx_runtime_1.jsx)(Thread_1.Thread, { flex: 1, ...thread, children: messages.map((turn, i) => ((0, jsx_runtime_1.jsx)(Message_1.Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), (0, jsx_runtime_1.jsx)(Composer_1.Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer }), dropping ? ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": true, style: {
98
+ return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, width: "100%", ...(0, slot_1.slot)('chat'), children: [centred ? (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('chat-space'), flex: 1 }) : null, opening ? (empty) : ((0, jsx_runtime_1.jsx)(Thread_1.Thread, { flex: 1, ...thread, children: messages.map((turn, i) => ((0, jsx_runtime_1.jsx)(Message_1.Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), (0, jsx_runtime_1.jsx)(Composer_1.Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer }), centred ? (0, jsx_runtime_1.jsx)(gui_1.YStack, { ...(0, slot_1.slot)('chat-space'), flex: 1 }) : null, dropping ? ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": true, style: {
94
99
  position: 'fixed',
95
100
  inset: 0,
96
101
  zIndex: 50,
@@ -58,6 +58,19 @@ export interface ChatProps extends Omit<ThreadProps, 'children' | 'ref'> {
58
58
  body?: (turn: Turn) => ReactNode;
59
59
  /** Shown instead of the thread while nothing has been said. */
60
60
  empty?: ReactNode;
61
+ /**
62
+ * While nothing has been said, `empty` and the composer sit together in the
63
+ * middle of the height, the free space split evenly above and below them.
64
+ * Once a turn exists the thread takes the height and the composer docks under
65
+ * it.
66
+ *
67
+ * The space is two spacers around the pair, not margins on it. With a `head`
68
+ * or `foot` the composer is a shell around its frame, and a margin passed in
69
+ * `composer` lands on the frame inside that shell, where it moves nothing.
70
+ * The spacers shrink to nothing when the pair is taller than the window, so
71
+ * the heading is never pushed above the top.
72
+ */
73
+ center?: boolean;
61
74
  /** The composer's own props — placeholder, hint, the send control, the field. */
62
75
  composer?: Partial<ComposerProps>;
63
76
  /**
@@ -72,5 +85,5 @@ export interface ChatProps extends Omit<ThreadProps, 'children' | 'ref'> {
72
85
  */
73
86
  onFiles?: (files: File[]) => void;
74
87
  }
75
- export declare function Chat({ messages, streaming, send: onSend, stop: onStop, body, empty, composer, onFiles, ...thread }: ChatProps): import("react").JSX.Element;
88
+ export declare function Chat({ messages, streaming, send: onSend, stop: onStop, body, empty, center, composer, onFiles, ...thread }: ChatProps): import("react").JSX.Element;
76
89
  //# sourceMappingURL=Chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAoCA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAK7D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAS,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,IAAI,CAAA;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC;IACtE,sCAAsC;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAA;IAChB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;IACjB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAA;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;IACjC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;CAClC;AAyBD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAiB,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,OAAO,EACP,GAAG,MAAM,EACV,EAAE,SAAS,+BA6EX"}
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAoCA,OAAO,EAAyB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAK7D,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AACzD,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAS,KAAK,IAAI,EAAE,MAAM,SAAS,CAAA;AAE1C;;;;;;;GAOG;AACH,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,IAAI,CAAA;CACf;AAED,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,KAAK,CAAC;IACtE,sCAAsC;IACtC,QAAQ,EAAE,IAAI,EAAE,CAAA;IAChB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;OAUG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;IACjB;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAA;IAChC,+DAA+D;IAC/D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;IACjC;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;CAClC;AAyBD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,SAAiB,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,MAAc,EACd,QAAQ,EACR,OAAO,EACP,GAAG,MAAM,EACV,EAAE,SAAS,+BAoFX"}
package/dist/chat/Chat.js CHANGED
@@ -60,7 +60,7 @@ import { words } from './words.js';
60
60
  * in exactly that direction: `Parts` reads `type` before it reads anything else.
61
61
  */
62
62
  const draw = (said) => typeof said === 'string' || said == null ? (ink(words(said))) : (_jsx(Parts, { parts: said }));
63
- export function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, composer, onFiles, ...thread }) {
63
+ export function Chat({ messages, streaming = false, send: onSend, stop: onStop, body, empty, center = false, composer, onFiles, ...thread }) {
64
64
  const [draft, setDraft] = useState('');
65
65
  // The ONE window-level drop, off the shared primitive. Enabled only when a
66
66
  // host passed `onFiles` — a surface that cannot route a file leaves the
@@ -77,6 +77,11 @@ export function Chat({ messages, streaming = false, send: onSend, stop: onStop,
77
77
  onSend(text);
78
78
  }, [draft, onSend]);
79
79
  const last = messages.length - 1;
80
+ const opening = messages.length === 0 && Boolean(empty);
81
+ // The spacers hold their places in the child list whether or not they draw,
82
+ // so the composer keeps its position and its field keeps focus when the
83
+ // first turn arrives.
84
+ const centred = center && opening;
80
85
  // No `minHeight: 0` on the frame: rnw's View base and gui's stack base both
81
86
  // set it already, measured on the rendered element — and gui publishes no
82
87
  // such prop, so writing it type-errors rather than silently doing nothing,
@@ -87,7 +92,7 @@ export function Chat({ messages, streaming = false, send: onSend, stop: onStop,
87
92
  // from the composer lands on a `display: contents` wrapper or on the page,
88
93
  // and then reports a component that is fine as broken, or one that is broken
89
94
  // as fine.
90
- return (_jsxs(YStack, { flex: 1, width: "100%", ...slot('chat'), children: [messages.length === 0 && empty ? (empty) : (_jsx(Thread, { flex: 1, ...thread, children: messages.map((turn, i) => (_jsx(Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), _jsx(Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer }), dropping ? (_jsx("div", { "aria-hidden": true, style: {
95
+ return (_jsxs(YStack, { flex: 1, width: "100%", ...slot('chat'), children: [centred ? _jsx(YStack, { ...slot('chat-space'), flex: 1 }) : null, opening ? (empty) : (_jsx(Thread, { flex: 1, ...thread, children: messages.map((turn, i) => (_jsx(Message, { role: turn.role, busy: streaming && i === last && turn.role === 'assistant', children: body ? body(turn) : draw(turn.content) }, turn.id))) })), _jsx(Composer, { value: draft, onChange: setDraft, onSend: send, busy: streaming, ...(onStop ? { onStop } : {}), ...composer }), centred ? _jsx(YStack, { ...slot('chat-space'), flex: 1 }) : null, dropping ? (_jsx("div", { "aria-hidden": true, style: {
91
96
  position: 'fixed',
92
97
  inset: 0,
93
98
  zIndex: 50,
@@ -1 +1 @@
1
- {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAE7D,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAA;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,QAAQ,EAAsB,MAAM,YAAY,CAAA;AACzD,OAAO,EAAE,OAAO,EAAa,MAAM,WAAW,CAAA;AAC9C,OAAO,EAAE,KAAK,EAAoB,MAAM,SAAS,CAAA;AACjD,OAAO,EAAE,MAAM,EAAoB,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,KAAK,EAAa,MAAM,SAAS,CAAA;AAyE1C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,IAAI,GAAG,CAAC,IAAU,EAAE,EAAE,CAC1B,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CACzC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CACjB,CAAC,CAAC,CAAC,CACF,KAAC,KAAK,IAAC,KAAK,EAAE,IAAqB,GAAI,CACxC,CAAA;AAEH,MAAM,UAAU,IAAI,CAAC,EACnB,QAAQ,EACR,SAAS,GAAG,KAAK,EACjB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,OAAO,EACP,GAAG,MAAM,EACC;IACV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEtC,2EAA2E;IAC3E,wEAAwE;IACxE,gDAAgD;IAChD,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;IAE1E,4EAA4E;IAC5E,yEAAyE;IACzE,iEAAiE;IACjE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,QAAQ,CAAC,EAAE,CAAC,CAAA;QACZ,MAAM,CAAC,IAAI,CAAC,CAAA;IACd,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAEnB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAA;IAEhC,4EAA4E;IAC5E,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,8EAA8E;IAC9E,gFAAgF;IAChF,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,WAAW;IACX,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,aAC3C,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAChC,KAAK,CACN,CAAC,CAAC,CAAC,CACF,KAAC,MAAM,IAAC,IAAI,EAAE,CAAC,KAAM,MAAM,YACxB,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACzB,KAAC,OAAO,IAEN,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,IAAI,EAAE,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,YAEzD,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAJlC,IAAI,CAAC,EAAE,CAKJ,CACX,CAAC,GACK,CACV,EACD,KAAC,QAAQ,IACP,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,IAAI,EACZ,IAAI,EAAE,SAAS,KACX,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAC1B,QAAQ,GACZ,EACD,QAAQ,CAAC,CAAC,CAAC,CACV,mCAEE,KAAK,EAAE;oBACL,QAAQ,EAAE,OAAO;oBACjB,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,EAAE;oBACV,OAAO,EAAE,MAAM;oBACf,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,QAAQ;oBACxB,aAAa,EAAE,MAAM;oBACrB,UAAU,EAAE,0BAA0B;oBACtC,MAAM,EAAE,oBAAoB;iBAC7B,YAED,eAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,qCAEzD,GACH,CACP,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"Chat.js","sourceRoot":"","sources":["../../src/chat/Chat.tsx"],"names":[],"mappings":"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"}
package/dist/gallery.html CHANGED
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.27.45</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
1
+ <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.27.47</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
2
2
  :root { --hanzo-ui-styles: 1; }
3
3
  /* Hanzo Design System — the entry point. Import THIS one file.
4
4
  *
@@ -1585,6 +1585,20 @@
1585
1585
  }
1586
1586
  }
1587
1587
 
1588
+ /* ── Solid — the one way out of the material ─────────────────────────────────
1589
+ A panel over something that moves (a menu over a streaming transcript) reads
1590
+ the motion through 72% frost. `<PopoverContent solid>` marks itself, and every
1591
+ popover opened from inside it, with `data-material="solid"`: the ground is
1592
+ design's opaque `--popover` and nothing behind is blurred into it. The rung's
1593
+ shadow, lit edge and prism lip stay, so it is the same surface at the same
1594
+ height with a solid fill. Declared after the material so the later rule wins
1595
+ between two !important declarations of equal weight. */
1596
+ [data-material="solid"] {
1597
+ background-color: var(--popover, #0f0f0f) !important;
1598
+ -webkit-backdrop-filter: none;
1599
+ backdrop-filter: none;
1600
+ }
1601
+
1588
1602
  /* ── Depth — three rungs, and the lit edge is the load-bearing half ──────────
1589
1603
  A cast shadow is how a light page shows lift. On a near-black canvas it is
1590
1604
  nearly free of information: black on near-black moves no pixels, so a raised
@@ -1805,13 +1819,15 @@
1805
1819
  itself. Every animation is off under `prefers-reduced-motion: reduce`.
1806
1820
 
1807
1821
  rise enter: fade up 10px over 400ms FadeIn, Timeline, tooltips
1822
+ `data-beat="n"` staggers it n x 70ms
1808
1823
  fade opacity eases 240ms SlideOver's scrim
1809
1824
  slide transform eases 260ms SlideOver's panel
1810
1825
  drag a row eases into place while one is held Reorder
1811
1826
  pulse opacity dims and returns, 2s Pulse, StatusDot, Skeleton
1812
1827
  blink on/off, 1s Caret
1813
1828
  shimmer a highlight sweeps a placeholder product Skeleton
1814
- unfold a sheet turns open about its hinge unfold() */
1829
+ unfold a sheet turns open about its hinge unfold()
1830
+ run a light sweeps a set, child by child Run */
1815
1831
 
1816
1832
  @keyframes rise {
1817
1833
  from {
@@ -1829,6 +1845,17 @@
1829
1845
  will-change: transform, opacity;
1830
1846
  }
1831
1847
 
1848
+ /* A staged entrance: `data-beat="n"` holds a rise back n beats of 70ms, so a set
1849
+ that arrives together still reads in order. Reduced motion drops the
1850
+ animation and the delay with it, so nothing waits hidden. */
1851
+ [data-motion='rise'][data-beat='1'] { animation-delay: 70ms; }
1852
+ [data-motion='rise'][data-beat='2'] { animation-delay: 140ms; }
1853
+ [data-motion='rise'][data-beat='3'] { animation-delay: 210ms; }
1854
+ [data-motion='rise'][data-beat='4'] { animation-delay: 280ms; }
1855
+ [data-motion='rise'][data-beat='5'] { animation-delay: 350ms; }
1856
+ [data-motion='rise'][data-beat='6'] { animation-delay: 420ms; }
1857
+ [data-motion='rise'][data-beat='7'] { animation-delay: 490ms; }
1858
+
1832
1859
  [data-motion='fade'] {
1833
1860
  transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
1834
1861
  will-change: opacity;
@@ -1909,8 +1936,45 @@
1909
1936
  --turn: 7deg;
1910
1937
  }
1911
1938
 
1939
+ /* A run: a light crosses a set of things that are all true at once (`<Run>`).
1940
+ Each direct child is lit `data-beat` steps of `--run-step` after the first;
1941
+ the sweep owns `color` and returns it to `--run-rest`. */
1942
+ @keyframes run {
1943
+ 0%,
1944
+ 26%,
1945
+ 100% {
1946
+ color: var(--run-rest, var(--neutral-400));
1947
+ border-color: var(--neutral-800);
1948
+ }
1949
+ 8% {
1950
+ color: var(--foreground);
1951
+ border-color: var(--muted-foreground);
1952
+ }
1953
+ }
1954
+
1955
+ [data-motion='run'] > * {
1956
+ animation: run 5.4s var(--ease-in-out) infinite;
1957
+ }
1958
+
1959
+ [data-motion='run'] > [data-beat='1'] { animation-delay: calc(1 * var(--run-step, 0.22s)); }
1960
+ [data-motion='run'] > [data-beat='2'] { animation-delay: calc(2 * var(--run-step, 0.22s)); }
1961
+ [data-motion='run'] > [data-beat='3'] { animation-delay: calc(3 * var(--run-step, 0.22s)); }
1962
+ [data-motion='run'] > [data-beat='4'] { animation-delay: calc(4 * var(--run-step, 0.22s)); }
1963
+ [data-motion='run'] > [data-beat='5'] { animation-delay: calc(5 * var(--run-step, 0.22s)); }
1964
+ [data-motion='run'] > [data-beat='6'] { animation-delay: calc(6 * var(--run-step, 0.22s)); }
1965
+ [data-motion='run'] > [data-beat='7'] { animation-delay: calc(7 * var(--run-step, 0.22s)); }
1966
+ [data-motion='run'] > [data-beat='8'] { animation-delay: calc(8 * var(--run-step, 0.22s)); }
1967
+ [data-motion='run'] > [data-beat='9'] { animation-delay: calc(9 * var(--run-step, 0.22s)); }
1968
+ [data-motion='run'] > [data-beat='10'] { animation-delay: calc(10 * var(--run-step, 0.22s)); }
1969
+ [data-motion='run'] > [data-beat='11'] { animation-delay: calc(11 * var(--run-step, 0.22s)); }
1970
+ [data-motion='run'] > [data-beat='12'] { animation-delay: calc(12 * var(--run-step, 0.22s)); }
1971
+ [data-motion='run'] > [data-beat='13'] { animation-delay: calc(13 * var(--run-step, 0.22s)); }
1972
+ [data-motion='run'] > [data-beat='14'] { animation-delay: calc(14 * var(--run-step, 0.22s)); }
1973
+ [data-motion='run'] > [data-beat='15'] { animation-delay: calc(15 * var(--run-step, 0.22s)); }
1974
+
1912
1975
  @media (prefers-reduced-motion: reduce) {
1913
- [data-motion] {
1976
+ [data-motion],
1977
+ [data-motion='run'] > * {
1914
1978
  animation: none;
1915
1979
  transition: none;
1916
1980
  }
@@ -2486,13 +2550,15 @@ a svg,
2486
2550
  itself. Every animation is off under `prefers-reduced-motion: reduce`.
2487
2551
 
2488
2552
  rise enter: fade up 10px over 400ms FadeIn, Timeline, tooltips
2553
+ `data-beat="n"` staggers it n x 70ms
2489
2554
  fade opacity eases 240ms SlideOver's scrim
2490
2555
  slide transform eases 260ms SlideOver's panel
2491
2556
  drag a row eases into place while one is held Reorder
2492
2557
  pulse opacity dims and returns, 2s Pulse, StatusDot, Skeleton
2493
2558
  blink on/off, 1s Caret
2494
2559
  shimmer a highlight sweeps a placeholder product Skeleton
2495
- unfold a sheet turns open about its hinge unfold() */
2560
+ unfold a sheet turns open about its hinge unfold()
2561
+ run a light sweeps a set, child by child Run */
2496
2562
 
2497
2563
  @keyframes rise {
2498
2564
  from {
@@ -2510,6 +2576,17 @@ a svg,
2510
2576
  will-change: transform, opacity;
2511
2577
  }
2512
2578
 
2579
+ /* A staged entrance: `data-beat="n"` holds a rise back n beats of 70ms, so a set
2580
+ that arrives together still reads in order. Reduced motion drops the
2581
+ animation and the delay with it, so nothing waits hidden. */
2582
+ [data-motion='rise'][data-beat='1'] { animation-delay: 70ms; }
2583
+ [data-motion='rise'][data-beat='2'] { animation-delay: 140ms; }
2584
+ [data-motion='rise'][data-beat='3'] { animation-delay: 210ms; }
2585
+ [data-motion='rise'][data-beat='4'] { animation-delay: 280ms; }
2586
+ [data-motion='rise'][data-beat='5'] { animation-delay: 350ms; }
2587
+ [data-motion='rise'][data-beat='6'] { animation-delay: 420ms; }
2588
+ [data-motion='rise'][data-beat='7'] { animation-delay: 490ms; }
2589
+
2513
2590
  [data-motion='fade'] {
2514
2591
  transition: opacity 240ms cubic-bezier(0.16, 1, 0.3, 1);
2515
2592
  will-change: opacity;
@@ -2590,8 +2667,45 @@ a svg,
2590
2667
  --turn: 7deg;
2591
2668
  }
2592
2669
 
2670
+ /* A run: a light crosses a set of things that are all true at once (`<Run>`).
2671
+ Each direct child is lit `data-beat` steps of `--run-step` after the first;
2672
+ the sweep owns `color` and returns it to `--run-rest`. */
2673
+ @keyframes run {
2674
+ 0%,
2675
+ 26%,
2676
+ 100% {
2677
+ color: var(--run-rest, var(--neutral-400));
2678
+ border-color: var(--neutral-800);
2679
+ }
2680
+ 8% {
2681
+ color: var(--foreground);
2682
+ border-color: var(--muted-foreground);
2683
+ }
2684
+ }
2685
+
2686
+ [data-motion='run'] > * {
2687
+ animation: run 5.4s var(--ease-in-out) infinite;
2688
+ }
2689
+
2690
+ [data-motion='run'] > [data-beat='1'] { animation-delay: calc(1 * var(--run-step, 0.22s)); }
2691
+ [data-motion='run'] > [data-beat='2'] { animation-delay: calc(2 * var(--run-step, 0.22s)); }
2692
+ [data-motion='run'] > [data-beat='3'] { animation-delay: calc(3 * var(--run-step, 0.22s)); }
2693
+ [data-motion='run'] > [data-beat='4'] { animation-delay: calc(4 * var(--run-step, 0.22s)); }
2694
+ [data-motion='run'] > [data-beat='5'] { animation-delay: calc(5 * var(--run-step, 0.22s)); }
2695
+ [data-motion='run'] > [data-beat='6'] { animation-delay: calc(6 * var(--run-step, 0.22s)); }
2696
+ [data-motion='run'] > [data-beat='7'] { animation-delay: calc(7 * var(--run-step, 0.22s)); }
2697
+ [data-motion='run'] > [data-beat='8'] { animation-delay: calc(8 * var(--run-step, 0.22s)); }
2698
+ [data-motion='run'] > [data-beat='9'] { animation-delay: calc(9 * var(--run-step, 0.22s)); }
2699
+ [data-motion='run'] > [data-beat='10'] { animation-delay: calc(10 * var(--run-step, 0.22s)); }
2700
+ [data-motion='run'] > [data-beat='11'] { animation-delay: calc(11 * var(--run-step, 0.22s)); }
2701
+ [data-motion='run'] > [data-beat='12'] { animation-delay: calc(12 * var(--run-step, 0.22s)); }
2702
+ [data-motion='run'] > [data-beat='13'] { animation-delay: calc(13 * var(--run-step, 0.22s)); }
2703
+ [data-motion='run'] > [data-beat='14'] { animation-delay: calc(14 * var(--run-step, 0.22s)); }
2704
+ [data-motion='run'] > [data-beat='15'] { animation-delay: calc(15 * var(--run-step, 0.22s)); }
2705
+
2593
2706
  @media (prefers-reduced-motion: reduce) {
2594
- [data-motion] {
2707
+ [data-motion],
2708
+ [data-motion='run'] > * {
2595
2709
  animation: none;
2596
2710
  transition: none;
2597
2711
  }
package/dist/glass.css CHANGED
@@ -115,6 +115,20 @@
115
115
  }
116
116
  }
117
117
 
118
+ /* ── Solid — the one way out of the material ─────────────────────────────────
119
+ A panel over something that moves (a menu over a streaming transcript) reads
120
+ the motion through 72% frost. `<PopoverContent solid>` marks itself, and every
121
+ popover opened from inside it, with `data-material="solid"`: the ground is
122
+ design's opaque `--popover` and nothing behind is blurred into it. The rung's
123
+ shadow, lit edge and prism lip stay, so it is the same surface at the same
124
+ height with a solid fill. Declared after the material so the later rule wins
125
+ between two !important declarations of equal weight. */
126
+ [data-material="solid"] {
127
+ background-color: var(--popover, #0f0f0f) !important;
128
+ -webkit-backdrop-filter: none;
129
+ backdrop-filter: none;
130
+ }
131
+
118
132
  /* ── Depth — three rungs, and the lit edge is the load-bearing half ──────────
119
133
  A cast shadow is how a light page shows lift. On a near-black canvas it is
120
134
  nearly free of information: black on near-black moves no pixels, so a raised
@@ -19,8 +19,14 @@ const slot_1 = require("../backends/gui/slot.cjs");
19
19
  const Cta = ({ href, children, quiet = false, ...p }) => ((0, jsx_runtime_1.jsx)(gui_1.Anchor, { ...(0, slot_1.slot)(quiet ? 'cta-quiet' : 'cta'), href: href, display: "inline-flex", items: "center", justify: "center", minH: 44, px: "$5", rounded: "$4", borderWidth: 1, borderColor: quiet ? '$borderColor' : 'transparent', bg: quiet ? 'transparent' : 'var(--primary)', color: quiet ? '$ink' : 'var(--primary-foreground)', fontSize: "$4", fontWeight: "500", text: "center", textDecorationLine: "none", hoverStyle: quiet ? { bg: '$hover' } : { bg: 'var(--primary-hover)' }, ...p, children: children }));
20
20
  exports.Cta = Cta;
21
21
  /**
22
- * TextLink — a link inside a sentence: the surrounding ink, underlined.
23
- * `Cta` is the control; this is the word.
22
+ * TextLink — a link inside a sentence: full ink and an underline, because in
23
+ * quiet text colour alone does not say "link", and the sentence's own face and
24
+ * size. `Cta` is the control; this is the word. A button inside such a sentence (no `href`) reads as one of its
25
+ * links: no box, and the sentence's own face, which @hanzo/design's base hands
26
+ * every button.
24
27
  */
25
- const TextLink = ({ href, children, ...p }) => ((0, jsx_runtime_1.jsx)(gui_1.Anchor, { ...(0, slot_1.slot)('text-link'), href: href, color: "$ink", textDecorationLine: "underline", style: { textUnderlineOffset: 3 }, ...p, children: children }));
28
+ /** The sentence's own type, which gui's Text would otherwise replace with its
29
+ * body size. */
30
+ const WORD = { fontFamily: 'inherit', fontSize: 'inherit', fontWeight: 'inherit', lineHeight: 'inherit', letterSpacing: 'inherit' };
31
+ const TextLink = ({ href, children, ...p }) => href !== undefined ? ((0, jsx_runtime_1.jsx)(gui_1.Anchor, { ...(0, slot_1.slot)('text-link'), href: href, ...WORD, color: "$ink", textDecorationLine: "underline", style: { textUnderlineOffset: 3 }, ...p, children: children })) : ((0, jsx_runtime_1.jsx)(gui_1.Text, { ...(0, slot_1.slot)('text-link'), render: (0, jsx_runtime_1.jsx)("button", { type: "button" }), p: 0, borderWidth: 0, bg: "transparent", ...WORD, color: "$ink", textDecorationLine: "underline", cursor: "pointer", style: { textUnderlineOffset: 3 }, ...p, children: children }));
26
32
  exports.TextLink = TextLink;
@@ -20,10 +20,12 @@ export type CtaProps = Omit<ComponentProps<typeof Anchor>, 'children' | 'href'>
20
20
  };
21
21
  declare const Cta: ({ href, children, quiet, ...p }: CtaProps) => import("react").JSX.Element;
22
22
  export { Cta };
23
- /**
24
- * TextLink — a link inside a sentence: the surrounding ink, underlined.
25
- * `Cta` is the control; this is the word.
26
- */
27
- declare const TextLink: ({ href, children, ...p }: Omit<CtaProps, 'quiet'>) => import("react").JSX.Element;
23
+ export type TextLinkProps = Omit<CtaProps, 'quiet' | 'href'> & {
24
+ /** Where it goes. Without one it is a button that reads as a link — "try
25
+ * again", "change address" — and `onPress` is what it does. */
26
+ href?: string;
27
+ disabled?: boolean;
28
+ };
29
+ declare const TextLink: ({ href, children, ...p }: TextLinkProps) => import("react").JSX.Element;
28
30
  export { TextLink };
29
31
  //# sourceMappingURL=Cta.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Cta.d.ts","sourceRoot":"","sources":["../../src/marketing/Cta.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItD,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,GAAG;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,SAAS,CAAA;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,QAAA,MAAM,GAAG,oCAA6C,QAAQ,gCAuB7D,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,CAAA;AAEd;;;GAGG;AACH,QAAA,MAAM,QAAQ,6BAA8B,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,gCAWlE,CAAA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"Cta.d.ts","sourceRoot":"","sources":["../../src/marketing/Cta.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAQ,MAAM,YAAY,CAAA;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItD,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC,GAAG;IAChF,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,SAAS,CAAA;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,QAAA,MAAM,GAAG,oCAA6C,QAAQ,gCAuB7D,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,CAAA;AAEd,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;IAC7D;oEACgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAaD,QAAA,MAAM,QAAQ,6BAA8B,aAAa,gCA6BtD,CAAA;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -11,14 +11,20 @@ import { jsx as _jsx } from "react/jsx-runtime";
11
11
  *
12
12
  * The 44px floor is `minH`, not padding, so a two-line label stays balanced.
13
13
  */
14
- import { Anchor } from '@hanzo/gui';
14
+ import { Anchor, Text } from '@hanzo/gui';
15
15
  import { slot } from '../backends/gui/slot.js';
16
16
  const Cta = ({ href, children, quiet = false, ...p }) => (_jsx(Anchor, { ...slot(quiet ? 'cta-quiet' : 'cta'), href: href, display: "inline-flex", items: "center", justify: "center", minH: 44, px: "$5", rounded: "$4", borderWidth: 1, borderColor: quiet ? '$borderColor' : 'transparent', bg: quiet ? 'transparent' : 'var(--primary)', color: quiet ? '$ink' : 'var(--primary-foreground)', fontSize: "$4", fontWeight: "500", text: "center", textDecorationLine: "none", hoverStyle: quiet ? { bg: '$hover' } : { bg: 'var(--primary-hover)' }, ...p, children: children }));
17
17
  export { Cta };
18
18
  /**
19
- * TextLink — a link inside a sentence: the surrounding ink, underlined.
20
- * `Cta` is the control; this is the word.
19
+ * TextLink — a link inside a sentence: full ink and an underline, because in
20
+ * quiet text colour alone does not say "link", and the sentence's own face and
21
+ * size. `Cta` is the control; this is the word. A button inside such a sentence (no `href`) reads as one of its
22
+ * links: no box, and the sentence's own face, which @hanzo/design's base hands
23
+ * every button.
21
24
  */
22
- const TextLink = ({ href, children, ...p }) => (_jsx(Anchor, { ...slot('text-link'), href: href, color: "$ink", textDecorationLine: "underline", style: { textUnderlineOffset: 3 }, ...p, children: children }));
25
+ /** The sentence's own type, which gui's Text would otherwise replace with its
26
+ * body size. */
27
+ const WORD = { fontFamily: 'inherit', fontSize: 'inherit', fontWeight: 'inherit', lineHeight: 'inherit', letterSpacing: 'inherit' };
28
+ const TextLink = ({ href, children, ...p }) => href !== undefined ? (_jsx(Anchor, { ...slot('text-link'), href: href, ...WORD, color: "$ink", textDecorationLine: "underline", style: { textUnderlineOffset: 3 }, ...p, children: children })) : (_jsx(Text, { ...slot('text-link'), render: _jsx("button", { type: "button" }), p: 0, borderWidth: 0, bg: "transparent", ...WORD, color: "$ink", textDecorationLine: "underline", cursor: "pointer", style: { textUnderlineOffset: 3 }, ...p, children: children }));
23
29
  export { TextLink };
24
30
  //# sourceMappingURL=Cta.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Cta.js","sourceRoot":"","sources":["../../src/marketing/Cta.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAGnC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAU3C,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,EAAY,EAAE,EAAE,CAAC,CACjE,KAAC,MAAM,OACD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,EACrC,IAAI,EAAE,IAAI,EACV,OAAO,EAAC,aAAa,EACrB,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAE,EAAE,EACR,EAAE,EAAC,IAAI,EACP,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,EACnD,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,EAC5C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,EACnD,QAAQ,EAAC,IAAI,EACb,UAAU,EAAC,KAAK,EAChB,IAAI,EAAC,QAAQ,EACb,kBAAkB,EAAC,MAAM,EACzB,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,sBAAsB,EAAE,KAChE,CAAY,YAEhB,QAAQ,GACF,CACV,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,CAAA;AAEd;;;GAGG;AACH,MAAM,QAAQ,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,EAA2B,EAAE,EAAE,CAAC,CACtE,KAAC,MAAM,OACD,IAAI,CAAC,WAAW,CAAC,EACrB,IAAI,EAAE,IAAI,EACV,KAAK,EAAC,MAAM,EACZ,kBAAkB,EAAC,WAAW,EAC9B,KAAK,EAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,KAC5B,CAAY,YAEhB,QAAQ,GACF,CACV,CAAA;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA"}
1
+ {"version":3,"file":"Cta.js","sourceRoot":"","sources":["../../src/marketing/Cta.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAIzC,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAU3C,MAAM,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,EAAE,GAAG,CAAC,EAAY,EAAE,EAAE,CAAC,CACjE,KAAC,MAAM,OACD,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,EACrC,IAAI,EAAE,IAAI,EACV,OAAO,EAAC,aAAa,EACrB,KAAK,EAAC,QAAQ,EACd,OAAO,EAAC,QAAQ,EAChB,IAAI,EAAE,EAAE,EACR,EAAE,EAAC,IAAI,EACP,OAAO,EAAC,IAAI,EACZ,WAAW,EAAE,CAAC,EACd,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,aAAa,EACnD,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAgB,EAC5C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,EACnD,QAAQ,EAAC,IAAI,EACb,UAAU,EAAC,KAAK,EAChB,IAAI,EAAC,QAAQ,EACb,kBAAkB,EAAC,MAAM,EACzB,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,sBAAsB,EAAE,KAChE,CAAY,YAEhB,QAAQ,GACF,CACV,CAAA;AAED,OAAO,EAAE,GAAG,EAAE,CAAA;AASd;;;;;;GAMG;AACH;iBACiB;AACjB,MAAM,IAAI,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAW,CAAA;AAE5I,MAAM,QAAQ,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAiB,EAAE,EAAE,CAC3D,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACnB,KAAC,MAAM,OACD,IAAI,CAAC,WAAW,CAAC,EACrB,IAAI,EAAE,IAAI,KACL,IAAe,EACpB,KAAK,EAAC,MAAM,EACZ,kBAAkB,EAAC,WAAW,EAC9B,KAAK,EAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,KAC5B,CAAY,YAEhB,QAAQ,GACF,CACV,CAAC,CAAC,CAAC,CACF,KAAC,IAAI,OACC,IAAI,CAAC,WAAW,CAAC,EACrB,MAAM,EAAE,iBAAQ,IAAI,EAAC,QAAQ,GAAG,EAChC,CAAC,EAAE,CAAC,EACJ,WAAW,EAAE,CAAC,EACd,EAAE,EAAC,aAAa,KACX,IAAe,EACpB,KAAK,EAAC,MAAM,EACZ,kBAAkB,EAAC,WAAW,EAC9B,MAAM,EAAC,SAAS,EAChB,KAAK,EAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,KAC5B,CAAY,YAEhB,QAAQ,GACJ,CACR,CAAA;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAA"}
@@ -0,0 +1,112 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.More = exports.Chip = exports.Action = void 0;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * The three controls a marketing page closes a thought with, one set:
8
+ *
9
+ * Action the button — chrome glass, or `fill` for the one loud control
10
+ * Chip a word in an outline: a badge, a tag, a filter
11
+ * More the quiet link — "View all →", "See full pricing ↗"
12
+ *
13
+ * Each is a gui Text, so it carries its own type and draws its own box: the
14
+ * label and any icon beside it inherit the ink, and nothing reaches in from a
15
+ * stylesheet. White space is the parent's, so a control inside a line that
16
+ * clips with an ellipsis stays on that line. An `href` makes it a link: an internal one goes through the app's
17
+ * router link (@hanzo/ui's `Link` context, set once at the root), any other is
18
+ * an anchor. A control that does something passes `render="button"`.
19
+ *
20
+ * The ease between rest and hover is @hanzo/design's base, which grants every
21
+ * `<a>` and `<button>` its colour, fill, edge and shadow transition, and the
22
+ * pointer (or `not-allowed` on a disabled button); a control restates none of it.
23
+ *
24
+ * Both themes are props. On the light ground the dark glass would draw a grey
25
+ * slab and the white fill would vanish into the page, so `$theme-light` turns
26
+ * the quiet weight to white glass with a dark edge and the loud one to ink.
27
+ */
28
+ const gui_1 = require("@hanzo/gui");
29
+ const slot_1 = require("../backends/gui/slot.cjs");
30
+ const host_1 = require("./host.cjs");
31
+ const BOX = {
32
+ display: 'inline-flex',
33
+ items: 'center',
34
+ whiteSpace: 'inherit',
35
+ textDecorationLine: 'none',
36
+ };
37
+ /** A rung that carries its own leading: naming the size alone leaves the line
38
+ * box to whatever an ancestor sets. */
39
+ const SMALL = { fontSize: '$2', lineHeight: 'calc(1.25 / 0.875)' };
40
+ /**
41
+ * A caller's own value holds in every state, the way a value stated on the
42
+ * element always has: a key the caller passes is dropped from the hover and from
43
+ * the light theme, so `color` on a chip stays that colour under the pointer and
44
+ * on the light ground. A caller's own `hoverStyle` or `$theme-light` replaces
45
+ * the default whole.
46
+ */
47
+ const states = (p, hover, light) => {
48
+ const own = (s) => Object.fromEntries(Object.entries(s).filter(([k]) => !(k in p)));
49
+ const { hoverStyle: lightHover, ...lightRest } = light;
50
+ return {
51
+ ...(p.hoverStyle === undefined ? { hoverStyle: own(hover) } : null),
52
+ ...(p['$theme-light'] === undefined
53
+ ? { '$theme-light': { ...own(lightRest), ...(lightHover && p.hoverStyle === undefined ? { hoverStyle: own(lightHover) } : null) } }
54
+ : null),
55
+ };
56
+ };
57
+ /** The quiet weight is chrome glass; `fill` drops the border outright rather
58
+ * than making it transparent, which would leave the loud control 2px wider
59
+ * than the quiet one beside it. 44px is the thumb floor, not a style. */
60
+ const Action = ({ render, fill = false, ...p }) => {
61
+ const host = (0, host_1.useHost)(render, p.href, 'a');
62
+ return ((0, jsx_runtime_1.jsx)(gui_1.Text, { ...(0, slot_1.slot)('action'), ...(fill ? { 'data-fill': '' } : null), render: host, ...BOX, ...SMALL, justify: "center", gap: "$2", minH: 44, px: "$5", rounded: 9999, fontWeight: "500", backdropFilter: "var(--chrome-blur)", ...(fill
63
+ ? {
64
+ borderWidth: 0,
65
+ bg: 'var(--pure-white)',
66
+ color: 'var(--pure-black)',
67
+ boxShadow: '0 4px 20px -2px var(--white-22), 0 2px 8px 0 color-mix(in srgb, var(--pure-black) 40%, transparent)',
68
+ ...states(p, { opacity: 0.92, bg: 'var(--neutral-100)', color: 'var(--pure-black)' }, {
69
+ bg: 'var(--foreground)',
70
+ color: 'var(--background)',
71
+ boxShadow: '0 4px 16px -6px color-mix(in srgb, var(--pure-black) 40%, transparent)',
72
+ hoverStyle: { bg: 'var(--foreground)', color: 'var(--background)' },
73
+ }),
74
+ }
75
+ : {
76
+ borderWidth: 1,
77
+ borderStyle: 'solid',
78
+ borderColor: 'var(--white-14)',
79
+ bg: 'color-mix(in srgb, var(--neutral-900) 65%, transparent)',
80
+ color: 'var(--foreground)',
81
+ boxShadow: 'inset 0 1px 0 0 var(--white-14), 0 4px 16px -2px color-mix(in srgb, var(--pure-black) 30%, transparent)',
82
+ ...states(p, { bg: 'color-mix(in srgb, var(--neutral-800) 80%, transparent)', borderColor: 'var(--white-22)', color: 'var(--pure-white)' }, {
83
+ borderColor: 'color-mix(in srgb, var(--pure-black) 14%, transparent)',
84
+ bg: 'color-mix(in srgb, var(--pure-white) 72%, transparent)',
85
+ color: 'var(--foreground)',
86
+ boxShadow: '0 2px 10px -4px color-mix(in srgb, var(--pure-black) 18%, transparent)',
87
+ hoverStyle: { borderColor: 'color-mix(in srgb, var(--pure-black) 26%, transparent)', bg: 'var(--pure-white)', color: 'var(--foreground)' },
88
+ }),
89
+ }), ...p }));
90
+ };
91
+ exports.Action = Action;
92
+ /** A word in an outline. Not an action — no fill, no weight — so the padding is
93
+ * the caller's: a chip and a badge are the same outline at two sizes. It
94
+ * brightens on approach only when it is a link. */
95
+ const Chip = ({ render, ...p }) => {
96
+ const host = (0, host_1.useHost)(render, p.href, 'span');
97
+ const link = (0, host_1.address)(host, p.href);
98
+ return ((0, jsx_runtime_1.jsx)(gui_1.Text, { ...(0, slot_1.slot)('chip'), render: host, ...BOX, ...SMALL, gap: "$2", borderWidth: 1, borderStyle: "solid", borderColor: "var(--white-08)", rounded: 9999, color: "var(--neutral-300)", bg: "var(--white-03)", ...states(p, link ? { borderColor: 'var(--white-20)', color: 'var(--pure-white)' } : {}, {
99
+ borderColor: 'var(--border)',
100
+ bg: 'var(--glass)',
101
+ color: 'var(--muted-foreground)',
102
+ ...(link ? { hoverStyle: { borderColor: 'var(--border-strong)', color: 'var(--foreground)' } } : null),
103
+ }), ...p }));
104
+ };
105
+ exports.Chip = Chip;
106
+ /** The quiet link. The hover is the reason it is a component rather than a
107
+ * colour at the call site. */
108
+ const More = ({ render, ...p }) => {
109
+ const host = (0, host_1.useHost)(render, p.href, 'a');
110
+ return ((0, jsx_runtime_1.jsx)(gui_1.Text, { ...(0, slot_1.slot)('more'), render: host, ...BOX, ...SMALL, gap: "$2", fontWeight: "500", color: "var(--neutral-300)", ...states(p, { color: 'var(--pure-white)' }, { color: 'var(--muted-foreground)', hoverStyle: { color: 'var(--foreground)' } }), ...p }));
111
+ };
112
+ exports.More = More;